.SD如何在内部工作?

时间:2017-02-06 13:57:18

标签: r data.table

我无法理解.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的向量。

1 个答案:

答案 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)。