我需要更改数据框中的某些值,以遍历行。对于每一行,如果某列中有1,则需要将其他列中的0值更改为NA。
我有一个有效的代码,但是使用更大的数据集时速度非常慢。
data = data.frame(id=c("A","B","C"),V1=c(1,0,0),V2=c(0,0,0),V3=c(1,0,1))
cols = names(data)[2:4]
for (i in 1:nrow(data)){
if(any(data[i,cols]==1)){
data[i,cols][data[i,cols]==0]=NA
}
}
我有一个示例数据集
data
id V1 V2 V3
1 A 1 0 1
2 B 0 0 0
3 C 0 0 1
预期的(和实际的)结果是
data
id V1 V2 V3
1 A 1 NA 1
2 B 0 0 0
3 C NA NA 1
我该如何以更优化的方式编写它?
答案 0 :(得分:0)
假设您想根据dplyr
中的值更改V1
和V2
列的值,使用V3
很容易。我们可以在mutate_at
中指定要为其更改值的列,并在funs
参数中指定要为其更改值的条件。
library(dplyr)
data %>% mutate_at(vars(V1:V2), funs(replace(., V3 == 1 & . == 0, NA)))
# id V1 V2 V3
#1 A 1 NA 1
#2 B 0 0 0
#3 C NA NA 1
答案 1 :(得分:0)
我们可以在base R
中执行此操作,方法是使用rowSums
创建逻辑向量,然后根据该索引更新数字列
i1 <- rowSums(data[-1] == 1) > 0
data[-1][i1,] <- NA^ !data[-1][i1,]
data
# id V1 V2 V3
#1 A 1 NA 1
#2 B 0 0 0
#3 C NA NA 1
如果索引需要基于单个列,例如说“ V3”,则将“ i1”更改为
i1 <- data$V3 == 1
,并用'i1'设置行后更新其他数字列,创建带否定的逻辑矩阵(!
-对于0值返回TRUE,其他所有值均为FALSE)。然后,在逻辑矩阵上使用NA^
返回NA表示TRUE,1表示其他值。由于只有二进制值,因此可以更新
data[i1, 2:3] <- NA^!data[i1, 2:3]
答案 2 :(得分:0)
单线可以是
data[rowSums(data[-1]) > 0,] <- replace(data[rowSums(data[-1]) > 0,],
data[rowSums(data[-1]) > 0,] == 0,
NA)
data
# id V1 V2 V3
#1 A 1 NA 1
#2 B 0 0 0
#3 C NA NA 1
为避免一遍又一遍地评估相同的表达式,我们可以先定义它,即
v1 <- rowSums(data[-1]) > 0
data[v1,] <- replace(data[v1,],
data[v1,] == 0,
NA)