1) 在 R 中,() 是一个函数,可以被覆盖,即您可以为其分配不同的行为。当您执行(a <- 1) 时,您可能会注意到控制台正在打印1,即可以重新制作此行为。在data.table 的上下文中,您的示例请参见下文。
首先我们准备plms数据表:
set.seed(123)
plms <- data.table(
a = sample(c("A", "B ", "C ", " D "), 5, replace = TRUE),
b = sample(c("A", "B ", "C ", " D "), 5, replace = TRUE),
c = sample(c("A", "B ", "C ", " D "), 5, replace = TRUE)
)
cols <- c("a", "b", "c")
plms
# a b c
# 1: B A D
# 2: D C B
# 3: B D C
# 4: D C C
# 5: D B A
如您所见,生成的数据表带有尾随空格。然后让我们应用您的代码:
plms[, (cols) := lapply(.SD, str_trim), .SDcols = cols]
plms
# a b c
# 1: B A D
# 2: D C B
# 3: B D C
# 4: D C C
# 5: D B A
已删除尾随空格 - 好的。这意味着data.table 重新定义了() 的功能——它从cols 向量中获取列名,并将column-wisestrtrim 结果分配给这些列。
现在没有括号:
plms[, cols := lapply(.SD, str_trim), .SDcols = cols]
plms
# a b c cols
# 1: B A D B,D,B,D,D
# 2: D C B A,C,D,C,B
# 3: B D C D,B,C,C,A
# 4: D C C B,D,B,D,D
# 5: D B A A,C,D,C,B
实际上,这意味着您创建了列cols,并为该列分配了list。
2) .SD - 是一个内部只读符号(实际上是data.table 对象)
.SD 是一个 data.table,其中包含每个组的 x 数据的子集,不包括 by(或 keyby)中使用的任何列。
您可以查看以下数据:
plms[, lapply(.SD, print), .SDcols = cols]
# [1] "B " " D " "B " " D " " D "
# [1] "A" "C " " D " "C " "B "
# [1] " D " "B " "C " "C " "A"
# a b c
# 1: B A D
# 2: D C B
# 3: B D C
# 4: D C C
# 5: D B A
如您所见,将print 按列应用于.SD 的结果显示了SDcols 的选定列。
[] 也被重新定义,该函数的参数之一是.SDcols,用于为.SD 数据表选择列。请参阅下面的文档。
.SDcols 指定 x 的列要包含在特殊的
符号 .SD 代表 data.table 的子集。可能是性格
列名或数字位置。这对速度很有用
通过(可能非常多)列的子集应用函数;
例如,DT[, lapply(.SD, sum), by="x,y", .SDcols=301:350]。
3) := 也是一个函数(你可以通过?":=" 看到它的帮助。这个函数的主要思想是在对象内部修改数据(通过引用):
plms[, a := "x"]
plms
# a b c
# 1: x A C
# 2: x D B
# 3: x A B
# 4: x B D
# 5: x C B
通常 R 按值工作,并且在函数执行期间不会修改对象(函数方法:函数在执行期间不应更改参数)。
从根本上说,这是data.table 包的争议点,因为对象内部状态的更改可能导致难以识别错误和调试困难,但与例如base::data.frame.