在所有行和多列中更改数据框迭代中的值

时间:2019-01-18 14:11:49

标签: r dataframe

我需要更改数据框中的某些值,以遍历行。对于每一行,如果某列中有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

我该如何以更优化的方式编写它?

3 个答案:

答案 0 :(得分:0)

假设您想根据dplyr中的值更改V1V2列的值,使用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)