按ID子集在R中用999替换NA值

4
我已经在R中创建了以下数据框:
    df<-data.frame("ID"=c("A", "A", "A", "B", "B", "B"),"II"=c(NA, NA, 
    NA,1,2,3),"JJ"=c(1,2,3, NA, NA, NA), 'KK'=c(1,2,NA, NA, 5,6))

生成的数据帧如下所示。
  ID II JJ KK
   A NA  1  1
   A NA  2  2
   A NA  3 NA
   B  1 NA NA
   B  2 NA  5
   B  3 NA  6

我希望你可以通过ID值对数据框进行子集操作,并将所有只包含NA值的列替换为999。结果应该如下所示:
 ID  II  JJ KK
  A 999   1  1
  A 999   2  2
  A 999   3 NA
  B   1 999 NA
  B   2 999  5
  B   3 999  6

我已经尝试了这段代码。
   library(dplyr)
   df%>%
   group_by(ID)%>%
   select(II, JJ,KK)%>%
   mutate_if(df[, colSums(is.na(df)) == nrow(df)]<999)

我遇到了以下错误

 Adding missing grouping variables: `ID`
 Error in tbl_if_vars(.tbl, .p, .env, ..., .include_group_vars = 
 .include_group_vars) : 
 length(.p) == length(tibble_vars) is not TRUE

我希望有人能看一下。我无法弄清楚。不需要基于dplyr的解决方案。


2
请翻译以下与编程有关的内容从英语到中文。只返回翻译后的文本:不是@tifu建议的重复。 - Sotos
你是正确的,将会删除这个建议。 - tifu
3个回答

10
我们可以使用all来捕获所有包含NA的组。由于我们想要替换所有列中的NA,所以可以使用mutate_all,其中funs(即应用于所有列的函数)是将包含all()值为NA的组简单替换为999replace()函数。
library(tidyverse)

df %>% 
 group_by(ID) %>% 
 mutate_all(funs(replace(., all(is.na(.)), 999)))
这将会给出,
# A tibble: 6 x 4
# Groups:   ID [2]
  ID       II    JJ    KK
  <fct> <dbl> <dbl> <dbl>
1 A       999     1     1
2 A       999     2     2
3 A       999     3    NA
4 B         1   999    NA
5 B         2   999     5
6 B         3   999     6

好的。请问它是如何工作的,先生?我理解了 group_by,但从 mutate_all 开始有点不清楚。 - Raghavan vmvs
@marciaakshayaLeo 我添加了一个解释。如果你有其他问题,请告诉我。 - Sotos

3

这里提供一种使用data.table的解决方案:

library(data.table)
setDT(df)
df[, lapply(.SD, 
            function(col) if (all(is.na(col))) 999 else col), 
     by = ID]
#    ID  II  JJ KK
# 1:  A 999   1  1
# 2:  A 999   2  2
# 3:  A 999   3 NA
# 4:  B   1 999 NA
# 5:  B   2 999  5
# 6:  B   3 999  6

我们使用 lapply 循环遍历所有非 ID 列,如果其中所有列均为 NA,则将它们替换为 999

3
你可以使用 setDT() 替代 as.data.table()(这样更快),而且你不需要指定 .SDcols --- 它自动包括除 by 指定的列以外的所有列。 - s_baldur
谢谢,我正在学习 data.table(我更喜欢 dplyr)- 我会修改代码的,感谢您的见解,非常有帮助!+1 - thothal

1
一个基于r的方法:
df[sapply(df, function(x)
  if(is.numeric(x)) is.na(ave(x, df$ID, FUN = function(y)
    mean(y, na.rm = TRUE))) else rep(FALSE, length(x)))] <- 999

df
  ID  II  JJ KK
1  A 999   1  1
2  A 999   2  2
3  A 999   3 NA
4  B   1 999 NA
5  B   2 999  5
6  B   3 999  6

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接