我无法理解.SD
的工作方式,因此我无法将其整合到我的工作流程中。
set.seed(10238)
DT <- data.table(A = rep(1:3, each = 5), B = rep(1:5, 3),
C = sample(15), D = sample(15))
数据表是一个列表,每个列名称是元素的名称,列是列表的向量元素。因此:
lapply(DT, mean)
$A
[1] 2
$B
[1] 3
$C
[1] 8
$D
[1] 8
当我在j-expression中使用列名时,它可以被视为表示列中数据的向量。因此:
DT[, mean(B)]
[1] 3
但是当使用关键字by
时,它开始变得棘手:如何在执行by
分组时体验它?
DT[, mean(B), by=A]
A V1
1: 1 3
2: 2 3
3: 3 3
DT[, print(B), by=A]
[1] 1 2 3 4 5
[1] 1 2 3 4 5
[1] 1 2 3 4 5
这里看起来关键字A根据A中存在的组将矢量B分成3个矢量。如何在这里看到B?它是一个向量列表,它是一个数据表,如何重建结果数据?
> DT[, lapply(B, mean), by=A]
A V1 V2 V3 V4 V5
1: 1 1 2 3 4 5
2: 2 1 2 3 4 5
3: 3 1 2 3 4 5
我无法理解这一点,这应该返回与DT[, mean(B), by=A]
相同的结果,因为lapply单独输入3个向量并且应该对它们应用均值,结果列表应该重建为之前见过的数据表。
最后,我想要转换几列专栏,我不明白为什么必须使用:
DT[, names(DT) := lapply(.SD, as.character)]
而不是:
DT[, names(DT) := lapply(DT, as.character)]
它应该是相同的,lapply这里将as.character应用于DT的每一列,并返回一个列表,其中包含以列命名并以相同顺序命名的caracters的向量。
答案 0 :(得分:4)
如果你把注意力转向文档,你会得到更好的接待。
我刚输入?.SD
。第一段指向小插图,Jaap提供的定义,底部的示例部分包含:
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'
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'
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'
DT[, c(.(y=max(y)), lapply(.SD, min)),
by=rleid(v), .SDcols=v:b] # compute 'j' for each consecutive runs of 'v'
DT[, grp := .GRP, by=x] # add a group counter
X[, DT[.BY, y, on="x"], by=x] # join within each group
所以,请说出英语或示例有什么问题。告诉别人并告诉别人你已经阅读了这些文档。
最后一部分:
最后我想转换几列的类,我没有 明白我必须使用的原因:
DT[, names(DT) := lapply(.SD, as.character)]
而不是:
DT[, names(DT) := lapply(DT, as.character)]
在这种情况下你可以。它们是相同的,因为没有分组(by=
或keyby=
)和没有i
子集。为什么你认为你必须使用第一个?你不是指你读到“你必须”的地方,从错误的脚开始。第一个是优选的,因为在这种情况下使用.SD
会保存另一个DT
的变量名称重复(一般原则解释为here)。如果内存效率很重要,那么简单的for
循环可以避免首先创建:=
的整个RHS; for
循环方式逐列(更详细here)。