在 data.table 中分配多个 lapplys?
Posted
技术标签:
【中文标题】在 data.table 中分配多个 lapplys?【英文标题】:Assignment with multiple lapplys in data.table? 【发布时间】:2022-01-13 20:52:06 【问题描述】:有没有比下面两个更优雅的解决方案来对 data.table 列集执行多个操作?我所说的“更优雅”是指作为一个单行而不是结合中间结果。
请注意,我在此特定示例中使用了by
,但该问题也适用于非by
情况。
library(data.table)
# create toy data.table
dt <- data.table(
ID=sample(1:10, 50, replace=TRUE),
A=letters[sample(1:26, 50, replace=TRUE)],
B=letters[sample(1:26, 50, replace=TRUE)],
C=letters[sample(1:26, 50, replace=TRUE)],
D=letters[sample(1:26, 50, replace=TRUE)]
)
# two sets of columns to process differently
use_all <- c("A","B")
just_first <- c("C","D")
# do these separately, then bind columns. assumes the `by` column is identical across the two:
results <- data.table(
dt[, lapply(.SD, function(x) x[1]), by=ID, .SDcols= just_first],
dt[, lapply(.SD, function(x) list(x)), by=ID, .SDcols= use_all][, .SD, .SDcols=-"ID"]
)
# do these separately, then merge. doesn't assume the `by` column is identically ordered:
results <- merge(
dt[, lapply(.SD, function(x) x[1]), by=ID, .SDcols= just_first],
dt[, lapply(.SD, function(x) list(x)), by=ID, .SDcols= use_all],
by="ID"
)
【问题讨论】:
【参考方案1】:out <- dt[, Map(function(x, nm) if (nm %in% just_first) x[1] else list(x),
.SD, names(.SD)),
by = ID, .SDcols = c(use_all, just_first)]
out
# ID A B C D
# <int> <list> <list> <char> <char>
# 1: 1 f,b,w,x,g u,s,y,x,r f q
# 2: 5 f,e,l,t,n,j v,p,i,w,x,b f t
# 3: 9 t,h,m,j p,z,m,n o q
# 4: 10 c,b,q,e,n,b,... v,i,w,j,a,s,... b a
# 5: 4 v,j,a,i,i,x,... q,y,h,e,p,n,... j b
# 6: 2 u,g,k,e,w,u,... l,f,z,f,k,p,... w h
# 7: 8 f,c,e,r,h,y u,k,y,q,e,v i e
# 8: 7 z,d k,q a m
# 9: 3 d,p,d a,j,q n f
# 10: 6 v,r y,o z t
# results <- data.table(...) # first of your two `results`
all.equal(out, results[,c(1,4,5,2,3)]) # column-order is different
# [1] TRUE
可重现的数据:
set.seed(42)
dt <- data.table(
ID=sample(1:10, 50, replace=TRUE),
A=letters[sample(1:26, 50, replace=TRUE)],
B=letters[sample(1:26, 50, replace=TRUE)],
C=letters[sample(1:26, 50, replace=TRUE)],
D=letters[sample(1:26, 50, replace=TRUE)]
)
head(dt, 3)
# ID A B C D
# <int> <char> <char> <char> <char>
# 1: 1 f u f q
# 2: 5 f v f t
# 3: 1 b s t a
【讨论】:
GeneC,这是否符合您的“单线”期望?它适用于您的真实数据吗? 这对我来说是单行的。将名称(.SD)传递给函数的巧妙技巧!这可能太迟钝而无法合并到可调试代码中,但很高兴看到它是如何完成的。 太钝了?您认为很难将其包含在可调试代码中吗?我发现这比许多人(我在 SO 上看到的)倾向于做的事情更具可读性,lapply
over indices 并在单个参数 anon-func 内部使用 [
-indexing 而不是做这样的事情。
绝对没有冒犯的意思,我喜欢你的解决方案。以上是关于在 data.table 中分配多个 lapplys?的主要内容,如果未能解决你的问题,请参考以下文章