【问题标题】:Make dplyr::if_else() return a NA value使 dplyr::if_else() 返回一个 NA 值
【发布时间】:2018-10-10 08:33:41
【问题描述】:

在约会时使用dplyr::if_else(),我想返回NA - 但R 中没有NA_date_ 或NA_double_(我知道- 或列出here)?如何执行以下代码:

ep <- df %>%
  group_by(id, episode) %>%
  summarise(ep_adm = min(adm, na.rm = T),
            ep_sepa = if_else(all(is.na(sepa)),
                             if_else(all(is.na(adm)), NA, max(adm, na.rm = T)),
                             max(sepa, na.rm = T)))

没有错误?

summarise_impl(.data, dots) 中的错误:评估错误:false 必须是逻辑类型,而不是双精度类型。

这个问题的动机是每个病人 id 的行将被分类到一个护理集(数据来自不同的数据源,其中一个不包括 sepa 日期),由处理group_by()。然后我想获得剧集的开始和结束日期,ep_adm 和 ep_sepa。规则是,如果所有的分离日期都是NA,则使用最后的入院日期,否则使用最后的分离日期。

预期输出中的代码有效,但我希望删除最后两行代码(使用dplyr::if_else(),因为这应该返回一个&lt;date&gt; 对象)。

预期输出:

ep <- df %>%
  group_by(id, episode) %>%
  summarise(ep_adm = min(adm, na.rm = T),
            ep_sepa = ifelse(all(is.na(sepa)),
                             ifelse(all(is.na(adm)), NA, max(adm, na.rm = T)),
                             max(sepa, na.rm = T)))
ep$ep_adm <- as.Date(ep$ep_adm, origin = "1970-01-01")
ep$ep_sepa <- as.Date(ep$ep_sepa, origin = "1970-01-01")

# # A tibble: 4 x 4
# # Groups:   id [?]
#      id episode ep_adm     ep_sepa   
#   <dbl>   <int> <date>     <date>    
# 1     1       1 2002-06-28 2002-07-05
# 2     1       2 2002-08-25 2002-08-25
# 3     1       3 2003-06-26 2003-06-26
# 4     1       4 2007-04-10 2007-04-11

left_join(df, ep, by = c("id", "episode"))

# # A tibble: 8 x 6
#      id episode adm        sepa       ep_adm     ep_sepa   
#   <dbl>   <int> <date>     <date>     <date>     <date>    
# 1     1       1 2002-06-28 NA         2002-06-28 2002-07-05
# 2     1       1 2002-06-28 NA         2002-06-28 2002-07-05
# 3     1       1 2002-06-28 2002-07-05 2002-06-28 2002-07-05
# 4     1       1 2002-06-28 2002-07-05 2002-06-28 2002-07-05
# 5     1       2 2002-08-25 NA         2002-08-25 2002-08-25
# 6     1       3 2003-06-26 NA         2003-06-26 2003-06-26
# 7     1       4 2007-04-10 NA         2007-04-10 2007-04-11
# 8     1       4 2007-04-10 2007-04-11 2007-04-10 2007-04-11

数据

df <- structure(list(id = c(1, 1, 1, 1, 1, 1, 1, 1), episode = c(1L, 
1L, 1L, 1L, 2L, 3L, 4L, 4L), adm = structure(c(11866, 11866, 
11866, 11866, 11924, 12229, 13613, 13613), class = "Date"), sepa = structure(c(NA, 
NA, 11873, 11873, NA, NA, NA, 13614), class = "Date")), row.names = c(NA, 
-8L), class = c("tbl_df", "tbl", "data.frame"))

【问题讨论】:

  • 您能分享一下您的预期输出吗?
  • 你能解释一下添加ep_sepa的规则吗?我不太确定我是否理解您要执行的操作:例如,is.na(.$sepa) 会检查 NA 跨 sepa 列中 所有 条目的条目,而不是在您定义的组中。那是你想做的吗?如果您可以详细说明规则,在我看来case_when 解决方案可能更容易(而不是嵌套的if_elses)。

标签: r date if-statement dplyr


【解决方案1】:

编辑

对于更新后的数据集,似乎我们可以从 sepa 和 adm 列组合中获取 max 日期。

df %>% 
   group_by(id, episode) %>% 
   summarise(ep_adm = min(adm, na.rm = T), 
             ep_sepa = max(c(sepa, adm), na.rm = TRUE))

#     id episode ep_adm     ep_sepa   
#   <dbl>   <int> <date>     <date>    
#1     1       1 2002-06-28 2002-07-05
#2     1       2 2002-08-25 2002-08-25
#3     1       3 2003-06-26 2003-06-26
#4     1       4 2007-04-10 2007-04-11

原答案

如果我正确理解了您的代码,您可以使用coalesce 减少它。对于ep_sepa 列,我们从max(sepa) 和max(adm) 列获得第一个非NA 条目。

library(dplyr)

df %>%
   group_by(rootnum, episode) %>%
   summarise(ep_adm = min(adm, na.rm = T), 
             ep_sepa = coalesce(max(sepa), max(adm)))



#  rootnum episode  ep_adm     ep_sepa   
#    <dbl>   <int> <date>     <date>    
#1       1       1 2002-06-28 2002-06-28
#2       1       2 2002-08-25 2002-08-25
#3       1       3 2003-06-26 2003-06-26
#4       1       4 2007-04-10 2007-04-10
#5       2       2 2012-06-26 2012-06-26

【讨论】:

  • 感谢@Ronak,我找到了一个更完整的示例数据(抱歉,我认为另一个就足够了)。我需要在我的最小值和最大值中包含na.rm = T,当我也添加这些你的答案时,我会收到我试图消除的警告。我已经更新了我的 OP,使其更加完整。
  • @Paul df %&gt;% group_by(id, episode) %&gt;% summarise(ep_adm = min(adm, na.rm = T), ep_sepa = max(c(sepa, adm), na.rm = TRUE)) 这似乎给出了您预期的输出,但我仍然不确定是否还有其他我遗漏的案例?
  • @Paul 此外,ifelse 使ep_sepa 失去了它的类。您可以在您尝试过的链中添加另一个命令。 df %&gt;% group_by(id, episode) %&gt;% summarise(ep_adm = min(adm, na.rm = T), ep_sepa = ifelse(all(is.na(sepa)), ifelse(all(is.na(adm)), NA, max(adm, na.rm = T)), max(sepa, na.rm = T))) %&gt;% mutate_at(vars(ep_sepa), as.Date) 将再次将其转换为 Date 类。
  • 我认为 max(c(sepa, adm), na.rm = TRUE) 可能会这样做,似乎我把事情复杂化了。明天上班的时候我去测试一下。感谢您今天的所有帮助!
猜你喜欢
  • 1970-01-01
  • 2019-10-20
  • 2022-01-15
  • 1970-01-01
  • 2021-10-22
  • 1970-01-01
  • 2018-06-05
  • 1970-01-01
  • 2019-03-19
相关资源
最近更新 更多