Изменение значений в итерациях на фрейме данных по всем строкам и нескольким столбцам - PullRequest
0 голосов
/ 18 января 2019

Мне нужно изменить некоторые значения в моем кадре данных, повторяя по строкам. Для каждой строки, если в одном столбце есть 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 голосов
/ 18 января 2019

Мы можем сделать это в 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', создайте логическую матрицу с отрицанием (! - возвращает TRUE для 0 значений и все остальные FALSE). Затем, используя NA^ в логической матрице, вы получите NA для TRUE и 1 для других значений. Поскольку существуют только двоичные значения, это можно обновить

data[i1, 2:3] <- NA^!data[i1, 2:3]
0 голосов
/ 18 января 2019

Однострочник может быть,

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)
0 голосов
/ 18 января 2019

Это просто с 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...