【问题标题】:Fill a column with one of four date columns based on another R用基于另一个 R 的四个日期列之一填充一列
【发布时间】:2022-08-23 12:20:46
【问题描述】:

我有一个像这样有 5 列的 DF;

A  B  Date1 Date2 Date3 Date4
1       x     NA    NA    NA
2      NA     y     NA    NA
3      NA    NA     z     NA  
4      NA    NA    NA     f

我想使用 dplyr 包和 case_when() 函数来说明这样的事情

df <- df %>%
    mutate(B = case_when(
     A == 1 ~ B == Date1,
     A == 2 ~ B == Date2,
     A == 3 ~ B == Date3,
     A == 4 ~ B == Date4))

基本上基于 A 的值,我想用 4 个日期列之一填充 B。

A是类字符,B和Date都是Date类。

问题是当我将它应用于数据框时,它根本不起作用。它返回 NA 并将 B 的类更改为布尔值。我正在使用 R 版本 4.1.2。任何帮助表示赞赏。

  • 您的case_when 语法错误,我们不会在其中使用==,只需A == 1 ~ Date1 就足够了。

标签: r dataframe dplyr


【解决方案1】:

您可以使用coalesce() 查找第一个非缺失元素。

library(dplyr)

df %>%
  mutate(B = coalesce(!!!df[-1]))

#   A Date1 Date2 Date3 Date4 B
# 1 1     x  <NA>  <NA>  <NA> x
# 2 2  <NA>     y  <NA>  <NA> y
# 3 3  <NA>  <NA>     z  <NA> z
# 4 4  <NA>  <NA>  <NA>     f f

上面的代码只是一个快捷方式

df %>%
  mutate(B = coalesce(Date1, Date2, Date3, Date4))

如果B需要根据A的值来填充,那么这里有c_across()的一个思路:

df %>%
  rowwise() %>%
  mutate(B = c_across(starts_with("Date"))[A]) %>%
  ungroup()

# # A tibble: 4 × 6
#       A Date1 Date2 Date3 Date4 B    
#   <int> <chr> <chr> <chr> <chr> <chr>
# 1     1 x     NA    NA    NA    x    
# 2     2 NA    y     NA    NA    y    
# 3     3 NA    NA    z     NA    z    
# 4     4 NA    NA    NA    f     f 

【讨论】:

  • 我觉得这不是正确的答案,因为 OP 的 case_when 声明如果 A 等于 1,则用 Date1 填充 B,它并没有真正说我们应该用唯一的填充 B非缺失值(您的答案假设每个A 仅有一个非缺失值)
【解决方案2】:

其他答案更好,但如果您必须将当前代码用于实际应用程序,更正后的版本是:

df %>%
  mutate(B = case_when(
    A == 1 ~ Date1,
    A == 2 ~ Date2,
    A == 3 ~ Date3,
    A == 4 ~ Date4))

输出:

# A B Date1 Date2 Date3 Date4
# 1 x     x  <NA>  <NA>  <NA>
# 2 y  <NA>     y  <NA>  <NA>
# 3 z  <NA>  <NA>     z  <NA>
# 4 f  <NA>  <NA>  <NA>     f

【讨论】:

    【解决方案3】:

    看起来,您想要来自 Date 列的对角线值,您可以使用 diag

    df$B <- diag(as.matrix(df[grepl("Date", colnames(df))]))
    #[1] "x" "y" "z" "f"
    

    其他答案(如果你想合并):

    • max:
    df$B <- apply(df[2:5], 1, \(x) max(x, na.rm = T))
    
    • c_across:
    df %>% 
      rowwise() %>% 
      mutate(B = max(c_across(Date1:Date4), na.rm = T))
    

    输出

      A Date1 Date2 Date3 Date4 B
    1 1     x  <NA>  <NA>  <NA> x
    2 2  <NA>     y  <NA>  <NA> y
    3 3  <NA>  <NA>     z  <NA> z
    4 4  <NA>  <NA>  <NA>     f f
    

    【讨论】:

    • 我觉得这不是正确的答案,因为 OP 的 case_when 声明如果 A 等于 1,则用 Date1 填充 B 等,它并没有真正说我们应该用 B 填充max 的非缺失值
    • 这是正确的。
    • 没错,B 需要根据 A 的值来填充。请参阅下面提供的答案 jpsmith,他在其中更正了我的代码。
    猜你喜欢
    • 1970-01-01
    • 2020-01-12
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多