如果名称按组的顺序不同,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 &lt;- 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 有关,它结合了数据框列表。我认为它应该组合基于相同列名的行,就像来自dplyrbind_rows 所做的那样。但似乎默认行为是按位置组合行。因此,您的函数以相同顺序为每个组返回结果变得很重要。查看?rbindlistuse.names 的解释了解更多详情。假设group应用函数在后台调用rbindlist,我认为如果列顺序不一样应该返回警告。但事实并非如此。

【讨论】:

以上是关于如果名称按组的顺序不同,R data.table 分组操作返回错误值?的主要内容,如果未能解决你的问题,请参考以下文章

在单个 R data.table 中按组有效地定位

R - 按组的累积产品和总和

markdown 线性分区用于按组的字母顺序排序,例如A-C

按组的 DB2 逗号分隔输出

在 data.table 中按组划分的分位数

如何按 data.table 中的十分位组计算统计信息