data.table包含的东西很多
但是很多东西都可以被plyr, dplyr的function取代
所以data.table很多function,我都不太熟
这里简单介绍一下data.table
如果你想要了解更多,请自行去看manual
要了解data.table,我们可以先从package的description来看
"Fast aggregation of large data (e.g. 100GB in RAM), fast ordered joins,
fast add/modify/delete of columns by group using no copies at all, list
columns and a fast file reader (fread). Offers a natural and flexible syntax,
for faster development."
简单翻译一下,大资料(例如,内存中大小为100GB的资料)的在不创建复本下,根据
类别(group)变量进行快速整合、排列、合并、增加/修改/删除行资料等动作。...
重点就在不创建复本,因为R修改data.frame时,会先复制一次再修改,
然后传回复本,因此,会浪费不少内存,而且很容易拖累速度,因此,
data.table提供这方面更有效率的操作。
(这方面的速度比较可以参考#1LeXNCKV (R_Language) [分享] 资料数据处理修改)
1. data.table
这个函数基本上data.frame使用差不多,而且data.frame的参数都可以放进
像是很常用到的stringsAsFactors,只是data.table默认是FALSE,
这点跟data.frame不同,使用上需要注意,范例如下:
` R
t = data.table(a = LETTERS[1:3])
str(t)
# Classes ‘data.table’ and 'data.frame': 3 obs. of 1 variable:
# $ a: chr "A" "B" "C"
# - attr(*, ".internal.selfref")=<externalptr>
t2 = data.frame(a = LETTERS[1:3])
str(t2)
# 'data.frame': 3 obs. of 1 variable:
# $ a: Factor w/ 3 levels "A","B","C": 1 2 3
`
第二个差异是data.table不包含rownames,
在转换data.frame到data.table时,要注意这点
下一章会提到把rowname转成column的函数
附注一条:data.table都包含data.frame的class
可以用在data.frame的方法都可以在data.table上实现
但是data.table还多了一个引数 "key",我对它的解读是一种索引的概念
而透过索引的动作都会被加速。
key可以是一个变量,也可以是多个变量,这点看个人使用。
再来,就是data.table的'[',这部分跟data.frame不太一样
所以需要特别说明,但是这部分,我自己也不是很熟悉,我只能大概讲过
a. 我们很常在data.frame做取多行的动作,在data.table是不可行的,举例:
` R
vars = data.frame(X = rnorm(3), Y = rnorm(3), Z = rnorm(3))
vars[,1:2]
# X Y
# 1 -0.5677575 2.1831285
# 2 -0.7161529 0.3714633
# 3 1.2665120 0.7837508
vars_dt = data.table(vars)
vars_dt[,1:2]
# [1] 1 2
`
但是你想这么做,怎么办? 加上with=FALSE就好了,或是用list包住column name
` R
vars_dt[,1:2,with=FALSE]
# X Y
# 1: -0.5677575 2.1831285
# 2: -0.7161529 0.3714633
# 3: 1.2665120 0.7837508
vars_dt[j=list(X, Y)]
# X Y
# 1: -0.5677575 2.1831285
# 2: -0.7161529 0.3714633
# 3: 1.2665120 0.7837508
`
剩下像是by, .SD, .SDcols等自行?data.table查看吧
data.table的部分就先说明到这,接下来,讲一些相关的function
b. setkey: 改变key的值, setnames: 改变column name,但是一样不制造复本
c. copy: 制造data.table的复本
d. setDF: 在不制作复本下,把data.table的class改为data.frame
举例:
` R
DT = data.table(X = rnorm(3), Y = rnorm(3))
str(DT)
# Classes ‘data.table’ and 'data.frame': 3 obs. of 2 variables:
# $ X: num -1.3738 0.167 -0.0578
# $ Y: num 0.487 1.728 0.646
# - attr(*, ".internal.selfref")=<externalptr>
setDF(DT)
str(DT)
# 'data.frame': 3 obs. of 2 variables:
# $ X: num -1.3738 0.167 -0.0578
# $ Y: num 0.487 1.728 0.646
DT = data.table(X = rnorm(3), Y = rnorm(3))
tracemem(DT)
# [1] "<0000000006A1BE28>"
setDF(DT) # 没有复制的动作
DF = data.frame(DT)
retracemem(DF, retracemem(DT))
# tracemem[<0000000006A1BE28> -> 0x00000000061ec928]:
## 内存位置就发生改变了,就复制了DT一次
`
这部分可能不太懂,不过没关系,记住一点,要转成data.frame用setDF就好
e. setDT: setDF的反向
f. duplicated, unique
duplicated提供一个跟data.table列数相等长度的逻辑值向量,
TRUE代表前面有一样的列,FALSE代表没有
unique则是留下没有重复的列,举例来说:
` R
set.seed(100)
DT = data.table(A = rbinom(5, 1, 0.5), B = rbinom(5, 1, 0.5))
# A B
# 1: 0 0
# 2: 0 1
# 3: 1 0
# 4: 0 1
# 5: 0 0
duplicated(DT)
# [1] FALSE FALSE FALSE TRUE TRUE
unique(DT)
# A B
# 1: 0 0
# 2: 0 1
# 3: 1 0
DT[!duplicated(DT)]
# A B
# 1: 0 0
# 2: 0 1
# 3: 1 0
`
不过unique还有更多功能,它可以选择变量做unique,举例来说:
` R
unique(DT, by = "A")
# A B
# 1: 0 0
# 2: 1 0
unique(DT, by = "B")
# A B
# 1: 0 0
# 2: 0 1
`
顺便一提,dplyr的distinct,如果你input的class是data.table
它就是用unique做的
` R
library(dplyr)
distinct(DT)
# A B
# 1: 0 0
# 2: 0 1
# 3: 1 0
`
你如果想看distinct怎么做,可以在R上面打dplyr:::distinct_.data.table
> dplyr:::distinct_.data.table
function (.data, ..., .dots)
{
dist <- distinct_vars(.data, ..., .dots = .dots)
if (length(dist$vars) == 0) {
unique(dist$data)
}
else {
unique(dist$data, by = dist$vars)
}
}
之后提到distinct,我们再来讲distinct
其他相关function像是subset, setcolorder, setorder (setorderv)
对这三个function有兴趣,再去看manual,不赘述
这三个对应到dplyr的filter, select, arrange,之后我们会再提到这些
g. transform: 改变column的属性、值等,举例来说:
` R
DT = data.table(a = 1:3, b = 2:4, c = LETTERS[1:3])
DT2 = copy(DT)
DT[, b := b**2]
DT2 %<>% transform(b = b**2)
all.equal(DT, DT2) # TRUE
DT %<>% transform(c = as.factor(c))
str(DT)
# Classes ‘data.table’ and 'data.frame': 3 obs. of 3 variables:
# $ a: int 1 2 3
# $ b: num 4 9 16
# $ c: Factor w/ 3 levels "A","B","C": 1 2 3
# - attr(*, ".internal.selfref")=<externalptr>
`
h. set: 用来变更特定column,某些列的值,举个简单的例子
` R
DT = data.table(a = 1:3, b = 2:4)
DT2 = copy(DT)
DT[, b := 1]
set(DT2,, "b", value = 1)
all.equal(DT, DT2) # TRUE
`
一般来说都用'['来做,但是你如果需要用到for再来完成,再用set
还有一个function是 J,这里就不提了,一样请洽manual
最后,还有一个operator,':=',它是用来扩增data.table的column,
同样,也不创造复本,这样可以更快的增加column
那如果删除怎么办?还记得前面学过 DT[, list('X', 'Y')],就用这个
再来,我们讲一些data.table中其他function
2. fread
功能可以用来取代read.table, read.csv
它可以用多种separate去分割columns,然后读入R
而且读入速度比read.table, read.csv快很多
但是注意,不规则的档案会读入失败
这里提几个参数:
a. sep: column跟column之间的分隔,如果是csv就是',',
如果是tab separated values就是'\t'
b. na.strings: 视作NA的字串,它可以是一个vector
c. stringsAsFactors:是否要把字串转成factor,默认是否
d. colClasses:各行的classes,可以自行设定
我爱用fread还有一个原因,第一个input可以直接放我要读的字串,
但是read.table需要经过其他的方式,有点麻烦(我懒得记,其实没记过)
举例来说
` R
text = "a b
1 2
3 4"
DT = fread(text)
setDF(DT) # 转成data.frame,前面学过,还记得吗?
DF = read.table(header = TRUE, text = text) # text format
DF2 = read.table(textConnection(text), header = TRUE) # file format
all.equal(DT, DF) # TRUE
all.equal(DT, DF2) # TRUE
`
fread很适合拿来读大资料,所以有必要把table输出成text
用文字方式处理时,读入就变得很方便,可见 #1LegOjwB (R_Language)
还剩下 dcast.data.table, melt 跟 merge
它们会留到之后跟tidyr一起介绍
下一章重点会放在dplyr
补充:
key,我也不是很熟悉,也很少用,因此,我这里介绍的很少
如果对key有兴趣,可能需要自行研究
[关键字]: data.table, reshape2