【问题标题】:Convert if then construct to case_when in the nested data using purrr map2使用 purrr map2 将嵌套数据中的 if then 构造转换为 case_when
【发布时间】:2018-05-02 01:08:34
【问题描述】:

这是我的数据:

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

df1 <- 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"))

这是我的代码:

df2 <- df1 %>% mutate(data = map2(data, C, ~ if(identical(.y, vec1)) filter(.x, B < 5) else filter(.x, B > 4)))

为了方便扩展条件的数量,我想将上面代码中的 if else 构造转换为 case_when 构造。我怎样才能做到这一点?

【问题讨论】:

  • 我相信您错过了数据中的vec1
  • @raymkchow 我的错,现在添加了这些。感谢您指出!

标签: r dplyr tidyverse purrr


【解决方案1】:

为什么需要case when

试试:

m=df1%>%
  mutate(filt=map2(data,match(C,list(vec1,vec2)),
               ~filter_(.x,c("B<=4","B>4")[.y])))

   m
# A tibble: 2 x 4
  A     data             C         filt            
  <chr> <list>           <list>    <list>          
1 X     <tibble [2 x 1]> <chr [2]> <tibble [1 x 1]>
2 Y     <tibble [4 x 1]> <chr [3]> <tibble [2 x 1]>

如果您希望它与您的 df2 相同,只需替换 data 列:

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

如果条件太多,你可以在外面创建。条件的顺序很重要:顺序或条件应与向量的顺序相匹配,例如:

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

【讨论】:

  • 很抱歉回复延迟! filter_ 似乎是不推荐使用的功能,将来会起作用吗?如果不太可能,我们在 dplyr 中是否有未弃用的 filter_ 等效/版本?
  • Filter_ 未被弃用,.. 当您需要非名称/符号参数时使用它。例如还有 mutate_etc...
  • 好的,这条新闻提到了那种东西! github.com/tidyverse/dplyr/blob/master/NEWS.md。但是,这是一个优雅的答案。谢谢!
【解决方案2】:

不幸的是,在这种情况下,我不知道你是否可以使用case_when。文档声明它返回一个向量并进行检查以确保所有元素都是相同的类型(如 R 中的向量所要求的那样)。这与基础ifelse 不同,例如,它将强制转换为字符。由于您返回的是列表而不是向量,因此所有元素都是不同的类型,case_when 将不起作用。如果您有许多不同的 vec 以及需要处理的相关操作,您可能需要指定更长的 if else if 链。

【讨论】:

  • 好的,我喜欢 case _hen,因为与 if_else 链相比,我很容易理解这个结构。
  • 是的,在这种情况下,您将函数应用于列表的每个元素,而 case_when 将整个向量作为输入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-24
  • 2021-08-26
相关资源
最近更新 更多