使用dplyr按行用以前的值填充缺失值
我正在处理一个数据框,R其中跨行有一些缺失值。接下来是数据框(最后dput添加):
df
id V1 V2 V3 V4
1 01 1 1 1 NA
2 02 2 1 NA NA
3 03 3 1 NA NA
4 04 4 1 2 NA
每一行都是不同的id。如您所见,行有缺失值。我想知道如何在不使用 reshape to long 或 pivot 的情况下以这种样式完成数据框,因为我的真实数据非常大:
df
id V1 V2 V3 V4
1 01 1 1 1 1
2 02 2 1 1 1
3 03 3 1 1 1
4 04 4 1 2 2
我试图使用fillfromtidyr但在行级别我遇到了问题。我看过一些帖子,它与dplyr函数一起使用,across但我找不到它。我试过使用group_by(id),rowwise但没有成功。此外,只有以 开头的变量/列V应填充以前的值。
接下来是数据:
#Data
df <- structure(list(id = c("01", "02", "03", "04"), V1 = c(1, 2, 3,
4), V2 = c(1, 1, 1, 1), V3 = c(1, NA, NA, 2), V4 = c(NA, NA,
NA, NA)), class = "data.frame", row.names = c(NA, -4L))
非常感谢您的时间。
回答
一种解决方案是将na.locf包中的函数与逐行操作中的函数zoo结合使用pmap。na.locf取最近的非NA值并用它替换所有即将出现的NA值。正如c(...)两个解决方案中的提醒V1:V4在每次迭代中捕获每一行中的所有值一样。但是,我排除id了两者中的列,因为它不参与我们的计算。
library(zoo)
library(purrr)
df %>%
mutate(pmap_df(., ~ na.locf(c(...)[-1])))
id V1 V2 V3 V4
1 01 1 1 1 1
2 02 2 1 1 1
3 03 3 1 1 1
4 04 4 1 2 2
或者我们可以使用coalesce来自dplyr. 我们可以用NA最后一个非NA值替换每一行中的每个值,这是我们之前用na.locf. 但是这个解决方案有点冗长:
df %>%
mutate(pmap_df(., ~ {x <- c(...)[!is.na(c(...))];
coalesce(c(...), x[length(x)])}))
id V1 V2 V3 V4
1 01 1 1 1 1
2 02 2 1 1 1
3 03 3 1 1 1
4 04 4 1 2 2
或者你也可以使用这个:
library(purrr)
df %>%
mutate(across(!id, ~ replace(., is.na(.), invoke(coalesce, rev(df[-1])))))
id V1 V2 V3 V4
1 01 1 1 1 1
2 02 2 1 1 1
3 03 3 1 1 1
4 04 4 1 2 2
可以忽略警告消息。它实际上是因为我们有 6 个NA值而产生的,但是coalesce在每个向量上应用的结果是 1 个元素,导致 4 个元素替换 6 个插槽。
- 看看这里。你要出名了!</sf/ask/4823929491/?noredirect=1#comment121793354_68914759>
回答
使用的一种选择dplyr可能是:
df %>%
mutate(across(-id, ~ ifelse(is.na(.), coalesce(!!!select(., V4:V1)), .)))
id V1 V2 V3 V4
1 1 1 1 1 1
2 2 2 1 1 1
3 3 3 1 1 1
4 4 4 1 2 2
- I always called it the "bang bang bang" operator, but "big bang" is so much better.