簡體   English   中英

如何將函數應用於data.table的子集,使用by並將所有列公開給函數?

[英]How to apply a function to a subset of data.table using by and exposing all columns to the function?

在按組切片data.table ,用於切片數據的變量在函數執行期間不在子集中。 我使用debugonce演示了這debugonce

library(data.table)
x <- data.table(a = rep(letters[1:4], each = 3), b = rep(c("a", "b"), each = 6), c = rnorm(12))

myfun <- function(y) paste(y$a, y$b, y$c, collapse = "")

> debugonce(myfun)
> x[, myfun(.SD), by = .(b, a)]
debugging in: myfun(.SD)
debug: paste(y$a, y$b, y$c, collapse = "")
Browse[2]> y
            c
1: -1.2662416
2:  0.9818497
3: -0.5395385

我所追求的是split-sapply范例的功能,我將根據factor(s)切片data.frame並將該函數應用於所有列,也就是說,還包括用於切片的變量它(如下所示)。

> debugonce(myfun)

> sapply(split(x, f = list(x$b, x$a)), FUN = myfun)
debugging in: FUN(X[[i]], ...)
debug: paste(y$a, y$b, y$c, collapse = "")
Browse[2]> y
a b          c
1: a a -1.2662416
2: a a  0.9818497
3: a a -0.5395385

該任擇議定書有一個函數,它接受一個列表,其中應包含data.table包括用於分組中列的所有列參數by

根據help(".SD")

.SD是一個data.table,包含每個組的x的數據子集, 不包括 by (或keyby )中使用的任何列。

(強調我的)

.BY是包含用於每個項目的長度1向量列表中的by 當事先不知道時by這可能是有用的。

因此, .BY.SD補充以訪問data.table的所有列。

而不是在函數調用中明確重復by

x[, myfun(c(list(b, a), .SD)), by = .(b, a)]

我們可以用

x[, myfun(c(.BY, .SD)), by = .(b, a)]
  ba V1 1: aaaa -1.02091215130492aa -0.295107569536843aa 0.77776326093429 2: abba -0.369037832486311ba -0.716211663822323ba -0.264799143319049 3: bccb -1.39603530693486cb 1.4707902839894cb 0.721925347069227 4: bddb -1.15220308230505db -0.736782242593426db 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)]
  ba V1 1: xc //1-//2-//3 2: xd //4-//5-//6 3: ye //7-//8-//9 4: yf //10-//11-//12 

因此,列ba確實在輸出中顯示為分組變量,但它們不會通過.SD傳遞給函數。

現在,用.BY補充.SD

x[, myfun(c(.BY, .SD)), by = .(b, a)]
  ba V1 1: xcc/x/1-c/x/2-c/x/3 2: xdd/x/4-d/x/5-d/x/6 3: yee/y/7-e/y/8-e/y/9 4: yff/y/10-f/y/11-f/y/12 

data.table的所有列都傳遞給函數。

函數調用中的單獨參數

Roland建議.BY.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 

其他鏈接

除了help(".SD") ,對以下SO問題的評論和回答可能有用:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM