【问题标题】:R data.table grouped operation returning wrong values if names are not in the same order by group?如果名称按组的顺序不同,R data.table 分组操作返回错误值?
【发布时间】: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 作为分组操作完成时获得的输出不同。这可能是一个非常具体的用例,但在某些情况下这似乎会产生不正确的输出。这是故意的吗?在这种情况下,避免这种行为的最佳方法是什么?

【问题讨论】:

    标签: r 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,我认为如果列顺序不一样应该返回警告。但事实并非如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 2022-11-15
      • 1970-01-01
      • 1970-01-01
      • 2010-12-08
      • 2019-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多