Eloquent根据一行值改变多行值的R解决方案

Eloquent R solution to change multiple row values based on one row value

我正在清理一个 200 行的调查数据集。该调查使用了相当多的分支,并且在参与者没有收到问题的情况下返回 NA,因此它放弃了我的缺失数据分析。我花了一天半的时间试图找出一个 eloquent 解决方案(for loops, if conditions, filter(dplyr), mutate(dplyr), case_when)。我选择了使用 mutate() 的解决方案,但我知道有更好的方法来做到这一点。

这里有一个可重现的数据框作为调查数据

df <- data.frame(attsess1 = c(1, 1, 1, -99, -99), attsess2 = c(-99, -99, 1, 1, 1), s1satis = c(1, 1, 1, NA, NA), s1time = c(1, 1, 1, NA, NA), s1qual = c(1, 1, NA, NA, NA), s2satis = c(NA, NA, NA, 1, 1), s2time = c(NA, NA, 1, 1, 1))

本质上,如果 attsess1 等于 -99,那么我希望 s1satis、s1time、s1qual 中的以下相应行将它们的 NA 更改为 -99。同样的逻辑适用于 attsess2 和 s2satis 和 s2time。

下面的代码是我用的。它可以工作,但需要太多行,这对于具有大量变量的大型数据集来说可能会有问题

library(dplyr)
df1 <- df %>% mutate(s1satis = case_when(attsess1 == -99 ~ -99)) %>% mutate(s1time  = case_when(attsess1 == -99 ~ -99)) %>% mutate(s1qual = case_when(attsess1 == -99 ~ -99)) %>% mutate(s2satis = case_when(attsess2 == -99 ~ -99)) %>% mutate(s2time = case_when(attsess2 == -99 ~ -99))

我尝试使用 mutate_atcase_when,但收到此错误消息:

must be a double vector, not an integer vector.

我也尝试过使用 if 条件嵌套的 for 循环,但我不记得收到的错误消息。我还遇到了几个论坛,在这些论坛上,作者提倡用 dplyr 函数替换 for 循环。

确保您的 dplyr 版本已更新并且这个想法应该可行:

df %>%
  mutate(
    across(starts_with("s1"), ~ case_when(attsess1 == -99 ~ -99, TRUE ~ .)),
    across(starts_with("s2"), ~ case_when(attsess2 == -99 ~ -99, TRUE ~ .))
  )

#   attsess1 attsess2 s1satis s1time s1qual s2satis s2time
# 1        1      -99       1      1      1     -99    -99
# 2        1      -99       1      1      1     -99    -99
# 3        1        1       1      1     NA      NA      1
# 4      -99        1     -99    -99    -99       1      1
# 5      -99        1     -99    -99    -99       1      1

虽然我不太确定你想要的结果,但请参阅我对你的问题的评论。

如果你想获取整个数据集并将所有 NA 替换为 -99,你可以使用:

df %>%
  mutate_all(~replace(., is.na(.), -99))