Итерация по всем строкам в R, удаление тех, которые соответствуют критериям - PullRequest
0 голосов
/ 30 января 2012

R фрейм данных.В нем около дюжины столбцов и около 150 строк.Я хочу перебрать каждую строку и удалить ее, при этих двух условиях

  1. Это значение в столбце 8 не определено
  2. Значение для строки ВЫШЕ, в столбце 8 определено.

Мой код выглядит так, но он продолжает падать.Это должна быть глупая ошибка, но я не могу ее понять.

for (i in 2:nrow(newfile)){
    if (is.na(newfile[i,8]) && !is.na(newfile[(i-1),8]){ 
    newfile<-newfile[-i,]
    }
}   

Очевидно, что в этом примере newfile - это мой фрейм данных.

Ошибка, которую я получаю

Ошибка в [.data.frame (newfile, -i,): объект 'i' не найден

Проблема решена, но некоторые тестовые данные, если вы, ребята, хотели обойти:

23  L8  29141078    744319  27165443
24  L8  27165443    NA  NA
25  L8  28357836    8293    25116398
26  L8  25116398    NA  NA
27  L8  28357836    21600   25116398
28  L8  25116398    NA  NA
29  L8  40929564    NA  NA
30  L8  40929564    NA  NA
31  L8  41917264    33234   39446503
32  L8  39446503    NA  NA
33  L8  41917264    33981   39446503
34  L8  39446503    NA  NA

Очевидно, что здесь немного изменен, так что теперь вы сравниваете столбец 4 с тем, что над ним (или вы можете использовать столбец 5 в любом случае)

Ответы [ 3 ]

2 голосов
/ 30 января 2012

Проблема в том, что вы меняете фрейм данных из-под себя; исходная оценка nrow(newfile) не обновляется по мере продвижения (это было бы, если бы у вас был цикл в стиле C for (i=1; i<=nrow(newfile); i++) ...). С другой стороны, в цикле while условие будет пересматриваться каждый раз через цикл, поэтому я думаю, что это сработает.

i <- 2
while (i<=nrow(newfile)){
   if (is.na(newfile[i,8]) && !is.na(newfile[i-1,8])) { 
     newfile<-newfile[-i,]
   }
   i <- i+1
} 

Вы не дали нам легко воспроизводимый ответ (т. Е. Тестовый набор данных с ответами), поэтому я не собираюсь проверять это прямо сейчас.

Тщательная мысль (которую у меня нет времени на это сейчас) может привести к не итеративному (и, следовательно, возможно, гораздо более быстрому, если это важно) способу сделать это.

0 голосов
/ 30 января 2012

Вот еще одно решение.Но он сохраняет значения NA, если предыдущее значение также равно NA.

#create some dummy data
newfile <- matrix(runif(800), ncol = 8)
newfile[rbinom(100, 1, 0.25) == 1, 8] <- NA
#the selection
newfile[-which(diff(is.na(newfile[, 8])) == 1) - 1, ]
0 голосов
/ 30 января 2012

Хм, если я это сделаю, я получу

Error in if (is.na(newfile[i,8]) && !is.na(newfile[(i-1),8]) { : 
  missing value where TRUE/FALSE needed

Это потому, что вы удаляете строки во время их итерации, поэтому к тому времени вы получаете nrow(newfile) (чтоисходное количество строк, поскольку nrow(newfile) вычисляется один раз в начале цикла foor), оно может больше не существовать, поскольку строки были удалены.

Вы можете полностью избежать зацикливания, создав логическую схему.Индекс строк, которые нужно сохранить (т. е. вектор длины nrow(newfile) с TRUE, если вы хотите сохранить строку и FALSE в противном случае):

n <- nrow(newfile)
# first bit says "is the row NA (for rows 2:n)"
# second bit says "is the row above *not* NA (for rows 1:(n-1))
# the & finds rows satisfying *both* conditions (first row always gets kept)
toRemove <- c(FALSE,is.na(newfile[-1,8])) & c(FALSE,!is.na(newfile[-n,8]))
toKeep   <- !toRemove
newfile  <- newfile[toKeep,]

Вы можете сделать все это в одной строке, еслиэто твоя вещь:

newfile <- newfile[ !(c(FALSE,is.na(newfile[-1,8])) & c(FALSE,!is.na(newfile[-nrow(newfile),8]))), ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...