【问题标题】:Replace sets of rows in a tibble with a single row用单行替换 tibble 中的行集
【发布时间】:2021-05-23 04:06:21
【问题描述】:

Replace sets of rows in a data.table with a single row 上的 data.table 有一个类似的问题,但我正在寻找 tidyverse 中的等效解决方案。所以,我有一个像这样的小标题:

DT <- tibble (
  id=c(1,1,1,1,2,2,2,2),
  location = c("a","b","c","d","a","b","d","e"),
  seq = c(1,2,3,4,1,2,3,4))

对于每个 id,我想查找序列 b、c、d,如果有这样的事情,我想用单行替换 b 和 c 的行,比如说 z。其他变量的值应保留前一个 b 的值(在本例中为 idseq

所以在这种情况下,新的小标题应该是

DT.Tobe <- tibble (
  id=c(1,1,1,2,2,2,2),
  place = c("a","z","d","a","b","d","e"),
  seq = c(1,2,4,1,2,3,4))

我什至找不到这个的起点......

【问题讨论】:

    标签: r replace tidyverse


    【解决方案1】:

    一种可能的选择是使用 for 循环。这是我的伪代码。

    for (i in nrows(DT)){ # Repeat this if statement for each row in your DT
    
        if (place[i] == "b & place[i+1] == "c"){ # if the first item is B and the second item is C
    
            DT <- DT %>%
                  dplyr::replace(place[i] == "z") # Replaces item B with the z character
            
            DT[-(i+1)] # Deletes item C's row
        }
    
    }
    

    The Dplyr cheat sheet 有一些有用的函数,它们可能有助于为该伪代码的 if 语句部分找到合适的工具。

    你有什么想法?

    【讨论】:

    • 谢谢@Sarah,理想情况下我宁愿避免for循环...
    【解决方案2】:
    library(dplyr)
    # library(zoo) # rollapply
    DT %>%
      group_by(id) %>%
      mutate(
        isseq = zoo::rollapply(location, 3, FUN = function(z) identical(z, c("b", "c", "d")), align = "left", partial = TRUE), 
        isseq = isseq | lag(isseq, default = FALSE)
      ) %>%
      group_by(id, isseq) %>%
      summarize(
        across(everything(), ~ {
          if (cur_group()$isseq) { 
            if (cur_column() == "location") "z" else first(.)
          }  else .
        })
      ) %>%
      ungroup() %>%
      select(-isseq)
    # # A tibble: 7 x 3
    #      id location   seq
    #   <dbl> <chr>    <dbl>
    # 1     1 a            1
    # 2     1 d            4
    # 3     1 z            2
    # 4     2 a            1
    # 5     2 b            2
    # 6     2 d            3
    # 7     2 e            4
    

    顺序改变了,因为group_by(isseq) 倾向于将“喜欢”放在一起。这应该很容易重新排序(假设"seq" 是有意义的)或预先添加一个订单变量并在以后使用它。

    如果单个id 有可能有多个这样的序列(如果是这样,说点什么),那么这里也需要运行长度编码(以区分相同的不同b-c-d 序列id)。

    【讨论】:

    • 谢谢@r2evans,只是对参数位置==“a”的澄清。子序列 b-c-d 可以存在于序列中的任何地方,并且一个序列可能根本不包含 a(它也可能从另一个位置开始)。如果我们删除条件的lag(location == "a", default = FALSE) &amp;部分呢?
    • 是的,删除== 'a' 组件同样有效。不知道为什么我会这样推断,补救了。
    • 我希望 a-b-c-d-a-b-c-dboth b-c-d 序列减少为单个 z 行,而不是每个 b-c-d 序列一个 z 行,并且这个是连续的还是间断的。
    猜你喜欢
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 2019-12-07
    • 1970-01-01
    • 2019-05-04
    相关资源
    最近更新 更多