1.关于样本集的复制
> DT <- data.table(a=c(1,2), b=c(11,12))
> DT2<-DT #用<-复制数据 集,新数据集改变后,原数据集会跟着一起改变
> DT2[,new3:=3L]
> DT2
a b new3
1: 1 11 3
2: 2 12 3
> DT
a b new3
1: 1 11 3
2: 2 12 3
> DT3<-copy(DT) #使用copy()函数,进行复制,不会产生上面的问题。
> DT
a b new3
1: 1 11 3
2: 2 12 3
> DT3[,new4:=4L]
> DT3
a b new3 new4
1: 1 11 3 4
2: 2 12 3 4
> DT
a b new3
1: 1 11 3
2: 2 12 3
2.关于子集.SD的用法
> fkt
[1] "teamIDBR" "teamIDlahman45" "teamIDretro"
#设置fkt中的列将类型转变为factor,注意要将fkt用括号括起来()
>Teams[ , (fkt) := lapply(.SD, factor), .SDcols = fkt]
#返回每个teamID的第一列 #不是很明白
> Teams[ , .SD[.N], by = teamID]
#返回每个teamID子集中R最大的行
> Teams[ , .SD[which.max(R)], by = teamID]
#分组回归
Pitching[ , if (.N > 20) .(w_coef = coef(lm(ERA ~ W))['W']), by = teamID
][ , hist(w_coef, 20, xlab = 'Fitted Coefficient on W',
ylab = 'Number of Teams', col = 'darkgreen',
main = 'Distribution of Team-Level Win Coefficients on ERA')]
3.关于data.table用数字选择列
方法1.
> dt <- data.table(a = 1, b = 2, c = 3)
> dt[, 2]
b
1: 2
> dt[, 2:3]
b c
1: 2 3
方法2.
> dt[, "a"]
a
1: 1
> dt[, c("a", "b")]
a b
1: 1 2
方法3.
> b<-data.table(a=1,b=2,c=3,d=4)
> b[,.SD,.SDcols=c(1:2)]
a b
1: 1 2
> dt[,.SD,.SDcols=c(1,3)]
a c
1: 1 3
> dt[,.SD,.SDcols=-2]
a c
1: 1 3
方法4.
> keep_cols = c("a", "c")
> dt[, ..keep_cols]
a c
1: 1 3
4.为了按照列名删除列
为了删除列名“foo”的一列,在数据框汇总,我是这样做的:
> df <- df[-grep('foo', colnames(df))]
然而,当把df转化成data.table后,这种方法不能再删除这一列了:
> library(data.table)
> df <- data.frame(id = 1:100, foo = rnorm(100))
> df2 <- df[-grep('foo', colnames(df))] # works
> df3 <- data.table(df)
> df3[-grep('foo', colnames(df3))]
这是怎么回事呢?Data.table如何删除列?
答案1:
以下几种方法都能删除data.table df3中的列“foo”:
#方法1:
> df3[,foo:=NULL]
> df3[, c("foo","bar"):=NULL] # remove two columns
> myVar = "foo"
> df3[, (myVar):=NULL] # lookup myVar contents
#方法2a
> df3[, grep("^foo$", colnames(df3)):=NULL]
#方法2b
> df3[, which(grepl("^foo$", colnames(df3))):=NULL]
#方法3
> df3[, !"foo", with=FALSE]
#方法4a
> df3[, -grep("^foo$", colnames(df3)), with=FALSE]
#方法4b
> df3[, !grepl("^foo$", colnames(df3)), with=FALSE]
注:grep()返回相匹配的下标值
grepl()返回所有的查询结果,并用逻辑向量表示匹配结果。
但都能用来提取相同的子集,grepl()前面加上了which()
答案2:
> dt <- data.table( a=letters, b=LETTERS, c=seq(26), d=letters, e=letters )
> set( dt, j=c(1L,3L,5L), value=NULL )
> dt[1:5]
b d
1: A a
2: B b
3: C c
4: D d
5: E e
用set(dt,j=c(),value=NULL)
其中的参数必须用j,value,表示j列的数字全部设置为空值,则第j列全部被删除。
答案3:
可以用与data.frame相同的方法:
> DT$foo<-NULL
但是如果DT数据量较大,上面的方法$foo就会有产生大量复制,运行速度慢,因此最好使用:
> DT<-DT[,foo:=NULL]
5.同时计算两列或多列数据
数据集:
library(lubridate)
days = 365*2
date = seq(as.Date("2000-01-01"), length = days, by = "day")
year = year(date)
month = month(date)
x1 = cumsum(rnorm(days, 0.05))
x2 = cumsum(rnorm(days, 0.05))
df1 = data.frame(date, year, month, x1, x2)
方法:
# 作者一般方法,只能计算一列数据
### aggregate variables by year month
df2=aggregate(x1 ~ year+month, data=df1, sum, na.rm=TRUE)
head(df2)
#使用reshape2处理包
require(reshape2)
df_melt <- melt(df1, id = c("date", "year", "month"))
dcast(df_melt, year + month ~ variable, sum)
或者用recast()函数,其融合了melt()与dcast()函数,如下:
recast(df1, year + month ~ variable, sum, id.var = c("date", "year", "month"))
# year month x1 x2
1 2000 1 -80.83405 -224.9540159
2 2000 2 -223.76331 -288.2418017
3 2000 3 -188.83930 -481.5601913
4 2000 4 -197.47797 -473.7137420
5 2000 5 -259.07928 -372.4563522
#使用aggregate(),将要计算的两列cbind()合并,一起处理
aggregate(cbind(x1, x2) ~ year + month, data = df1, sum, na.rm = TRUE)
year month x1 x2
1 2000 1 7.862002 -7.469298
2 2001 1 276.758209 474.384252
3 2000 2 13.122369 -128.122613
...
23 2000 12 63.436507 449.794454
24 2001 12 999.472226 922.726589
计算除了分类变量后的所有变量的和,并考虑缺失值。
aggregate(. ~ year + month, df1, sum, na.rm = TRUE)
#使用data.table处理包
library(data.table)
df2 <- setDT(df1)[, lapply(.SD, sum), by=.(year, month), .SDcols=c("x1","x2")]
setDF(df2) # convert back to dataframe
#使用plyr处理包
require(plyr)
df2 <- ddply(df1, c("year", "month"), function(x) colSums(x[c("x1", "x2")]))
#使用Hmisc包中的summarize()
# need to detach plyr because plyr and Hmisc both have a summarize()
detach(package:plyr)
require(Hmisc)
df2 <- with(df1, summarize( cbind(x1, x2), by=llist(year, month), FUN=colSums))
#使用dplyr处理包
library(dplyr)
# summarising all non-grouping variables
df2 <- df1 %>% group_by(year, month) %>% summarise_all(sum)
# summarising a specific set of non-grouping variables
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(x1, x2), sum)
df2 <- df1 %>% group_by(year, month) %>% summarise_at(vars(-date), sum)
# summarising a specific set of non-grouping variables based on condition (class)
df2 <- df1 %>% group_by(year, month) %>% summarise_if(is.numeric, sum)
6.rbind与rbindlist的比较
rbindlist速度更快
> do.call(rbind, list(data.frame(a = 1:2, b = 2:3), data.frame(b = 1:2, a = 2:3)))
> rbindlist(list(data.frame(a = 1:5, b = 2:6), data.frame(b = 1:5, a = 2:6)))
7.字符型向量降序排列
library(data.table)
DT = data.table(x=rep(c("b","a","c"),each=3), y=c(1,3,6), v=1:9)
在data.table 1.9.4版本之前,DT[-x]会报错,因为x是charac tor类型,而现在的版本已经可以处理了,不需要其他的处理方法。当然还有其他的而解决办法,但最简单最好用的就可以了。
其他方法:
DT[order(-rank(x),y)]
DT[order(x,-v,decreasing=TRUE),]
setorder(DT, -x) #Setkey\setnames\setDT\等类似的指令set
8.批量为多列赋值,根据已有的数据列
x <- data.table(a = 1:3, b = 1:6)
f <- function(x) {list("hi", "hello")}
x[ , c("col1", "col2") := f(), by = a][]
x[ , c("mean", "sum") := list(mean(b), sum(b)), by = a][]
mynames = c("Name1", "Longer%")
x[ , (mynames) := list(mean(b) * 4, sum(b) * 3), by = a]
x[ , mynames := list(mean(b) * 4, sum(b) * 3), by = a, with = FALSE][] # same
x[ , get("mynames") := list(mean(b) * 4, sum(b) * 3), by = a][] # same
x[ , eval(mynames) := list(mean(b) * 4, sum(b) * 3), by = a][] # same
dt[,`:=`(avg=mean(mpg), med=median(mpg), min=min(mpg)), by=cyl]
9.R中最快的merge/join数据的方法
#merge指合并两张表,表中存在相同的变量,将这两个表根据相同的变量在一起,相当于并的概念。
DF1 = data.frame(a = c(1, 1, 2, 2), b = 1:4)
DF2 = data.frame(b = c(1, 2, 3, 3, 4), c = letters[1:5])
merge(DF1, DF2)
b a c
1 1 1 a
2 2 1 b
3 3 2 c
4 3 2 d
5 4 2 e
根据两张表中的变量b,来计算表1中变量c的值,表1中原来没有c,从关联的表2中得来的。
DF1$c = DF2$c[match(DF1$b, DF2$b)] #相当于数据框生成新变量的做法。
DF1$c
[1] a b c e
Levels: a b c d e
> DF1
a b c
1 1 1 a
2 1 2 b
3 2 3 c
4 2 4 e
10.快速重新排列数据集中列的顺序
使用setcolorder()
library(data.table)
x <- data.table(a = 1:3, b = 3:1, c = runif(3))
x
# a b c
# [1,] 1 3 0.2880365
# [2,] 2 2 0.7785115
# [3,] 3 1 0.3297416
setcolorder(x, c("c", "b", "a"))
x
# c b a
# [1,] 0.2880365 3 1
# [2,] 0.7785115 2 2
# [3,] 0.3297416 1 3
这种方法非常高效,不会引起整个数据集的复制。Data.table中set命令都是引用,不会复制,占用工作内存。
只移动个别列时:
setcolorder(df, c("someCol",colnames(dt)[!(colnames(dt) %in% c("someCol"))]))
11.批量修改列的类型
1.对于单列:
dtnew <- dt[, Quarter:=as.character(Quarter)]
str(dtnew)
Classes ‘data.table’ and 'data.frame': 10 obs. of 3 variables:
$ ID : Factor w/ 2 levels "A","B": 1 1 1 1 1 2 2 2 2 2
$ Quarter: chr "1" "2" "3" "4" ...
$ value : num -0.838 0.146 -1.059 -1.197 0.282 ...
2.使用lapply和as.character:
dtnew <- dt[, lapply(.SD, as.character), by=ID]
str(dtnew)
Classes ‘data.table’ and 'data.frame': 10 obs. of 3 variables:
$ ID : Factor w/ 2 levels "A","B": 1 1 1 1 1 2 2 2 2 2
$ Quarter: chr "1" "2" "3" "4" ...
$ value : chr "1.487145280568" "-0.827845218358881" "0.028977182770002" "1.35392750102305" ...
3.
DT <- data.table(X1 = c("a", "b"), X2 = c(1,2), X3 = c("hello", "you"))
changeCols <- colnames(DT)[which(as.vector(DT[,lapply(.SD, class)]) == "character")]
changeCols<- names(Filter(is.character, DT)) #以上两句都可以,第二句更方便
DT[,(changeCols):= lapply(.SD, as.factor), .SDcols = changeCols]
12.什么时候应该在data.table中使用“:=”
提高速度
m = matrix(1,nrow=100000,ncol=100)
DF = as.data.frame(m)
DT = as.data.table(m)
system.time(for (i in 1:1000) DF[i,1] <- i)
user system elapsed
287.062 302.627 591.984
system.time(for (i in 1:1000) DT[i,V1:=i])
user system elapsed
1.148 0.000 1.158 ( 511 times faster )
使用的各种场景
DT["a",done:=TRUE] # binary search for group 'a' and set a flag 不太理解
DT[,newcol:=42] # add a new column by reference (no copy of existing data) 添加新列
DT[,col:=NULL] # remove a column by reference 删除一列
DT[,newcol:=sum(v),by=group] # like a fast transform() by group 分组计算
13.将"inf"值批量转化为“NA”值
选项1
使用a data.frame是列的列表,然后用于do.call重新创建一个data.frame。
do.call(data.frame,lapply(DT, function(x) replace(x, is.infinite(x),NA)))
选项2 - data.table
你可以使用data.table和set。这避免了一些内部复制。且速度最快,推荐此方法
DT <- data.table(dat)
invisible(lapply(names(DT),function(.name) set(DT, which(is.infinite(DT[[.name]])), j = .name,value =NA)))
选项3-
或者使用列号(如果列数很多,可能会更快):
for (j in 1:ncol(DT)) set(DT, which(is.infinite(DT[[j]])), j, NA)
14.在R中使用传递变量引用data.table中的列名称
library('data.table')
DT = data.table(x=c("b","b","b","a","a"),v=rnorm(5))
使用quote()和eval()函数将变量传递给j。当你这样做时,你不需要在列名上使用双引号,因为quote()ed字符串将在DT[]内部被评估
temp <- quote(x)
DT[,eval(temp)]
# [1] "b" "b" "b" "a" "a"
使用单个列名称,结果是一个向量。如果你想要一个data.table结果或者几列,使用列表形式
temp <- quote(list(x,v))
DT[,eval(temp)]
# x v
# 1: b 1.52566586
# 2: b 0.66057253
# 3: b -1.29654641
# 4: a -1.71998260
# 5: a 0.03159933
15.在R中使用前一行的值进行计算
> DT <- data.table(A=1:5, B=1:5*10, C=1:5*100)
> DT
A B C
1: 1 10 100
2: 2 20 200
3: 3 30 300
4: 4 40 400
5: 5 50 500
> DT[, D := C + BPreviousRow] # What is the correct code here?
#使用data.table() 中shift()功能
DT[ , D := C + shift(B, 1L, type="lag")]
# or equivalently, in this case,
DT[ , D := C + shift(B)]
新功能shift()快速lead/lag实现向量,列表,data.frames或data.tables。它需要一个type可以是“滞后”(默认)或“领先”的参数。它可以非常方便地使用:=或set()。例如:DT[, (cols) := shift(.SD, 1L), by=id]。
16.最快的恰当的方式来重塑data.table()
已知:
library(data.table)
set.seed(1234)
DT <- data.table(x=rep(c(1,2,3),each=4), y=c("A","B"), v=sample(1:100,12))
DT
x y v
[1,] 1 A 12
[2,] 1 B 62
[3,] 1 A 60
[4,] 1 B 61
[5,] 2 A 83
[6,] 2 B 97
[7,] 2 A 1
[8,] 2 B 22
[9,] 3 A 99
[10,] 3 B 47
[11,] 3 A 63
[12,] 3 B 49
我可以很容易地通过data.table中的组对变量v进行求和:
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
out
x y SUM
[1,] 1 A 72
[2,] 1 B 123
[3,] 2 A 84
[4,] 2 B 119
[5,] 3 A 162
[6,] 3 B 96
但是,我想将组(y)设置为列,而不是行。我可以完成这个使用reshape:
out <- reshape(out,direction='wide',idvar='x', timevar='y')
out
x SUM.A SUM.B
[1,] 1 72 123
[2,] 2 84 119
[3,] 3 162 96
聚合后有没有更有效的方法来重塑数据?有没有办法将这些操作合并为一个步骤,使用data.table操作?
答案:
library(data.table)
set.seed(1234)
DT <- data.table(x=rep(c(1,2,3),each=1e6),
y=c("A","B"),
v=sample(1:100,12))
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
# edit (mnel) to avoid setNames which creates a copy
# when calling `names<-` inside the function
out[, as.list(setattr(SUM, 'names', y)), by=list(x)]
})
x A B
1: 1 26499966 28166677
2: 2 26499978 28166673
3: 3 26500056 28166650
第二种方法:tapply()函数
tapply(DT$v,list(DT$x, DT$y), FUN=sum)
A B
1 26499966 28166677
2 26499978 28166673
3 26500056 28166650
而且,它速度很快:
system.time({
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
out[, as.list(setattr(SUM, 'names', y)), by=list(x)]})
## user system elapsed
## 0.64 0.05 0.70
system.time(tapply(DT$v,list(DT$x, DT$y), FUN=sum))
## user system elapsed
## 7.23 0.16 7.39
UPDATE
因此,该解决方案也适用于非平衡数据集(即某些组合不存在),您必须首先在数据表中输入这些数据:
library(data.table)
set.seed(1234)
DT <- data.table(x=c(rep(c(1,2,3),each=4),3,4), y=c("A","B"), v=sample(1:100,14))
out <- DT[,list(SUM=sum(v)),by=list(x,y)]
setkey(out, x, y)
intDT <- expand.grid(unique(out[,x]), unique(out[,y]))
setnames(intDT, c("x", "y"))
out <- out[intDT]
out[, as.list(setattr(SUM, 'names', y)), by=list(x)]
概要
结合上述评论,以下是单线解决方案:
DT[, sum(v), keyby = list(x,y)][CJ(unique(x), unique(y)), allow.cartesian = T][,
setNames(as.list(V1), paste(y)), by = x]
修改它也很容易,不仅仅是总和,例如:
DT[, list(sum(v), mean(v)), keyby = list(x,y)][CJ(unique(x), unique(y)), allow.cartesian = T][,
setNames(as.list(c(V1, V2)), c(paste0(y,".sum"), paste0(y,".mean"))), by = x]
# x A.sum B.sum A.mean B.mean
#1: 1 72 123 36.00000 61.5
#2: 2 84 119 42.00000 59.5
#3: 3 187 96 62.33333 48.0
#4: 4 NA 81 NA 81.0
17.选择列替换NA值为0值
全部替换:
x[is.na(x)]<-0
数据:
set.seed(1234)
x <- data.frame(a=sample(c(1,2,NA), 10, replace=T),
b=sample(c(1,2,NA), 10, replace=T),
c=sample(c(1:5,NA), 10, replace=T))
部分替换:
答案1:
x[, 1:2][is.na(x[, 1:2])] <- 0
x[c("a", "b")][is.na(x[c("a", "b")])] <- 0
在这两种情况下,1:2或者c("a", "b")可以被预先定义的向量替代。
x[, 1:2][x[, 1:2] == 1] <- 0 #将所有为1的替换为0,原理一样的
答案2:适用于data.table
for (col in c("a", "b")) y[is.na(get(col)), (col) := 0]
for (col in 1:2) set(x, which(is.na(x[[col]])), col, 0)
答案3:
tidyr::replace_na(x, list(a=0, b=0))
18.删除重复行
library(data.table)
dt <- data.table(
V1=LETTERS[c(1,1,1,1,2,3,3,5,7,1)],
V2=LETTERS[c(2,3,4,2,1,4,4,6,7,2)]
)
setkey(dt, "V2")
unique(dt)
setkey(dt)
unique(dt)
setkey(dt,NULL)
unique(dt,by=c("V1","V2"))
19.按组获取最高值
数据:将数据框d中的列x进行降序排列,并根据grp分组,获取每组最高的5个值。
d <- data.frame( x = runif(90), grp = gl(3, 30))
答案1:
#注意区别这两行代码的区别。本代码是前面不对grp排序,后面使用keyby,对输出的keyby升序排列。下面一行代码是前面对grp升序,后面仅使用by即可,输出结果与上一行结果相同。
setorder(setDT(d), -x)[, head(.SD, 5), keyby = grp]
setorder(setDT(d), grp, -x)[, head(.SD, 5), by = grp]#grp升序,x降序
答案2
#对处理大数据更快,因为不用到.Sd对每组的呼叫。#seq_len代表选区的数据集的长度,后面的链接限制长度的大小。
setorder(setDT(d), grp, -x)[, indx := seq_len(.N), by = grp][indx <= 5]
20.data.table按照数字选择列并输出向量,而不是data.table
DT<-data.table(x=c(1,2),y=c(3,4),z=c(5,6))
is.list(DT)
#[1] TRUE
DT[[2]]
#[1] 3 4
如果不一定要用数字选择列的话,DT[,x]输出结果也是向量,而DT[,.(X)]则是data.table.
21.在data.table中插入一行
set.seed(12345)
dt1 <- data.table(a=rnorm(5), b=rnorm(5))
microbenchmark(
rbind(dt1, list(5, 6)),
rbindlist(list(dt1, list(5, 6)))
)
如果你想在其他地方插入这一行,下面的内容将起作用,但它不是很好:
rbindlist(list(dt1[1:3, ], list(5, 6), dt1[4:5, ])) #在第三行和第四行中间插入新的一行。
或者:
rbindlist(list(dt1[1:3, ], as.list(c(5, 6)), dt1[4:5, ]))
如果您正在修改某一行(这是首选方法),则需要事先定义data.table的大小,即
dt1 <- data.table(a=rnorm(6), b=rnorm(6))
set(dt1, i=6L, j="a", value=5) # refer to column by name #对第六行,a列,赋值为5
set(dt1, i=6L, j=2L, value=6) # refer to column by number#对第六行,第二列(即b列),赋值为6
这种方法可用来修改某一处的值。
22.使用.I返回包含一定条件的data.table包的行号
require(data.table)
DT <- data.table(X=c(5, 15, 20, 25, 30))
希望返回行中大于20的行或行号
1.如果只要行号
DT[X > 20, which = TRUE]
2..I返回子集所在的行号
set.seed(1)
LL <- sample(LETTERS[1:5], 20, TRUE)
DT <- data.table(X=LL)
DT[X == "B", .I] #首先执行的是筛选子集,然后返回在子集的位置,所以是连续的,显然这不是我们想要的
# [1] 1 2 3 4 5 6
DT[ , .I[X == "B"] ]#这个返回是是整个表中的位置
# [1] 1 2 5 11 14 19
高级:分组时,可以在j表达式中使用符号.SD,.BY,.N,.I和.GRP,定义如下。
.I是一个等于seq_len(nrow(x))的整数向量。分组时,它将组中的每个项目的行位置保存在x中。这对j中的子集很有用。例如DT [,.I [which.max(somecol)],by = grp]。这里强调了我的强调。最初的目的是.I在分组时使用。
23.选择data.table中列的子集
选择不包含某些列的数据集的子集
dt = data.table(matrix(sample(c(0,1),5,rep=T),50,10))
dt[,-3,with=FALSE] # Is this the only way to not print column "V3"?
df = data.frame(matrix(sample(c(0,1),5,rep=T),50,10))
df[,!(colnames(df)%in% c("X3"))]
问题:不打印数据,且不利用数字,用类似数据框的那种处理方式,用data.table来做。
方法1:
dt[, setdiff(colnames(dt),"V9"), with=FALSE] #setdiff(x,y)选择x,y中不同的值
keep <- setdiff(names(dt), "V9")
dt[, ..keep] #前缀符号..将在调用范围(即全局环境)中查找,并将其值视为列名或数字
方法2:
dt[, -grep("^V3$", names(dt)), with=FALSE]
dt[ , -grep("^V3$|^V9$", names(dt), with=FALSE #多列
方法3:
dt[, -'V3', with=FALSE]
dt[, -c('V3', 'V9'), with=FALSE]#多列
请注意,变量名称周围的引号是必需的。
附:setdiff相关的一些函数
x = data.table(c(1,2,2,2,3,4,4))
y = data.table(c(2,3,4,4,4,5))
fintersect(x, y) # intersect 返回x\y中的交集
fintersect(x, y, all=TRUE) # intersect all
fsetdiff(x, y) # except x\y中不同的值
fsetdiff(x, y, all=TRUE) # except all 返回全部不同的值
funion(x, y) # union 合并x\y中的值
funion(x, y, all=TRUE) # union all 返回全部x\y中的值
fsetequal(x, y) #返回逻辑判断值 TRUE 或 FALSE 判断两变量是否相同
24.
DT2 <- DT[, .(C = cumsum(C)), by = .(A, B)]
DT2 <- DT[,C := cumsum(C),by=.(A,B)]
25.仍旧是.SD
通过指定列号:
dt.out <- dt[, lapply(.SD, mean), by=grp, .SDcols = 251:300]
dim(dt.out) # 15 * 51 (what we expect)
或者通过指定列标识:
ids <- paste0("V", 251:300) # get column ids
dt.out <- dt[, lapply(.SD, mean), by=grp, .SDcols = ids]
dim(dt.out) # 15 * 51 (what we expect)
26..SD使用不同的函数,共同输出,需要用到c()
dt = data.table(grp = sample(letters[1:3],100, replace = TRUE),
v1 = rnorm(100),
v2 = rnorm(100),
v3 = rnorm(100))
sd.cols = c("v2", "v3")
dt.out = dt[, c(v1 = sum(v1), lapply(.SD,mean)), by = grp, .SDcols = sd.cols]
附:.SD, .BY, .N, .I and .GRP
.SD, .BY, .N, .I and .GRP are read only symbols for use in j. .N can be used in i as well.
DT = data.table(x=rep(c("b","a","c"),each=3), v=c(1,1,1,2,2,1,1,2,2), y=c(1,3,6), a=1:9, b=9:1)
DT
X = data.table(x=c("c","b"), v=8:7, foo=c(4,2))
X
DT[.N] # last row, only special symbol allowed in 'i' 只用在i中表示最后一行
DT[, .N] # total number of rows in DT
DT[, .N, by=x] # number of rows in each group 每一组的个数
DT[, .SD, .SDcols=x:y] # select columns 'x' and 'y'
DT[, .SD[1]] # first row of all columns 所有列的第一行
DT[, .SD[1], by=x] # first row of 'y' and 'v' for each group in 'x' 按照x分组的每一组的第一行
DT[, c(.N, lapply(.SD, sum)), by=x] # get rows *and* sum columns 'v' and 'y' by group 行数及分组求和
DT[, .I[1], by=x] # row number in DT corresponding to each group 每一组的第一个元素的行数
DT[, .N, by=rleid(v)] # get count of consecutive runs of 'v' V中连贯的元素的个数。
DT[, c(.(y=max(y)), lapply(.SD, min)),
by=rleid(v), .SDcols=v:b] # compute 'j' for each consecutive runs of 'v' 对v中连贯的元素计算j列。
DT[, grp := .GRP, by=x] # add a group counter 添加分组标签,属于哪类,标签就标记为几。
X[, DT[.BY, y, on="x"], by=x] # join within each group 不太明白.BY的使用功能
27.有条件的删除行
在data.table下,可以执行以下语句:
data <- data[ menuitem != 'coffee' | amount > 0]
若想提高速度,可以设置主键,执行以下语句。
setkey(data, menuitem)
data <- data[!"coffee"]
28.将列中的字符串之间的空值替换为下划线
library(data.table)
## Create three identical 1000000-by-20 data.tables
DT1 <- data.table(1:1e6,
as.data.table(replicate(1e6, paste(sample(letters, nr, TRUE),
sample(letters, nr, TRUE)))))
cnames <- c("ID", paste0("X", 1:19))
setnames(DT1, cnames)
DT2 <- copy(DT1); DT3 <- copy(DT1)
## Method 1 方法1 lapply
system.time({
DT1[, cnames[-1] := lapply(DT1[,cnames[-1],with=FALSE],
function(x) gsub(" ", "_", x))]
})
## user system elapsed
## 10.90 0.11 11.06
## Method 2 方法2 loop + set
system.time({
for(cname in cnames[-1]) {
set(DT2, j=cname, value=gsub(" ", "_", DT2[[cname]]))
}
})
## user system elapsed
## 10.65 0.05 10.70
## Method 3 方法3 loop + 数据框
system.time({
for(cname in cnames[-1]) {
DT3[ , cname := gsub(" ", "_", DT3[[cname]]), with=FALSE]
}
})
## user system elapsed
## 10.33 0.03 10.37
29.打印函数
打印不出来:
library(data.table)
mydt <- data.table(x = 1:3, y = 5:7)
myfunction <- function(dt) {
dt[, z := y - x]
dt
}
正确方法:
myfunction <- function(dt) {
dt[, z := y - x][]
}
myfunction(mydt)
30.x[Y]与merge之间的区别
例1. 当两个表中的主键列中没有重复数据,即unique(x[,.key])=nrow(x)
x<-data.table(grp=letters[1:7],foo =1:7)
y<-data.table(grp=c("a","b","h"),bar=c(4,2,7))
setkey(x,grp)
setkey(y,grp)
x[y] #根据y表中的grp匹配x表中的值,dim(x[y])=dim(y)
x[y,nomatch=0L]
y[x] #根据x表中的grp值匹配y表中的值,dim(y[x]=dim(x))
y[x,namatch=0L]
merge(x,y)#与下面的结果相同,也与x[y,nomatch=0L]、y[x,namatch=0L]结果相同
merge(y,x)
sql:
select * from x ,y where x.grp = y.grp 不知是否正确?
例2.当两个表中的主键列中有重复数据,即unique(x[,.key])!=nrow(x)
X = data.table(grp = c("a", "a", "b",
"b", "b", "c", "c"), foo = 1:7)
setkey(X, grp)
Y = data.table(c("b", "c"), bar = c(4, 2))
X[Y]
X[Y, sum(foo*bar)] #同X[Y][,sum(foo*bar)]
X[Y, sum(foo*bar), by = .EACHI] #同X[Y][,sum(foo*bar),by= grp][order(grp)]
31.mycol 如何返回列
mycol=c("姓名")
DT[,list(mycol))]
DT[,.SD,.SDcols=mycol] #data.table
DT[[mycol]]#vector
DT[,mycol,with=FALSE] #data.table
32.关于DT[,j]的用法
DT[,j]
DT[ , mean(x*y/z)]
DT[x>1000, sum(y*z)]
DT[x>1000, plot(y, z)]
DT[x>1000, sum(y*z), by = w]
33.