将单个列传递给j并从data.table中选择相同的列有什么区别?

时间:2017-02-05 03:39:03

标签: r data.table

我有一个包含nameclass的data.table。每个name属于一个class。这是一个示例数据集。

library(data.table)
DT <- data.table(name = c("John","Smith","Jane","Ruby","Emerald","Jasmine","Tulip"),
             class = c(1,2,3))

我想创建一个列,其中包含一个人所属的班级中的所有学生。这就是我正在做的事情并且它有效。

DT[, class.students := paste(.SD), .SDcols = "name", by = "class"]

我试图理解为什么以下内容不起作用,即它不会评估组中所有name列表中的函数(它只返回name创建列中行的值)

DT[, class.students := paste(name), by = "class"]

特别是下面的max代码按预期工作时,即它会对组中的所有元素进行求值,并为每个组返回相同的值。

DT[, class.students := max(name), by = "class"]

我在这里缺少什么?

编辑:max是一个糟糕的例子,因为它不能以第一种方式使用.SDcols,但我希望我想传达的内容很明确。

1 个答案:

答案 0 :(得分:3)

.SDlist,因此它会返回一个可能不合适的输出(如果我们检查str)。作为一个小例子

paste(list(letters[1:3])) #not the desirable output
#[1] "c(\"a\", \"b\", \"c\")"

paste(letters[1:3]) #did not change anything
#[1] "a" "b" "c"

但是,paste也有sepcollapse作为参数

paste(letters[1:3], collapse=", ")
#[1] "a, b, c"

使用OP的例子,

DT[, class.students := paste(name, collapse=", "), by = class]

我们建议直接将函数应用于.SD,但如果只有一列,我们可以listvector转换为[[或转换为unlistDT[, class.students := paste(unlist(.SD), collapse=", "), by = class] 等。

DT[, class.students := paste(.SD[[1]], collapse=", "), by = class]

或者

str(DT)

如果我们检查上述所有内容中的.SD,那就是相同的

关于在list上应用函数的最佳方式 - 正如我们已经提到的那样,它是.SD。当列数更多时,data.frame非常有用。与lapply中一样,当有多个列时,我们使用DT[, class.students := lapply(.SD, paste, collapse=", "), by = class] 遍历列并继续

.SDcols

如果只使用了一列列,我们也可以指定.SDcols。这里,在示例中,只有两列,因此不需要str(DT) #Classes ‘data.table’ and 'data.frame': 7 obs. of 3 variables: # $ name : chr "John" "Smith" "Jane" "Ruby" ... # $ class : num 1 2 3 1 2 3 1 # $ class.students: chr "John, Ruby, Tulip" "Smith, Emerald" "Jane, Jasmine" "John, Ruby, Tulip" ... # - attr(*, ".internal.selfref")=<externalptr>

time