仅使用 Mutate 和 Case_When 来填充 NA 行

Hel*_*san 5 r filter missing-data dataframe dplyr

我已经盯着看几个小时了,我不知道在哪里可以找到像这样简单的问题的答案,所以我希望这不是一个重复的问题。

我有一个大数据框(936848 x 12),其中一列是一个编码名称,我可以从中导出其他列的值,在本例中,制造年份是根据列代码的第一个字符得出的。

数据框的小样本:

df <- data.frame(Code = c("AX123", "CL199", "GH679"), 
                 Year = c(NA, "2014", "2018")) 
Run Code Online (Sandbox Code Playgroud)

我只想仅在值丢失时才根据列代码更改“年份”列。我不想覆盖年份列中的现有值。

由于这还涉及识别代码中字符串中的第一个字母,因此我使用case_whenand startsWith:

df <- df %>%
  filter(is.na(Year)) %>%
  mutate(Year = case_when(startsWith(Code, "A") ~ 2013,
                          startsWith(Code, "C") ~ 2014,
                          startsWith(Code, "D") ~ 2015,
                          startsWith(Code, "E") ~ 2016,
                          startsWith(Code, "F") ~ 2017,
                          startsWith(Code, "G") ~ 2018,
                          startsWith(Code, "H") ~ 2019,
                          startsWith(Code, "J") ~ 2020,
                          TRUE ~ NA_real_
                          ))
Run Code Online (Sandbox Code Playgroud)

这将给出这个结果:

   Code Year
1 AX123 2013
Run Code Online (Sandbox Code Playgroud)

我的问题是我编写此过滤器以过滤掉数据框中所有非 NA 行的方式。我想保持数据框不变,只填充 NA 行。

我正在考虑将其嵌套到 ifelse 函数中,仅当列为 NA 时才进行变异,但我对如何编写它感到困惑。

df <- df %>%
  mutate(ifelse(is.na(Year),
                case_when(startsWith(Code, "A") ~ 2013,
                          startsWith(Code, "C") ~ 2014,
                          startsWith(Code, "D") ~ 2015,
                          startsWith(Code, "E") ~ 2016,
                          startsWith(Code, "F") ~ 2017,
                          startsWith(Code, "G") ~ 2018,
                          startsWith(Code, "H") ~ 2019,
                          startsWith(Code, "J") ~ 2020,
                          TRUE ~ NA_real_
  )), "")
Run Code Online (Sandbox Code Playgroud)

这显然会给出这个错误

Error: Problem with `mutate()` input `..1`.
i `..1 = ifelse(...)`.
x argument "no" is missing, with no default
Run Code Online (Sandbox Code Playgroud)

我有很多类似的任务,我需要使用ifelse、grepl等substring来检测代码列中的字符并填充其他列中缺少的 NA 。但是,由于许多已填充值的行是由于不遵循编码名称约定的规则的异常所致,因此我不想覆盖它们。

Gnu*_*une 1

你几乎明白了。ifelse需要 3 个参数:

  • 测试(在你的情况下is.na():)
  • 是(在您的情况下:根据起始字符替换为年份)
  • 否(在您的情况下:复制Year)

df %>%
  mutate(Year1 = ifelse(is.na(Year),
                case_when(startsWith(Code, "A") ~ 2013,
                          startsWith(Code, "C") ~ 2014,
                          startsWith(Code, "D") ~ 2015,
                          startsWith(Code, "E") ~ 2016,
                          startsWith(Code, "F") ~ 2017,
                          startsWith(Code, "G") ~ 2018,
                          startsWith(Code, "H") ~ 2019,
                          startsWith(Code, "J") ~ 2020,
                ), Year))
Run Code Online (Sandbox Code Playgroud)

输出:

   Code Year Year1
1 AX123 <NA>  2013
2 CL199 2014  2014
3 GH679 2018  2018
Run Code Online (Sandbox Code Playgroud)

如评论中所要求的,没有匹配字母的示例:

df <- data.frame(Code = c("AX123", "CL199", "GH679", "XX485"), 
                 Year = c(NA, "2014", "2018", NA))

df %>%
  mutate(Year1 = ifelse(is.na(Year),
                case_when(startsWith(Code, "A") ~ 2013,
                          startsWith(Code, "C") ~ 2014,
                          startsWith(Code, "D") ~ 2015,
                          startsWith(Code, "E") ~ 2016,
                          startsWith(Code, "F") ~ 2017,
                          startsWith(Code, "G") ~ 2018,
                          startsWith(Code, "H") ~ 2019,
                          startsWith(Code, "J") ~ 2020,
                ), Year))
Run Code Online (Sandbox Code Playgroud)

输出

   Code Year Year1
1 AX123 <NA>  2013
2 CL199 2014  2014
3 GH679 2018  2018
4 XX485 <NA>  <NA>
Run Code Online (Sandbox Code Playgroud)