将所有零列替换为NA。

3

我在R中有以下数据框:

library(dplyr)
 library(tidyr)

df= data.frame("ID"= c("A", "A", "A", "A", "B", "B", "B"), 
"A1"= c(0,0, 0, 0, 1,0,1), "B1"= c(1,0, 1,0, 0, 0, 0))

数据框的呈现如下所示。
  ID A1 B1
1  A  0  1
2  A  0  0
3  A  0  1
4  A  0  0
5  B  1  0
6  B  0  0
7  B  1  0

我想要获得以下数据框:

   ID A1 B1
 1  A NA  1
 2  A NA  0
 3  A NA  1
 4  A NA  0
 5  B  1 NA
 6  B  0 NA
 7  B  1 NA

我已经尝试了以下代码。
df%>%group_by(ID)%>%
mutate(A1=case_when(sum(A1)==0~NA))%>%
mutate(B1=case_when(sum(B1)==0~NA))

这将完全将A1和B1转换为NA值。
我在这里请求一些帮助。
2个回答

3
我们可以通过将 ID 进行分组,并使用 mutate_allreplace 来完成。
library(dplyr)

df %>%
  group_by(ID) %>%
  mutate_all(~replace(., all(. == 0), NA))

# ID       A1    B1
#  <fct> <dbl> <dbl>
#1 A        NA     1
#2 A        NA     0
#3 A        NA     1
#4 A        NA     0
#5 B         1    NA
#6 B         0    NA
#7 B         1    NA

如果有其他列,而我们只想将此应用于特定列,我们可以使用 mutate_at

df %>%
  group_by(ID) %>%
  mutate_at(vars(A1,B1), ~replace(., all(. == 0), NA))

使用case_when,我们可以按照以下方式进行操作
df %>%
  group_by(ID) %>%
  mutate_all(~case_when(all(. == 0) ~ NA_real_, TRUE ~ .))

OP的尝试中存在问题,即在case_when中没有定义TRUE情况,因此当没有匹配的条件时,默认返回NA。参见? case_when。
如果我们定义了TRUE情况,它就会按预期工作。另外,我们不应该检查sum(A1)== 0,因为如果列中有负数和正数(如-2,+2),它们会相加得到0,从而产生意外的结果。
df%>%
  group_by(ID) %>%
  mutate(A1 = case_when(all(A1 == 0) ~ NA_real_, TRUE ~ A1), 
         B1 = case_when(all(B1 == 0) ~ NA_real_, TRUE ~ B1))

谢谢。我可以将所有值为0的列变异为NA来阅读它吗? - Thilaga raghavan
1
@Thilagaraghavan 是的,更准确地说,我们也可以将其解读为对所有列进行“变异”,并在组内的“所有”值为0时将值替换为“NA”。 - Ronak Shah
整洁,绝对清晰。但是为什么我编写的代码不起作用呢?我已经按ID分组,然后根据colsums ==0进行了变异。 - Thilaga raghavan
1
@Thilagaraghavan 我在答案中添加了一些关于 case_when 的解释。 - Ronak Shah

2

使用tidyverse,我们可以使用if/else

最初的回答
library(tidyverse)
df %>% 
   group_by(ID) %>% 
   mutate_all(list(~ if(all(.==0)) NA_integer_ else .))
# ID       A1    B1
#  <fct> <dbl> <dbl>
#1 A        NA     1
#2 A        NA     0
#3 A        NA     1
#4 A        NA     0
#5 B         1    NA
#6 B         0    NA
#7 B         1    NA

最初的回答
或者不使用任何if/else。
df %>%
   group_by(ID) %>%
   mutate_all(~ NA^all(!.) * .)

or using data.table

library(data.table)
setDT(df)[, lapply(.SD, function(x) replace(x, all(x == 0), NA)), ID]

或者使用基础R语言

by(df[-1], df$ID, FUN = function(x)  x * (NA^ !colSums(!!x))[col(x)])

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