r - 如何在 R 中用中间结果改变新列,累积或减少

标签 r tidyverse reduce accumulate

我有一个数据集 my_df 具有以下结构(dput 添加在问题的末尾)

> my_df
   group_id other_id    case
1         1        1     add
2         1        1     add
3         1       11     add
4         1        1 replace
5         1       11 replace
6         1        1 replace
7         1       10     add
8         1       10 replace
9         2        2     add
10        2       10     add
11        2       10 replace
12        2        2 replace
13        2        3     add
14        2        3 replace

我想做的(以 tidyverse 的方式)是创建一个新列,比如 collection,其中 other_id 将为 group_id< 上的每个 group_by 存储 基于这两个条件-

  • 如果 case 被添加,那么当前行的 Other_id 将被粘贴到该列的前一个值中

  • 如果 case == 'replace',则当前行的 other_id 将替换为来自上一行计算(累积)值的 ""(无)。

我想要的结果是这样的

> result
   group_id other_id    case collection
1         1        1     add         1,
2         1        1     add       1,1,
3         1       11     add    1,1,11,
4         1        1 replace      1,11,
5         1       11 replace         1,
6         1        1 replace          
7         1       10     add        10,
8         1       10 replace          
9         2        2     add         2,
10        2       10     add      2,10,
11        2       10 replace         2,
12        2        2 replace          
13        2        3     add         3,
14        2        3 replace          

显然每组的末尾都会有空白,因为 my_df 已经这样排列/排序了。

我正在尝试 accumulatereduce 但我只能生成/累积 case == 'add' 的值,我无法在此管道中应用 str_replace(如下)。此外,我希望 other_id 的值将在 case == 'add' 时粘贴到 collection 中,但仅粘贴到先前出现的值是否可能属于不同的情况(结果中的第 7 和 13 行)。

我尝试的语法只部分起作用

library(tidyverse)
my_df %>% group_by(group_id) %>%
  mutate(collection = case_when(case == "add" ~ accumulate(other_id, paste, sep=", "),
                                case == "replace" ~ "?"))

# A tibble: 14 x 4
# Groups:   group_id [2]
   group_id other_id case    collection            
   <chr>    <chr>    <chr>   <chr>                 
 1 1        1        add     1                     
 2 1        1        add     1, 1                  
 3 1        11       add     1, 1, 11              
 4 1        1        replace ?                     
 5 1        11       replace ?                     
 6 1        1        replace ?                     
 7 1        10       add     1, 1, 11, 1, 11, 1, 10
 8 1        10       replace ?                     
 9 2        2        add     2                     
10 2        10       add     2, 10                 
11 2        10       replace ?                     
12 2        2        replace ?                     
13 2        3        add     2, 10, 10, 2, 3       
14 2        3        replace ?

感谢期待。

样本输入是

my_df <- structure(list(group_id = c("1", "1", "1", "1", "1", "1", "1", 
"1", "2", "2", "2", "2", "2", "2"), other_id = c("1", "1", "11", 
"1", "11", "1", "10", "10", "2", "10", "10", "2", "3", "3"), 
    case = c("add", "add", "add", "replace", "replace", "replace", 
    "add", "replace", "add", "add", "replace", "replace", "add", 
    "replace")), row.names = c(NA, -14L), class = "data.frame")

最佳答案

我的想法与@Cettt 相同——使用accumulate2。这是一个使用正则表达式处理尾随逗号的选项。

addOrRemove = function(acc, other_id, case) {
  if(case == "add") {
    ifelse(acc == "", other_id, paste(acc, other_id, sep = ", "))
  } else {
    sub(
      paste0("((?<=^| )", other_id, "(, ))|((^|(, ))", other_id, "$)"), 
      "", 
      acc
      ,
      perl = TRUE
    )
  }
}


my_df %>% 
  group_by(group_id) %>%
    mutate(collection = unlist(accumulate2(other_id, case[-1], addOrRemove))
)

# A tibble: 14 x 4
# Groups:   group_id [2]
   group_id other_id case    collection
   <chr>    <chr>    <chr>   <chr>     
 1 1        1        add     "1"       
 2 1        1        add     "1, 1"    
 3 1        11       add     "1, 1, 11"
 4 1        1        replace "1, 11"   
 5 1        11       replace "1"       
 6 1        1        replace ""        
 7 1        10       add     "10"      
 8 1        10       replace ""        
 9 2        2        add     "2"       
10 2        10       add     "2, 10"   
11 2        10       replace "2"       
12 2        2        replace ""        
13 2        3        add     "3"       
14 2        3        replace ""  

关于r - 如何在 R 中用中间结果改变新列,累积或减少,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65405560/

相关文章:

R:根据列中的类别从数据框中删除重复项

r - 计算一行中第一个和最后一个观察值之间的差异,其中每行都不同

java - 使用reduce组合函数

python - Python : like reduce but giving the list of intermediate results 中的缩减列表

重新排列不平衡的时间序列数据

r - 当此值等于 1 时,将下 n 个值设置为零

r - 如何检测是否为裸变量或字符串

r - gtsummary::tbl_regression 使用 pool_and_tidy_mice() 和 tidy_standardize()

javascript - 如何使用_.reduce或原生reduce对对象进行求和和排序?

r - 使用R映射博客之间的链接网络?