data.table简介

data.table是R中一个强大的数据处理包,提供快速的数据分片、分组和聚合功能,比base R快约10倍。主要函数包括:`fread()`用于快速读取数据,`[ ]`操作符进行便捷的子集选择,`setkey()`用于设置键以加速查询。此外,`merge()`实现快速融合数据,`duplicated()`和`unique()`处理重复值。参考文档包括Introduction、FAQs、重塑和键的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

data.table是一个十分有效的数据处理包,它是data.frame的一个扩展,能够快速的对数据进行分片,分组,聚合等操作,比data.frame快很多。在数据处理方面,据实验结果表明,对于2G的数据,tapply耗时16秒,而data.table耗时1.6秒,快了10倍,官方还介绍说,对于100G的数据,它还能运行很好。
下面介绍几个主要用到的函数:

fread

read.table相似,但是更快更方便

fread(input, sep="auto", sep2="auto", nrows=-1L, header="auto", na.strings="NA", file,
stringsAsFactors=FALSE, verbose=getOption("datatable.verbose"), autostart=1L,
skip=0L, select=NULL, drop=NULL, colClasses=NULL,
integer64=getOption("datatable.integer64"), # default: "integer64"
dec=if (sep!=".") "." else ",", col.names,
check.names=FALSE, encoding="unknown", quote="\"",
strip.white=TRUE, fill=FALSE, blank.lines.skip=FALSE, key=NULL,
showProgress=getOption("datatable.showProgress"), # default: TRUE
data.table=getOption("datatable.fread.datatable") # default: TRUE
)

主要参数:
input:输入的文件,也可以是一个URL
sep:列的分隔符,默认的是符号集[,\t |;:]中的第一个
nrows:要读取的行数,默认为-1为全部
header:第一行是否为列名
stringAsFactors:是否把字符串的列转化为因子向量
skipskip>0意味着开始于第skip+1
select:选择要留下的列向量,丢弃剩下的
drop:和seelct相反
colClasses:设定列的类型,一个向量或一个列表
key:传递到setkey的列名的字符向量,像key="x,y,z"key=c("x","y","z"),只有当data.table=TRUE时才有效
data.table:TRUE时返回一个data.table,FALSE时返回一个data.frame

n=1e7
DT = data.table( a=sample(1:1000,n,replace=TRUE),
b=sample(1:1000,n,replace=TRUE),
c=rnorm(n),
d=sample(c("foo","bar","baz","qux","quux"),n,replace=TRUE),
e=rnorm(n),
f=sample(1:1000,n,replace=TRUE) )

 fwrite(DT,"DT.csv",row.names = F)

写入的数据507M。下面试一试freadread.csvread_csv的读入时间。

system.time(DT <- fread("DT.csv",header=F))

Read 10000001 rows and 6 (of 6) columns from 0.495 GB file in 00:02:01
  用户   系统   流逝 
118.44   1.83 121.09 

system.time(dt <- read.csv("DT.csv",header=F))
   用户    系统    流逝 
1436.48    6.53 1454.64

library(readr)
system.time(dt <- read_csv("DT.csv"))
 用户  系统  流逝 
19.67  0.58 22.26 

这儿有些奇怪,用readr包里的read_csv竟然比fread要快,我又试了几次,fread几次读取时间差别都很大,在读取到80%之前,几乎每秒读取20%,但是在80%上卡了,最后平均用时40多秒。

fsort

fsort(x, decreasing = FALSE, na.last = FALSE, internal=FALSE, verbose=FALSE, ...)

参数:
x:向量
decreasing:是否是降序排列
na.last:对NA的控制,如果TRUE,则数据中的缺失值放到最后,如果FALSE,放在最前,如果是NA,则去除。

 x = runif(1e7)
system.time(ans1 <- sort(x,method="quick"))
用户 系统 流逝 
2.53 0.10 2.62 

system.time(ans2 <- fsort(x))
用户 系统 流逝 
0.78 0.19 0.35 

duplicated

duplicated(x, incomparables=FALSE, fromLast=FALSE, by=seq_along(x), ...)

unique(x, incomparables=FALSE, fromLast=FALSE, by=seq_along(x), ...)

参数:
x:一个data.table
fromLast:保留所有重复的最后一个
by:字符或整数向量,指示在x中和哪些列的组合为唯一值
na.rm:默认FALSE,缺失值是否要移除

DT <- data.table(A = rep(1:3, each=4), B = rep(1:4, each=3),
C = rep(1:2, 6), key = "A,B")
duplicated(DT)
[1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

unique(DT)
    A B C
 1: 1 1 1
 2: 1 1 2
 3: 1 2 2
 4: 2 2 1
 5: 2 2 2
 6: 2 3 1
 7: 2 3 2
 8: 3 3 1
 9: 3 4 2
10: 3 4 1

duplicated(DT,by=c("A","C"))
 [1] FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE

unique(DT, by=c("A", "C"))
   A B C
1: 1 1 1
2: 1 1 2
3: 2 2 1
4: 2 2 2
5: 3 3 1
6: 3 4 2

firstlast

first(x, ...)
last(x, ...)

返回第一个值
参数:
x:一个向量,列表,data.frame或data.table

x = data.table(x=1:5, y=6:10)
first(x)
   x y
1: 1 6

last(x)
   x  y
1: 5 10

和x[1]一样,但是这儿注意,此时的x[1]和用data.frame生成的x[1]是不一样的,用data.table生成的x,x[1]取的是行,而data.rame生成的x,x[1]取的是列。

like

like(vector,pattern)
vector %like% pattern

调用正则表达式
参数:
vector:字符向量或因子,因子更快
pattern:传递到grepl

DT = data.table(Name=c("Mary","George","Martha"), Salary=c(2,3,4))
 DT
     Name Salary
1:   Mary      2
2: George      3
3: Martha      4

DT[Name %like% "^Mar"]
     Name Salary
1:   Mary      2
2: Martha      4

DT[like(Name,"^Mar")]
     Name Salary
1:   Mary      2
2: Martha      4

melt

melt(data, id.vars, measure.vars,
variable.name = "variable", value.name = "value",
..., na.rm = FALSE, variable.factor = TRUE,
value.factor = FALSE,
verbose = getOption("datatable.verbose"))

参数:
data:一个要融合的data.table
id.vars:id变量向量
measure.vars:度量变量向量
variable.name:度量变量的名称
value.name:融合后数据值的名称

DT <- data.table(
i_1 = c(1:5, NA),
i_2 = c(NA,6,7,8,9,10),
f_1 = factor(sample(c(letters[1:3], NA), 6, TRUE)),
f_2 = factor(c("z", "a", "x", "c", "x", "x"), ordered=TRUE),
c_1 = sample(c(letters[1:3], NA), 6, TRUE),
d_1 = as.Date(c(1:3,NA,4:5), origin="2013-09-01"),
d_2 = as.Date(6:1, origin="2012-01-01"))

 DT
   i_1 i_2 f_1 f_2 c_1        d_1        d_2
1:   1  NA   a   z   a 2013-09-02 2012-01-07
2:   2   6   b   a   a 2013-09-03 2012-01-06
3:   3   7   b   x   a 2013-09-04 2012-01-05
4:   4   8   b   c   b       <NA> 2012-01-04
5:   5   9  NA   x   a 2013-09-05 2012-01-03
6:  NA  10   a   x   b 2013-09-06 2012-01-02

melt(DT,id=1:2,measure="f_1")
   i_1 i_2 variable value
1:   1  NA      f_1     a
2:   2   6      f_1     b
3:   3   7      f_1     b
4:   4   8      f_1     b
5:   5   9      f_1    NA
6:  NA  10      f_1     a

melt(DT,id=c("i_1","i_2"),measure=3)##same as above
   i_1 i_2 variable value
1:   1  NA      f_1     a
2:   2   6      f_1     b
3:   3   7      f_1     b
4:   4   8      f_1     b
5:   5   9      f_1    NA
6:  NA  10      f_1     a

melt(DT, id=1:2, measure=patterns("^f_", "^d_"), value.factor=TRUE)
    i_1 i_2 variable value1     value2
 1:   1  NA        1      a 2013-09-02
 2:   2   6        1      b 2013-09-03
 3:   3   7        1      b 2013-09-04
 4:   4   8        1      b       <NA>
 5:   5   9        1     NA 2013-09-05
 6:  NA  10        1      a 2013-09-06
 7:   1  NA        2      z 2012-01-07
 8:   2   6        2      a 2012-01-06
 9:   3   7        2      x 2012-01-05
10:   4   8        2      c 2012-01-04
11:   5   9        2      x 2012-01-03
12:  NA  10        2      x 2012-01-02

merge

快速融合,默认的,它试图融合

  • 首先依据共有的键,如果没有,那么
  • 依据第一个参数x的键,如果没有,那么
  • 依据两个data.table中相同的列
merge(x, y, by = NULL, by.x = NULL, by.y = NULL,
all = FALSE, all.x = all, all.y = all, sort = TRUE, suffixes = c(".x", ".y"),
allow.cartesian=getOption("datatable.allow.cartesian"), # default FALSE
...)

x,y:为data.table
by:在x,y中要融合的共享的列名向量
by.x, by.yx,y中要融合的列名向量
allall.x=TRUE,all.y=TRUE的简写
all.x:逻辑值,如果TRUE,额外的行将会加入到输出列,默认为FALSE,即只有在y,x中都有的数据才被输出
all.y:上同
sort:逻辑值,如果为TRUE,融合后的数据会根据键排序,如果FALSE,不排序。

(dt1 <- data.table(A = letters[1:10], X = 1:10, key = "A"))
    A  X
 1: a  1
 2: b  2
 3: c  3
 4: d  4
 5: e  5
 6: f  6
 7: g  7
 8: h  8
 9: i  9
10: j 10

(dt2 <- data.table(A = letters[5:14], Y = 1:10, key = "A"))
    A  Y
 1: e  1
 2: f  2
 3: g  3
 4: h  4
 5: i  5
 6: j  6
 7: k  7
 8: l  8
 9: m  9
10: n 10

merge(dt1, dt2)
   A  X Y
1: e  5 1
2: f  6 2
3: g  7 3
4: h  8 4
5: i  9 5
6: j 10 6

merge(dt1, dt2, all = TRUE)
    A  X  Y
 1: a  1 NA
 2: b  2 NA
 3: c  3 NA
 4: d  4 NA
 5: e  5  1
 6: f  6  2
 7: g  7  3
 8: h  8  4
 9: i  9  5
10: j 10  6
11: k NA  7
12: l NA  8
13: m NA  9
14: n NA 10

set.seed(1L)
d1 <- data.table(a=sample(rep(1:3,each=2)), z=1:6)
d2 <- data.table(a=2:0, z=10:12)

d1
   a z
1: 1 1
2: 3 2
3: 2 3
4: 2 4
5: 1 5
6: 3 6
d2
   a  z
1: 2 10
2: 1 11
3: 0 12

merge(d1,d2,by="a")
   a z.x z.y
1: 1   1  11
2: 1   5  11
3: 2   3  10
4: 2   4  10

merge(d1,d2,by="a",all=T)
   a z.x z.y
1: 0  NA  12
2: 1   1  11
3: 1   5  11
4: 2   3  10
5: 2   4  10
6: 3   2  NA
7: 3   6  NA

setnames(d2, "a", "b")

d2
   b  z
1: 2 10
2: 1 11
3: 0 12

merge(d1, d2, by.x="a", by.y="b")
   a z.x z.y
1: 1   1  11
2: 1   5  11
3: 2   3  10
4: 2   4  10

merge(d1, d2, by.x="a", by.y="b", all=TRUE)
   a z.x z.y
1: 0  NA  12
2: 1   1  11
3: 1   5  11
4: 2   3  10
5: 2   4  10
6: 3   2  NA
7: 3   6  NA

merge(d2, d1, by.x="b", by.y="a")
   b z.x z.y
1: 1  11   1
2: 1  11   5
3: 2  10   3
4: 2  10   4

一些介绍data.table的文章

  1. 对数据的一些简单的处理,请看Introduction to data.table

  2. 常见的一些问题,请看Frequently Asked Questions about data.table

  3. 数据的重塑,请看Efficient reshaping using data.tables

  4. 设置键而二值搜索,请看Keys and fast binary search based subset

  5. 参考语义,请看Reference semantics
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值