OP有一个函数,它接受一个列表作为参数,其中应该包含alldata.table 的列,包括用于分组的列by
.
根据help(".SD")
:
.SD
是一个 data.table 包含的子集x
每组的数据,排除中使用的任何列by
(or keyby
).
(强调我的)
.BY
是一个列表,其中每个项目都包含长度为 1 的向量by
。这在以下情况下很有用:by
事先不知道。
So, .BY
and .SD
相互补充以访问 data.table 的所有列。
而不是明确地重复by
函数调用中的列
x[, myfun(c(list(b, a), .SD)), by = .(b, a)]
我们可以用
x[, myfun(c(.BY, .SD)), by = .(b, a)]
b a V1
1: a a a a -1.02091215130492a a -0.295107569536843a a 0.77776326093429
2: a b b a -0.369037832486311b a -0.716211663822323b a -0.264799143319049
3: b c c b -1.39603530693486c b 1.4707902839894c b 0.721925347069227
4: b d d b -1.15220308230505d b -0.736782242593426d b 0.420986999145651
OP已使用debugonce()
显示传递给的参数myfun()
:
> debugonce(myfun)
> x[, myfun(c(.BY, .SD)), by = .(b, a)]
debugging in: myfun(c(.BY, .SD))
debug at #1: paste(y$a, y$b, y$c, collapse = "")
Browse[2]> y
$b
[1] "a"
$a
[1] "a"
$c
[1] -1.0209122 -0.2951076 0.7777633
另一个例子
使用另一个示例数据集和函数可能更容易举例说明问题的核心:
x <- data.table(a = rep(letters[3:6], each = 3), b = rep(c("x", "y"), each = 6), c = 1:12)
myfun <- function(y) paste(y$a, y$b, y$c, sep = "/", collapse = "-")
x[, myfun(.SD), by = .(b, a)]
b a V1
1: x c //1-//2-//3
2: x d //4-//5-//6
3: y e //7-//8-//9
4: y f //10-//11-//12
所以,列b
and a
确实作为分组变量出现在输出中,但它们不是通过.SD
到函数。
现在,与.BY
互补.SD
x[, myfun(c(.BY, .SD)), by = .(b, a)]
b a V1
1: x c c/x/1-c/x/2-c/x/3
2: x d d/x/4-d/x/5-d/x/6
3: y e e/y/7-e/y/8-e/y/9
4: y f f/y/10-f/y/11-f/y/12
data.table 的所有列都传递给该函数。
函数调用中的单独参数
罗兰建议 https://stackoverflow.com/questions/45295639/how-to-apply-a-function-to-a-subset-of-data-table-using-by-and-exposing-all-colu/45295654?noredirect=1#comment77599900_45295654通过.BY
and .SD
作为函数的单独参数。的确,.BY
是一个列表对象并且.SD
是一个 data.table 对象(本质上也是一个列表,允许我们使用c(.BY, .SD)
)。在某些情况下,差异可能很重要。
为了验证,我们可以定义一个打印的函数str()
作为副作用。该函数仅针对第一组调用(.GRP == 1L
).
myfun1 <- function(y) str(y)
x[, if (.GRP == 1L) myfun1(.SD), by = .(b, a)]
Classes ‘data.table’ and 'data.frame': 3 obs. of 1 variable:
$ c: int 1 2 3
- attr(*, ".internal.selfref")=<externalptr>
- attr(*, ".data.table.locked")= logi TRUE
Empty data.table (0 rows) of 2 cols: b,a
x[, if (.GRP == 1L) myfun1(.BY), by = .(b, a)]
List of 2
$ b: chr "x"
$ a: chr "c"
Empty data.table (0 rows) of 2 cols: b,a
x[, if (.GRP == 1L) myfun1(c(.BY, .SD)), by = .(b, a)]
List of 3
$ b: chr "x"
$ a: chr "c"
$ c: int [1:3] 1 2 3
Empty data.table (0 rows) of 2 cols: b,a
附加链接
Beside help(".SD")
以下问题的评论和答案可能有用:
- R中data.table中的.SD代表什么 https://stackoverflow.com/questions/8508482/what-does-sd-stand-for-in-data-table-in-r
- 在 data.table R 中使用 lapply .SD https://stackoverflow.com/questions/32276887/use-of-lapply-sd-in-data-table-r