首页 文章

RunID的dplyr组将值传递给下一组

提问于
浏览
2

我有要分组的数据,执行计算然后是最终结果,将其用于下一组中的计算 .

我们使用条件语句并按组执行计算,例如:

# Example Data 
condition <- c(0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,0)
col_a <- c(0,0,0,2,3,4,0,0,0,2,4,5,6,0,0,0,0,0,0,0,0,1,2,0)
col_b <- c(0,0,0,10,131,14,0,0,0,22,64,75,96,0,0,0,0,0,0,0,0,41,52,0)
df <- data.frame(condition,col_a,col_b)

这是进行计算的代码,按RunID分组

# Group by RunID
# Perform calculations 
# Last value, brought forward to next group
require(dplyr) 
output <- df %>%
  dplyr::mutate(RunID = data.table::rleid(condition)) %>%
  group_by(RunID) %>%
  dplyr::mutate(calculation = ifelse(condition == 0,0, ifelse(row_number() == n(),first(col_a) * last(col_b),0))) %>%

dplyr :: mutate(last.tag = ifelse(condition == 0,0,ifelse(row_number()== n(),2,0)))%>%#添加助手ID号 . 在回答ungroup()%>%select(-RunID)输出< - data.frame(输出)head(输出,15)中帮助for循环

随着输出:

condition col_a col_b calculation
1          0     0     0           0
2          0     0     0           0
3          0     0     0           0
4          1     2    10           0
5          1     3   131           0
6          1     4    14          28
7          0     0     0           0
8          0     0     0           0
9          0     0     0           0
10         1     2    22           0
11         1     4    64           0
12         1     5    75           0
13         1     6    96         192
14         0     0     0           0
15         0     0     0           0

我想做的是 . 在第一个结果上,计算列中的结果是28.我想将该值传递给下一个组并插入col_a,第10行(28个替换,2) . 然后随着该值的更新 . 第二组计算结果为96 * 28 = 2688对比(96 * 2 = 192)

如上所述,结转将始终插入每组的第一行 .

预期产量:

condition col_a col_b calculation
1          0     0     0           0
2          0     0     0           0
3          0     0     0           0
4          1     2    10           0
5          1     3   131           0
6          1     4    14          28
7          0     0     0           0
8          0     0     0           0
9          0     0     0           0
10         1     28    22           0
11         1     4    64           0
12         1     5    75           0
13         1     6    96         2688
14         0     0     0           0
15         0     0     0           0

其他解决方案:

我将子集删除所有0,s . 添加了识别到每个组底部的2个数字以进行连续运行,然后使用for循环进行抓取和替换 . 可能不是最优雅,但似乎工作:

# Subset to remove all 0 
subset.no.zero <- subset(output,condition >0)
# Loop to move values
for (i in 1:nrow(subset.no.zero)) {
  temp <- ifelse(subset.no.zero$last.tag[i-1] == 2, subset.no.zero$calculation[i-1],subset.no.zero$col_a[i])
  subset.no.zero$new_col_a[i] <- data.frame(temp)
}

# Re join by index no.
final_out <- full_join(output,subset.no.zero, by="index")

1 回答

  • 4

    我只能提供data.table解决方案,但也许您可以将逻辑转换为dplyr:

    library(data.table)
    setDT(df)
    
    #first group multiply 2 and 14
    df[rleid(condition) %in% 1:2 & condition != 0, 
       calculation := {
         res <- rep(NA_real_, .N)
         res[.N] <- col_b[.N] * col_a[1]
         res
       }
       ]
    
    #all groups other than first copy col_b
    df[, calculation := if (condition[.N] != 0) {
      if(is.na(calculation[.N])) {
        res <- rep(NA_real_, .N)
        res[.N] <- col_b[.N]
        res
      } else calculation
    } else NA_real_,
    by = rleid(condition)
    ]    
    
    #cumulative product
    df[!is.na(calculation), 
       calculation := cumprod(calculation)] 
    
    #copy values into col_a
    df[i = df[, .(condition = condition[1], i = .I[1]), 
              by = rleid(condition)][condition == 1L][-1, i], #finds rows to replace values
       col_a := head(df[!is.na(calculation), calculation], -1) 
       ]
    
    #    condition col_a col_b calculation
    # 1:         0     0     0          NA
    # 2:         0     0     0          NA
    # 3:         0     0     0          NA
    # 4:         1     2    10          NA
    # 5:         1     3   131          NA
    # 6:         1     4    14          28
    # 7:         0     0     0          NA
    # 8:         0     0     0          NA
    # 9:         0     0     0          NA
    #10:         1    28    22          NA
    #11:         1     4    64          NA
    #12:         1     5    75          NA
    #13:         1     6    96        2688
    #14:         0     0     0          NA
    #15:         0     0     0          NA
    #16:         0     0     0          NA
    #17:         0     0     0          NA
    #18:         0     0     0          NA
    #19:         0     0     0          NA
    #20:         0     0     0          NA
    #21:         0     0     0          NA
    #22:         1  2688    41          NA
    #23:         1     2    52      139776
    #24:         0     0     0          NA
    #    condition col_a col_b calculation
    

相关问题