data.table包主要特色是:设置keys、快速分组和滚得时序的快速合并。data.table主要通过二元检索法大大提高数据操作的效率,同时它也兼容适用于data.frame的向量检索法。

require(data.table)
## Loading required package: data.table

1.创建data.table格式数据

类似于data.frame数据的创建,使用data.table函数

(DF = data.frame(x=c("b","b","b","a","a"), v=rnorm(5)))
##   x       v
## 1 b -0.8870
## 2 b 1.6066
## 3 b -0.1895
## 4 a 0.2375
## 5 a 1.0084
(DT = data.table(x=c("b","b","b","a","a"), v=rnorm(5)))
##    x       v
## 1: b -1.8458
## 2: b -0.2212
## 3: b -0.5812
## 4: a 0.2949
## 5: a 1.7858

可以看出,DF和DT的行号有一些区别,这也是data.frame和data.table主要区别。我们可以利用data.frame创建data.table:

CARS = data.table(cars)
head(CARS)
##    speed dist
## 1: 4 2
## 2: 4 10
## 3: 7 4
## 4: 7 22
## 5: 8 16
## 6: 9 10

现在我们已经创建了两个data.table数据,tables命令可以显示该信息:

tables()
##      NAME NROW MB COLS       KEY
## [1,] CARS 50 1 speed,dist
## [2,] DT 5 1 x,v
## Total: 2MB

其中"MB"列可以快速评估内存使用,发现删除可以释放内存的表格。

如果要查看表中数据类型可以使用

sapply(DT, class)
##           x           v
## "character" "numeric"

2.键Keys

类似人的姓名有“姓”和“名”组成,data.table中的Keys可以由多个部分组成,Keys的组成部分可以使整数、因子、字符串或其他格式,而且data.table中的每行数据是按照Keys排序的,所以data.table数据最多只有一个Key.

DT和CARS是data.table格式,当前没有设置任何Keys,我们可以使用适用于数据框data.frame的语法:

DT[2, ]
##    x       v
## 1: b -0.2212
DT[DT$x=="b", ]
##    x       v
## 1: b -1.8458
## 2: b -0.2212
## 3: b -0.5812

由于DT没有行名称,所以下面的命令不能正常运行:

cat(try(DT["b", ], silent=TRUE))
## Error in `[.data.table`(DT, "b", ) :
## When i is a data.table (or character vector), x must be keyed (i.e. sorted, and, marked as sorted) so data.table knows which columns to join to and take advantage of x being sorted. Call setkey(x,...) first, see ?setkey.

报错信息显示,我们需要对data.table数据设置keys:

setkey(DT, x)
DT
##    x       v
## 1: a 0.2949
## 2: a 1.7858
## 3: b -1.8458
## 4: b -0.2212
## 5: b -0.5812

此时,DT已经按照x值进行了重新排序,如果要确认一个data.table数据是否有keys,我们可以使用haskey()、key()、attributes()或者tables()函数。

tables()
##      NAME NROW MB COLS       KEY
## [1,] CARS 50 1 speed,dist
## [2,] DT 5 1 x,v x
## Total: 2MB

现在,DT数据已经拥有Key:x,我们尝试列出所有x=b的数据

DT["b", ]
##    x       v
## 1: b -1.8458
## 2: b -0.2212
## 3: b -0.5812

使用mult可以筛选出每组数据的第一个观测值和最后一个观测值

DT["b", mult="first"]
##    x      v
## 1: b -1.846
DT["b", mult="last"]
##    x       v
## 1: b -0.5812

下面创建一个足够大的数据来说明“向量检索法”和“二元检索法”的效率差异。

#10000068行,676个分组的数据DF
grpsize = ceiling(1e7/26^2)
tt=system.time( DF <- data.frame(
x=rep(LETTERS,each=26*grpsize),
y=rep(letters,each=grpsize),
v=runif(grpsize*26^2),
stringsAsFactors=FALSE)
)
tt
##    user  system elapsed
## 1.56 0.05 1.60
head(DF, 3)
##   x y       v
## 1 A a 0.08119
## 2 A a 0.64764
## 3 A a 0.80780
tail(DF, 3)
##          x y       v
## 10000066 Z z 0.65856
## 10000067 Z z 0.01941
## 10000068 Z z 0.88818
dim(DF)
## [1] 10000068        3

下面我们从DF中剥离其中任意一组

#'向量检索法'
(tt=system.time(ans1 <- DF[DF$x=="R" & DF$y=="h",]))
##    user  system elapsed
## 2.92 0.14 3.06
head(ans1, 3);dim(ans1)
##         x y       v
## 6642058 R h 0.90416
## 6642059 R h 0.86002
## 6642060 R h 0.02253
## [1] 14793     3
#'二元检索法'
DT = as.data.table(DF)
system.time(setkey(DT,x,y))#一次性遍历所有元素时间
##    user  system elapsed
## 0.26 0.04 0.31
(ss=system.time(ans2 <- DT[J("R","h")]))#二元条件检索
##    user  system elapsed
## 0.01 0.00 0.01
head(ans2, 3);dim(ans2)
##    x y       v
## 1: R h 0.90416
## 2: R h 0.86002
## 3: R h 0.02253
## [1] 14793     3
identical(ans1$v, ans2$v)
## [1] TRUE

可以看出使用二元检索法较向量检索法,效率上要高很多。

当然,data.table也支持向量检索,但这样的话效率会低很多,我们应尽量避免这种情况。例如:

system.time(ans1 <- DT[x=="R" & y=="h",])#低效的data.table用法
##    user  system elapsed
## 2.41 0.08 2.49
system.time(ans2 <- DF[DF$x=="R" & DF$y=="h",])#data.frame用法
##    user  system elapsed
## 4.59 0.20 4.89
mapply(identical,ans1,ans2)
##    x    y    v
## TRUE TRUE TRUE

上例中,当使用DT$x==“R"时候,就会使用”向量检索法“遍历数据的整列,y=="h"同样,最后再使用”&“合并两个条件。data.table包提供了J()函数用于数据合并,可以大大提高效率。

identical( DT[J("R","h"), ], DT[data.table("R","h"), ])
## [1] TRUE

3.快速分组

对于data.table,使用”[i, j]“进行二元检索,我们可以接"by"进行分组计算

DT[, sum(v), by=x]
##     x     V1
## 1: A 192333
## 2: B 192379
## 3: C 192299
## 4: D 192062
## 5: E 192653
## 6: F 192099
## 7: G 192296
## 8: H 192402
## 9: I 192396
## 10: J 192262
## 11: K 192200
## 12: L 192308
## 13: M 192475
## 14: N 192103
## 15: O 192423
## 16: P 192341
## 17: Q 192340
## 18: R 192135
## 19: S 192233
## 20: T 192492
## 21: U 192434
## 22: V 191940
## 23: W 192353
## 24: X 192466
## 25: Y 192206
## 26: Z 192385
## x V1

该种方法相当高效,下面我们将其与tapply函数进行对比

ttt=system.time(tt <- tapply(DT$v,DT$x,sum)); ttt
##    user  system elapsed
## 3.15 0.48 3.67
sss=system.time(ss <- DT[,sum(v),by=x]); sss
##    user  system elapsed
## 0.34 0.00 0.34
head(tt);head(ss)
##      A      B      C      D      E      F
## 192333 192379 192299 192062 192653 192099
##    x     V1
## 1: A 192333
## 2: B 192379
## 3: C 192299
## 4: D 192062
## 5: E 192653
## 6: F 192099
identical(as.vector(tt), ss$V1)
## [1] TRUE

下面我们按两列进行分组,比较两种方法的效率

ttt=system.time(tt <- tapply(DT$v,list(DT$x,DT$y),sum)); ttt
##    user  system elapsed
## 5.64 0.63 6.36
sss=system.time(ss <- DT[,sum(v),by="x,y"]); sss
##    user  system elapsed
## 0.35 0.00 0.34
tt[1:5,1:5]
##      a    b    c    d    e
## A 7507 7417 7360 7383 7399
## B 7449 7453 7405 7374 7384
## C 7412 7388 7375 7442 7388
## D 7430 7387 7418 7338 7433
## E 7387 7464 7440 7434 7464
head(ss)
##    x y   V1
## 1: A a 7507
## 2: A b 7417
## 3: A c 7360
## 4: A d 7383
## 5: A e 7399
## 6: A f 7413
identical(as.vector(t(tt)), ss$V1)
## [1] TRUE

4.其他

关于data.table的更多信息参见:https://github.com/Rdatatable/data.table

----------------------------------------------------------------------------------------

  • 简介 
    data.table继承于data.frame。它提供了一个快速通道,让我们能更加快速的读取文件,对数据进行筛选、分组、排序、联表,而且其语法灵活、简介。由于data.table是一个data.frame所以它几乎兼容所有的函数。

  • 特点

    1. data.table(DT)的操作语句类似于SQL,DT[i, j, by]中的i, j, by 对应着SQL语句的 i=where, j=select, by=group by。所以DT中的i, j并不是只是像data.frame只代表着行列,它更加的灵活多变。
    2. 符号 ” := “快速的增加或者删除列,类似SQL的update。
    3. setkey(DT, colA, colB),可以使得检索和分组更加快速
    4. order,快速多重排序, 例如对DT按照x,y进行排序DT[order(DT$x, -DT$y),]或者DT[with(DT, order(x, -y)),]
  • compare 
    包括使用DT使用Key后与DF的检索速度对比。 
    快速分组(需要设置KEY),进行计算,和使用tapply分组计算速度

###生成数据
grpsize <- ceiling(1e7/26^2) ##10^7 rows, 676 groups
DF <- data.frame(x=rep(LETTERS,each=26*grpsize),
y=rep(letters,each=grpsize), v=runif(grpsize*26^2),
stringsAsFactors=FALSE)
head(DF,3)
x y v
1 A a 0.5310106
2 A a 0.1980941
3 A a 0.8835322 DT <- as.data.table(DF) ##creat data.table
setkey(DT,x,y) #s et the key
##################################################
#比较检索速度,搜索x=="R",y="h"
system.time(ans1 <- DF[DF$x=="R" & DF$y=="h",]) #vector scan
user system elapsed
0.528 0.016 0.544
system.time(ans2 <- DT[list("R","h")]) # binary search
user system elapsed
0.004 0.000 0.001 ####################################################
###快速分组,按照x分组,然后计算sum(v)
#tapply
system.time(tt <- tapply(DT$v,DT$x,sum))
user system elapsed
0.704 0.064 0.767
#syntax of data.table
system.time(ss <- DT[,sum(v),by=x])
user system elapsed
0.080 0.000 0.078
#cheak ss and tt
head(ss)
x V1
1: A 192213.2
2: B 192183.3
3: C 192601.7
4: D 192308.0
5: E 192428.5
6: F 192071.0
head(tt)
A B C D E F
192213.2 192183.3 192601.7 192308.0 192428.5 192071.0
  • 其他基本操作 
    联表和统计计算,更清晰认知,DT[i, j, by]中的i, j, by 对应着SQL语句的 i=where, j=select, by=group by。
###Data preparation
DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9) ##creat data.table DT
X = data.table(c("b","c"),foo=c(4,2)) ##use to join
setkey(DT,x) #set the key
########################cheak the data#######
DT
x y v
1: a 1 1
2: a 3 2
3: a 6 3
4: b 1 4
5: b 3 5
6: b 6 6
7: c 1 7
8: c 3 8
9: c 6 9 X
V1 foo
1: b 4
2: c 2
#################联表,注key1联的另一个表的第一列#################
##join类型1,联表,X中有b,c
DT[X] ##join X,by the key x.
x y v foo
1: b 1 4 4
2: b 3 5 4
3: b 6 6 4
4: c 1 7 2
5: c 3 8 2
6: c 6 9 2
##join类型2,类似查询,.() 表示list,类似于联一个1行2列的表
DT[.("a",3)]
x y v V2
1: a 1 1 3
2: a 3 2 3
3: a 6 3 3
#############################计算建表#############
#where=DT, select=sum(v)....., group by DT$x
DT[,list(MySum=sum(v),
MyMin=min(v),
MyMax=max(v)),
by=.(x)]
x MySum MyMin MyMax
1: a 6 1 3
2: b 15 4 6
3: c 24 7 9

data.table包简介的更多相关文章

  1. R︱高效数据操作——data.table包(实战心得、dplyr对比、key灵活用法、数据合并)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 由于业务中接触的数据量很大,于是不得不转战开始 ...

  2. R语言数据分析利器data.table包 —— 数据框结构处理精讲

        R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代码简洁,只要一行命令就可以完成诸多任务,另一方面是处理 ...

  3. 使用 data.table 包操作数据

    在第一节中,我们回顾了许多用于操作数据框的内置函数.然后,了解了 sqldf 扩展包,它使得简单的数据查询和统计变得更简便.然而,两种方法都有各自的局限性.使用内置函数可能既繁琐又缓慢,而相对于各式各 ...

  4. R语言data.table包fread读取数据

    R语言处理大规模数据速度不算快,通过安装其他包比如data.table可以提升读取处理速度. 案例,分别用read.csv和data.table包的fread函数读取一个1.67万行.230列的表格数 ...

  5. R语言数据分析利器data.table包—数据框结构处理精讲

    R语言数据分析利器data.table包-数据框结构处理精讲 R语言data.table包是自带包data.frame的升级版,用于数据框格式数据的处理,最大的特点快.包括两个方面,一方面是写的快,代 ...

  6. data.table包

    data.table 1.生成一个data.table对象 生成一个data.table对象,记为DT. library(data.table) :],V3=round(rnorm(),),V4=:) ...

  7. data.table包使用应该注意的一些细节

    fread中nThread 参数的使用   注意默认nThread=getDTthreads(),即使用所有能用的核心,但并不是核心用的越多越好,本人亲自测试的情况下,其实单核具有较强的性能,只有在数 ...

  8. R读取大数据data.table包之fread

    >library(data.table)>data=fread("10000000.txt")>Read 9999999 rows and 71 (of 71) ...

  9. R语言学习笔记(十七):data.table包中melt与dcast函数的使用

    melt函数可以将宽数据转化为长数据 dcast函数可以将长数据转化为宽数据 > DT = fread("melt_default.csv") > DT family_ ...

随机推荐

  1. java代码开发完成后,代码走查规范

    代码走查注意事项: 1.不变的值,尽量写个常量类 2.尽量使用if{}else,不要一直if去判断 3.减少循环调用方法查询数据库 4.dao层尽量不要用逻辑,尽量在service里写业务逻辑 5.金 ...

  2. 利用jackson-databind,复杂对象对象和json数据互转

    如果简单对象,那么转换的方式比较多,这里指的复杂对象,是指对象里面存在cycle引用,比如: /** * @author ding * */@Entity@Table(name = "ser ...

  3. yeoman 使用问题总结

    1.今天尝试使用yeoman,执行grunt server 时报错: cannot find where you keep your bower packges 需要将bower npm instal ...

  4. React服务器渲染最佳实践

    源码地址:https://github.com/skyFi/dva-starter React服务器渲染最佳实践 dva-starter 完美使用 dva react react-router,最好用 ...

  5. linux网口绑定笔记-bind

    模式0:balance-rr 模式1:active-backup 模式2:balance-xor 模式3:broadcast 模式4:802.3ad 模式5:balance-tlb 模式6:balan ...

  6. JS中的循环嵌套 BOM函数

    [嵌套循环特点]                           外层循环转一次,内层循环转一圈              外层循环控制行数,内层循环控制每行元素个数             [做 ...

  7. 关于Java中继承多接口同名方法的问题

    在Java中如果一个类同时继承接口A与B,并且这两个接口中具有同名方法,会怎么样? 动手做实验: interface A{ void fun(); } interface B{ void fun(); ...

  8. python基本数据类型——dict

    一.创建字典: d = { "name": "morra", #字典是无序的 "age": 99, "gender": ...

  9. 03(1) Gaussians,GMMs基础

    1.单成分单变量高斯模型 2.单成分多变量高斯模型 若协方差矩阵为对角矩阵且对角线上值相等,两变量高斯分布的等值线为圆形 若协方差矩阵为对角矩阵且对角线上值不等,两变量高斯分布的等值线为椭圆形, 长轴 ...

  10. bzoj4785 [Zjoi2017]树状数组

    Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进 ...