【问题标题】:Restrict `fill` to last occurrence of pattern将“填充”限制为模式的最后一次出现
【发布时间】:2021-12-12 00:25:42
【问题描述】:

我有这样的数据:

df <- structure(list(line = c("001", "002", "003", "004", "005", "006", 
                              "007", "008", "009", "010", "011", "012", "013", "014"), 
                     utterance = c("((m: both hands", 
                                   "((m: both hands", 
                                   "((i: DH=1, SZ=0", "((i: DH=1, SZ=0", 
                                   "((s: Preface))", "((m: both hands", 
                                   "((m: both hands clasped", 
                                   "((m: both hands clasped", 
                                   "((s: Background))", "((m: enumerating", 
                                   "((m: enumerating", 
                                   "((s: End))", "((i: DH=1, SZ=0", "((m: relax gesture))"
                              )), row.names = c(NA, 14L), class = "data.frame")

我想创建一个新列 storyfill 该列,其中包含与正则表达式模式 \\(\\(s 匹配的列 utterance 中的值。但我希望fill停在与这种模式匹配的最后一个值,即((s: End))

这个fill 命令不会停在那个模式上 - 我怎样才能让fill 停在那个模式上?

library(tidyr)
df %>%
  mutate(story = ifelse(grepl("\\(\\(s", utterance), utterance, NA)) %>%
  fill(story, .direction = "down")
   line               utterance             story
1   001         ((m: both hands              <NA>
2   002         ((m: both hands              <NA>
3   003         ((i: DH=1, SZ=0              <NA>
4   004         ((i: DH=1, SZ=0              <NA>
5   005          ((s: Preface))    ((s: Preface))
6   006         ((m: both hands    ((s: Preface))
7   007 ((m: both hands clasped    ((s: Preface))
8   008 ((m: both hands clasped    ((s: Preface))
9   009       ((s: Background)) ((s: Background))
10  010        ((m: enumerating ((s: Background))
11  011        ((m: enumerating ((s: Background))
12  012              ((s: End))        ((s: End))
13  013         ((i: DH=1, SZ=0        ((s: End))
14  014    ((m: relax gesture))        ((s: End))

希望

   line               utterance             story
1   001         ((m: both hands              <NA>
2   002         ((m: both hands              <NA>
3   003         ((i: DH=1, SZ=0              <NA>
4   004         ((i: DH=1, SZ=0              <NA>
5   005          ((s: Preface))    ((s: Preface))
6   006         ((m: both hands    ((s: Preface))
7   007 ((m: both hands clasped    ((s: Preface))
8   008 ((m: both hands clasped    ((s: Preface))
9   009       ((s: Background)) ((s: Background))
10  010        ((m: enumerating ((s: Background))
11  011        ((m: enumerating ((s: Background))
12  012              ((s: End))        ((s: End))
13  013         ((i: DH=1, SZ=0              <NA>
14  014    ((m: relax gesture))              <NA>

【问题讨论】:

    标签: r dplyr tidyr


    【解决方案1】:

    tidyr::fill 本身不这样做,但你可以再添加一个mutate

    df %>%
      mutate(story = if_else(grepl("\\(\\(s", utterance), utterance, NA_character_)) %>%
      fill(story, .direction = "down") %>%
      mutate(story = if_else(story == last(story) & duplicated(story), NA_character_, story))
    #    line               utterance             story
    # 1   001         ((m: both hands              <NA>
    # 2   002         ((m: both hands              <NA>
    # 3   003         ((i: DH=1, SZ=0              <NA>
    # 4   004         ((i: DH=1, SZ=0              <NA>
    # 5   005          ((s: Preface))    ((s: Preface))
    # 6   006         ((m: both hands    ((s: Preface))
    # 7   007 ((m: both hands clasped    ((s: Preface))
    # 8   008 ((m: both hands clasped    ((s: Preface))
    # 9   009       ((s: Background)) ((s: Background))
    # 10  010        ((m: enumerating ((s: Background))
    # 11  011        ((m: enumerating ((s: Background))
    # 12  012              ((s: End))        ((s: End))
    # 13  013         ((i: DH=1, SZ=0              <NA>
    # 14  014    ((m: relax gesture))              <NA>
    

    这会查找最后一次出现的 story 并删除除第一个以外的所有内容。这假设顺序很重要,并且假设最后一个story 必须包含文字s: End,但如果您愿意,可以相应地更新逻辑。

    仅供参考,我从 ifelse 更改为 if_else,因为它是类型安全的(base::ifelse 不是)。它需要明确使用哪个 NA(有超过六种不同的变体)。

    【讨论】:

      【解决方案2】:

      我们可以使用na.locf

      library(dplyr)
      library(zoo)
      df %>%
        mutate(story = ifelse(grepl("\\(\\(s", utterance), utterance, NA), 
          ind = match("((s: End))", story),
         story = replace(story, seq_len(first(ind)), 
          zoo::na.locf0(story[seq_len(first(ind))])), ind = NULL)
      

      -输出

       line               utterance             story
      1   001         ((m: both hands              <NA>
      2   002         ((m: both hands              <NA>
      3   003         ((i: DH=1, SZ=0              <NA>
      4   004         ((i: DH=1, SZ=0              <NA>
      5   005          ((s: Preface))    ((s: Preface))
      6   006         ((m: both hands    ((s: Preface))
      7   007 ((m: both hands clasped    ((s: Preface))
      8   008 ((m: both hands clasped    ((s: Preface))
      9   009       ((s: Background)) ((s: Background))
      10  010        ((m: enumerating ((s: Background))
      11  011        ((m: enumerating ((s: Background))
      12  012              ((s: End))        ((s: End))
      13  013         ((i: DH=1, SZ=0              <NA>
      14  014    ((m: relax gesture))              <NA>
      

      【讨论】:

        猜你喜欢
        • 2019-12-07
        • 2021-12-09
        • 2013-07-05
        • 2013-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-25
        相关资源
        最近更新 更多