【问题标题】:Purrr filter the nested data based on unnested variable containing character vectorsPurrr 根据包含字符向量的未嵌套变量过滤嵌套数据
【发布时间】:2018-10-11 23:10:29
【问题描述】:

我有类似df3的数据。要重现数据,请运行以下命令:

vec1 <- c("A", "B")
vec2 <- c("A", "B", "C")

df1 <- tibble::tribble(
          ~A, ~B,
          "X", 4L,
          "X", 9L,
          "Y", 5L,
          "Y", 2L,
          "Y", 8L,
          "Y", 2L) %>%
  group_by(A) %>% 
  nest()

df2 <- tibble::tribble(
  ~A, ~C,
  "X", vec1,
  "Y", vec2)

df3 <- df1 %>% left_join(df2, by = "A")

我需要使用以下方式过滤嵌套数据:

df4 <- df3 %>% filter(when C==vec1, B (part of nested data now) < 5 
                      when C==vec2, B (part of nested data now) >4)

或者可能是这样的:

df4 <- df3 %>% map(.$data, ~filter((identicle(.$C, vec1) & B < 5) | 
                                  identical(.$C, vec2) & B >4))

我只有 df3,我想要 df4。我应该如何使用 purrr 进行上述过滤以获得以下所需的 df4 输出。

df11 <- tibble::tribble(
  ~A, ~B,
  "X", 4L,
  "Y", 5L,
  "Y", 8L) %>%
  group_by(A) %>% 
  nest()

df4 <- df11 %>% left_join(df2, by = "A")

【问题讨论】:

  • 我没有关注B 的过滤方式。如果df3$data 由嵌套的B 列组成,例如,您如何检查B &lt; 5?如果B 中的any() 值是&lt; 5?如果您可以显示预期的 df4 结果示例,那将很有帮助。
  • 我想过滤嵌套数据框内的 B,其变量名为“数据”,由嵌套自动创建。我已更新问题以反映所需的输出。
  • 这不是很有效,但你可以match 列出:match(df3$C, list(vec1,vec2)) 例如,这会给你一个决定下一步做什么的标志。
  • 你能建议以 df4

标签: r dplyr tidyverse purrr


【解决方案1】:

不需要 if-else 语句:

mine=df3%>%
   mutate(data=map2(data,match(C,list(vec1,vec2)),
                ~filter_(.x,c("B<=4","B>4")[.y])))
 identical(mine,df4)
[1] TRUE

【讨论】:

    【解决方案2】:

    这是一种不同的方法,它使用unnest 直接处理B 的值,然后替换原始向量。

    library(tidyverse)
    vec1 <- c("A", "B")
    vec2 <- c("A", "B", "C")
    
    df3 <- structure(list(A = c("X", "Y"), data = list(structure(list(B = c(4L, 9L)), .Names = "B", row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame")), structure(list(B = c(5L, 2L, 8L, 2L)), .Names = "B", row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"))), C = list(c("A", "B"), c("A", "B", "C"))), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -2L), .Names = c("A", "data", "C"))
    
    veclist <- list(vec1, vec2)
    df3 %>%
      mutate(vec = match(C, veclist)) %>%
      unnest(data) %>%
      filter(vec == 1 & B < 5 | vec == 2 & B > 4) %>%
      nest(B) %>%
      mutate(C = map(vec, ~ veclist[[.]])) %>%
      as.data.frame()
    #>   A vec data       C
    #> 1 X   1    4    A, B
    #> 2 Y   2 5, 8 A, B, C
    

    reprex package (v0.2.0) 于 2018 年 5 月 1 日创建。

    【讨论】:

      【解决方案3】:

      这是使用map2identical 进行条件检查的一个选项:

      df3 %>% 
          mutate(
              data = map2(
                  data, C, ~ if(identical(.y, vec1)) filter(.x, B < 5) else filter(.x, B > 4)
              )
          ) %>% 
          identical(df4)
      # [1] TRUE
      

      【讨论】:

      • 这行得通。你能帮我用 case_when 做这件事吗?
      • 我不确定你是否可以在这种情况下使用case_when,因为你想返回一个列表而case_when需要一个向量输出。因此ifelse
      猜你喜欢
      • 1970-01-01
      • 2023-02-11
      • 2017-02-04
      • 2021-01-14
      • 2020-03-11
      • 2018-11-02
      • 1970-01-01
      • 2018-11-06
      • 2018-05-25
      相关资源
      最近更新 更多