在 R 中通过 data.table 进行自定义广播

Custom dcasting via data.table in R

这是我的数据

dt = data.table(x=sample(8,20,TRUE), 
                y=sample(2,20,TRUE), 
                w = sample(letters[5:20], 20, TRUE),
                u = sample(letters[2:25], 20, TRUE),
                z=sample(letters[1:4], 20,TRUE), 
                d1 = runif(20), d2=runif(20))

这是我的广播代码。

DC_1 = dcast.data.table(dt,x+w ~ z, value.var = "d1")

这很好用。但是,我的数据还可以另外包括 'a' 列和 's' 列,如下所示。两者都可以包括在内,可以是其中之一,也可以是 none 个。

dt = data.table(x=sample(8,20,TRUE), 
                y=sample(2,20,TRUE), 
                w = sample(letters[5:20], 20, TRUE),
                u = sample(letters[2:25], 20, TRUE),
                z=sample(letters[1:4], 20,TRUE), 
                a = sample(letters[1:25], 20, T),
                s = sample(letters[2:17], 20, T),
                d1 = runif(20), d2=runif(20))

然而,额外的列总是 characters 。此外,我的数据始终必须在列 'z' 上进行转换,值变量始终为 'd1'

如何通过 data.table 进行投射,以便它获取数据 table 中可用的所有字符列(z 除外)并将它们投射到 z 上?

我们可以对数据集列进行子集化,并在 ~ 的左轴上使用 ... 来指定所有列,在公式的右轴上使用 'z'

dcast(dt[, setdiff(names(dt), 'd2'), with = FALSE], ... ~ z, value.var = 'd1')

或者以编程方式获取字符列的列名

nm1 <- dt[, names(which(unlist(lapply(.SD, is.character))))]
nm2 <- setdiff(nm1, 'z')
dcast(dt,paste0(paste(nm2, collapse="+"), "~ z"), value.var = 'd1')

或者另一个选项是 select 来自 dplyr

library(dplyr) #1.0.0
dcast(dt[, select(.SD, where(is.character), d1)], ... ~ z, value.var = 'd1')

tidyverse 中的类似选项是

library(tidyr)
dt %>% 
   select(where(is.character), d1) %>% 
   pivot_wider(names_from = z, values_from = d1)