如果名称按组的顺序不同,R data.table 分组操作返回错误值?
Posted
技术标签:
【中文标题】如果名称按组的顺序不同,R data.table 分组操作返回错误值?【英文标题】:R data.table grouped operation returning wrong values if names are not in the same order by group? 【发布时间】:2022-01-17 09:57:38 【问题描述】:我正在data.table
中按组计算操作,其中函数返回每个组的长度相同且名称相同的列表。但是,如果生成的列表的名称并不总是按组的顺序排列,那么最终输出中的值可能会被错误地分配。
这是一个人为的例子来说明这种行为:
f <- function(x, allcols)
l <- floor(log2(length(x)))
y <- c(1:l, l)
names(y) <- paste0(c(rep("n",length(y)-1),"s"), y)
y[setdiff(allcols, names(y))] <- 0
return(as.list(y))
d <- data.table(x = rep(1,30), group = c(rep(1,14), rep(2,16)))
allcols <- c(paste0("n",1:4), paste0("s",3:4))
x1 <- d[group==1,x]
x2 <- d[group==2,x]
f(x1,allcols)
f(x2,allcols)
d[, f(x, allcols), by = group]
您可以看到,单独对组运行时产生的输出与使用 data.table
作为分组操作完成时获得的输出不同。这可能是一个非常具体的用例,但在某些情况下这似乎会产生不正确的输出。这是故意的吗?在这种情况下,避免这种行为的最佳方法是什么?
【问题讨论】:
【参考方案1】:我在你的函数中添加了一行,y <- y[allcols]
。这将根据allcols
中的内容对y
中的输出进行排序。
library(data.table)
f <- function(x, allcols)
l <- floor(log2(length(x)))
y <- c(1:l, l)
names(y) <- paste0(c(rep("n",length(y)-1),"s"), y)
y[setdiff(allcols, names(y))] <- 0
y <- y[allcols]
return(as.list(y))
现在,当您将函数应用于向量和按组应用于data.table
时,输出是相同的。
f(x1, allcols = allcols)
# $n1
# [1] 1
#
# $n2
# [1] 2
#
# $n3
# [1] 3
#
# $n4
# [1] 0
#
# $s3
# [1] 3
#
# $s4
# [1] 0
f(x2, allcols = allcols)
# $n1
# [1] 1
#
# $n2
# [1] 2
#
# $n3
# [1] 3
#
# $n4
# [1] 4
#
# $s3
# [1] 0
#
# $s4
# [1] 4
d[, f(x = x, allcols), by = group]
# group n1 n2 n3 n4 s3 s4
# 1: 1 1 2 3 0 3 0
# 2: 2 1 2 3 4 0 4
我不知道为什么您的原始代码不起作用。但我的猜测是这与rbindlist
有关,它结合了数据框列表。我认为它应该组合基于相同列名的行,就像来自dplyr
的bind_rows
所做的那样。但似乎默认行为是按位置组合行。因此,您的函数以相同顺序为每个组返回结果变得很重要。查看?rbindlist
和use.names
的解释了解更多详情。假设group
应用函数在后台调用rbindlist
,我认为如果列顺序不一样应该返回警告。但事实并非如此。
【讨论】:
以上是关于如果名称按组的顺序不同,R data.table 分组操作返回错误值?的主要内容,如果未能解决你的问题,请参考以下文章