【问题标题】:Adding columns sums in dataframe row wise conditional on a dummy以虚拟为条件在数据帧行中添加列总和
【发布时间】:2018-02-04 13:49:20
【问题描述】:

我想一次将我的数据帧的列的总和添加一行,以具有二进制变量的另一列为条件。

因此,对于每一行,我想为对应行中的二进制变量具有相同值的所有行计算其上方整个列的总和。

这是一个例子:

dummy var1  var2
1     x1     y1
0     x2     y2
0     x3     y3
1     x4     y4

我的目标是获得这个:

dummy var1     var2
1     x1       y1
0     x2       y2
0     x3+x2    y3+y2
1     x4+x1    y4+y1

我之前曾针对简化版本 (Adding columns sums in dataframe row wise) 提出过这个问题,我只是在没有条件的情况下添加了上面的所有值。有没有办法合并这个条件?

【问题讨论】:

  • 你可以使用这里提到的ave函数stackoverflow.com/questions/16850207/…
  • 那行得通。有没有一种优雅的方法可以将其应用于整个数据框。使用 ave 我可以做到这一点: df$newVar
  • 我可以在 apply 中使用它作为我选择的功能吗?
  • 对应行的值是否相同?您的意思是如果在第 5 行中虚拟是 1,那么 var1 将是 x4+x1+x5,而 var2 是 y4+y5+y1?或者所有具有相同值的虚拟行具有相同的对应值?它们是两种不同的算法。
  • 您的ave 答案看起来很完美。你想如何应用它?您是否担心扩展到超过两列而不将它们全部写出来?

标签: r dataframe apply


【解决方案1】:

data.table::rleid 会给你你想要的分组。如果将数据框转换为 data.table,则如下所示:

(注意:这假定您的文本是准确的,而您的示例不正确:它按dummy 列中的连续 相等值分组。)

library(data.table)
setDT(your_data)
your_data[, id := rleid(dummy)][
  , c("var1", "var2") := .(cumsum(var1), cumsum(var2)), by = id
]

如果您需要对一堆列执行此操作,请如上所述设置id,定义列向量,然后:

cols = c("var1", "var2", "var3", ...)
your_data[, (cols) := lapply(.SD, cumsum), by = id, .SD = cols]

如果您只想按虚拟列分组,忽略连续性,那么您的问题is an exact duplicate of this one,您可以这样做:

setDT(your_data)
your_data[, c("var1", "var2") := .(cumsum(var1), cumsum(var2)), by = dummy]

【讨论】:

  • 好答案,我很少使用data.table,我应该熟悉它。
  • 是否可以在不写所有列名的情况下通过虚拟列使用较低的组(我有超过 50 列)。
  • 因此,您的较低选择(虚拟组)可以完美运行,但是在传递列向量时我无法使其正常工作。例如,如果我定义: cols=c("var1", "var2") 然后运行 ​​your_data[, cols := .(cumsum(var1), cumsum(var2)), by = dummy] 数据保持不变。
  • 哦,我刚刚在您的帖子中看到我忘记了括号。没关系。
【解决方案2】:

你可以使用Reduce:

fun=function(x)Reduce(function(x,y)paste0(y,"+",x),x,accumulate = T)
sapply(dat[-1],function(x)ave(x,dat[,1],FUN = fun))
     var1    var2   
[1,] "x1"    "y1"   
[2,] "x2"    "y2"   
[3,] "x3+x2" "y3+y2"
[4,] "x4+x1" "y4+y1"

如果这些只是值,那么你可以这样做:

#Example data
dat2=data.frame(dummy=dat[,1],var1=c(1,2,10,20),var2=c(10,20,50,3))

使用什么:

sapply(dat2[-1],function(x)ave(x,dat2[,1],FUN=cumsum))
     var1 var2
[1,]    1   10
[2,]    2   20
[3,]   12   70
[4,]   21   13

【讨论】:

    【解决方案3】:

    这里已经有一些很好的答案。这是使用dplyr的解决方案:

    data.frame(dummy = c(1L,0L,0L,1L), var1 = c(1L,2L,4L,6L), var2 = c(100L,20L,30L,400L)) %>%
        group_by(dummy) %>%
        mutate_all(funs(cumsum))
    
    # A tibble: 4 x 3
    # Groups:   dummy [2]
      dummy  var1  var2
      <dbl> <dbl> <dbl>
    1  1.00  1.00 100  
    2  0     2.00  20.0
    3  0     6.00  50.0
    4  1.00  7.00 500  
    

    【讨论】:

      【解决方案4】:

      嗯,我不认为你可以使用一个简单的函数来做到这一点,至少从我的经验来看是这样。所以我建议写一个函数如下:

      sum_new_df  <- function(df){
          new_df <- df[,-1]
          for (i in 1:nrow(df)){
              for (j in (i+1):nrow(df)){
                  if (df$dummy[i] == df$dummy[j]){
                      new_df[j,] <- df[,-1][j,] + df[,-1][j,]
                  }    
              }
          }
      }
      

      此函数只能通过增加行数来总结相同虚拟对象的行值。所以如果那是一个大的data.frame,那么这个值就会像金字塔一样。

      【讨论】:

      • 查看我对 2 行 data.table 版本的回答
      猜你喜欢
      • 2018-03-09
      • 2020-11-22
      • 2013-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2019-05-05
      相关资源
      最近更新 更多