【问题标题】:Filter dataframe on sequence of rows conditional on two columns在以两列为条件的行序列上过滤数据框
【发布时间】:2023-04-11 12:32:01
【问题描述】:

我有这种类型的数据,其中Sequ 列中的数值定义了一个行序列,Q 中的字符值命名了序列的类型:

df <- data.frame(
  Line = 1:12,
  Speaker = c(NA, "ID01.A", NA, "ID01.B", "ID07.A", NA, "ID33.B", 
              "ID33.A", "ID33.C", NA, "ID77.A", "ID77.C"),
  Utterance = c(NA, "Who did it?", "(1.99)", "Peter did.", "Hello!", NA, "So you're coming?", 
                "erm", "Yes, sure.", "(0.22)", "Good night?", "Yeah, sleep well"),
  Sequ = c(NA,1,1,1, NA,NA, 2,2,2, NA, 3,3),
  Q = c(NA, "q_wh", "", "", NA, NA, "q_decl", "", "", NA, "q_wh", "")
)

我想对那些 Sequ 数值(而不是 NA)和其中 Q == q_wh 的数据框进行子集化。我可以使用na_if 然后fill 来完成这项任务:

library(tidyr)
df %>%
  mutate(Q = na_if(Q, "")) %>%
  fill(Q, .direction = "down") %>%
  filter(!is.na(Sequ) & Q == "q_wh")
  Line Speaker        Utterance Sequ    Q
1    2  ID01.A      Who did it?    1 q_wh
2    3    <NA>           (1.99)    1 q_wh
3    4  ID01.B       Peter did.    1 q_wh
4   11  ID77.A      Good night?    3 q_wh
5   12  ID77.C Yeah, sleep well    3 q_wh

但是有没有另一种更直接的方法,不绕道na_iffill,过滤df

编辑

我找到了一个没有fillna_if 的解决方案:

df %>%
  group_by(Sequ) %>%
  mutate(Q = Q[!Q==""]) %>%
  filter(!is.na(Sequ) & Q == "q_wh")

【问题讨论】:

    标签: r tidyr


    【解决方案1】:

    使用ave"Sequ" 替换为第一个相应的Q,最后是subset

    df[!is.na(df$Sequ), ] |>
      transform(Q=ave(Q, Sequ, FUN=\(x) x[1])) |>
      subset(!is.na(Sequ) & Q == 'q_wh')
    #    Line Speaker        Utterance Sequ    Q
    # 2     2  ID01.A      Who did it?    1 q_wh
    # 3     3    <NA>           (1.99)    1 q_wh
    # 4     4  ID01.B       Peter did.    1 q_wh
    # 11   11  ID77.A      Good night?    3 q_wh
    # 12   12  ID77.C Yeah, sleep well    3 q_wh
    

    注意:R version 4.1.2 (2021-11-01).

    或者使用tidyverse方言。

    library(magrittr)
    df[!is.na(df$Sequ), ] %>%
      dplyr::mutate(Q=ave(Q, Sequ, FUN=\(x) x[1])) %>%
      dplyr::filter(!is.na(Sequ) & Q == 'q_wh')
    #   Line Speaker        Utterance Sequ    Q
    # 1    2  ID01.A      Who did it?    1 q_wh
    # 2    3    <NA>           (1.99)    1 q_wh
    # 3    4  ID01.B       Peter did.    1 q_wh
    # 4   11  ID77.A      Good night?    3 q_wh
    # 5   12  ID77.C Yeah, sleep well    3 q_wh
    

    数据:

    df <- structure(list(Line = 1:12, Speaker = c(NA, "ID01.A", NA, "ID01.B", 
    "ID07.A", NA, "ID33.B", "ID33.A", "ID33.C", NA, "ID77.A", "ID77.C"
    ), Utterance = c(NA, "Who did it?", "(1.99)", "Peter did.", "Hello!", 
    NA, "So you're coming?", "erm", "Yes, sure.", "(0.22)", "Good night?", 
    "Yeah, sleep well"), Sequ = c(NA, 1, 1, 1, NA, NA, 2, 2, 2, NA, 
    3, 3), Q = c(NA, "q_wh", "", "", NA, NA, "q_decl", "", "", NA, 
    "q_wh", "")), class = "data.frame", row.names = c(NA, -12L))
    

    【讨论】:

    • 我有一个旧版本的 R。我猜|&gt; 相当于 %&gt;%,但什么相当于 `FUN=` 中的反斜杠?
    • @ChrisRuehlemann 是的,|&gt; 是新的基础管道,将 \ 替换为 function 即可。不过,我建议您或您的管理员更新 R。请注意,我已经更新了 tidyverse 版本。
    • 谢谢。我赞成该解决方案。然而问题是Q 列不能填充诸如q_wh 之类的值;在序列的开头必须有一个这样的值。 (这也是我的“填充”解决方案不正确的原因。)
    • @ChrisRuehlemann 你能举一个我们的解决方案会失败的例子吗?
    • 不,只是我需要在转换后对数据进行后处理,这样不填满所有Q行会方便得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 2020-11-21
    • 2013-12-03
    • 2020-12-22
    • 1970-01-01
    • 2023-01-04
    • 1970-01-01
    相关资源
    最近更新 更多