R: удаление строк и замена значений с использованием условий из нескольких столбцов - PullRequest
3 голосов
/ 15 января 2011

Я хочу отфильтровать все значения var3 <5, сохранив хотя бы одно вхождение каждого значения var1. </p>

> foo <- data.frame(var1=c(1, 1, 8, 8, 5, 5, 5), var2=c(1,2,3,2,4,6,8), var3=c(7,1,1,1,1,1,6))
> foo
  var1 var2 var3
1    1    1    7
2    1    2    1
3    8    3    1
4    8    2    1
5    5    4    1
6    5    6    1
7    5    8    6

subset(foo, (foo$var3>=5)) удалит строки со 2 по 6, и я потерял бы var1 == 8.

  • Я хочу удалить строку, если есть другое значение var1, которое удовлетворяет условию foo $ var3> = 5. См. Строку 5.
  • Я хочу сохранить строку, назначив NA для var2 и var3, если все вхождения значения var1 не удовлетворяют условию foo $ var3> = 5.

Это результат, который я ожидаю:

  var1 var2 var3
1    1    1    7
3    8   NA   NA
7    5    8    6

Это самое близкое, что у меня есть:

> foo$var3[ foo$var3 < 5 ] = NA
> foo$var2[ is.na(foo$var3) ] = NA
> foo
  var1 var2 var3
1    1    1    7
2    1   NA   NA
3    8   NA   NA
4    8   NA   NA
5    5   NA   NA
6    5   NA   NA
7    5    8    6

Теперь мне просто нужно знать, как условно удалить правильные строки (2, 3 или 4, 5, 6): удалить строку, если var2 и var3 равны NA, и если значение var1 имеет более 1 вхождения.

Но, несомненно, есть гораздо более простой / элегантный способ решения этой маленькой проблемы.

редактировать: изменено foo, чтобы напоминать мой вариант использования подробнее

Ответы [ 5 ]

10 голосов
/ 16 января 2011

Самый быстрый способ - использовать слияние:

> merge(foo[foo$var3>5,],unique(foo$var1),by.x=1,by.y=1,all.y=T)
  var1 var2 var3
1    1    1    7
2    5    8    6
3    8   NA   NA

unique(foo$var1) дает уникальные значения в var1. Эти сопоставляются с фреймом данных, где var3 больше пяти. Вы берете первый столбец каждого аргумента (all.x = 1, all.y = 1) и говорите, что все значения в y должны быть представлены (all.y = T) Смотри также ?merge.

Если вы хотите сохранить заказ, то:

> merge(foo[foo$var3>5,],unique(foo$var1),by.x=1,by.y=1,
+ all.y=T)[order(unique(foo$var1)),]
  var1 var2 var3
1    1    1    7
3    8   NA   NA
2    5    8    6

Слияние сортирует переменную, по которой происходит сопоставление. order дает эту сортировку, так что вы можете изменить ее, используя этот порядок в качестве индексов. Смотри также ?order.

3 голосов
/ 16 января 2011

После того, как вы выполните:

foo$var3[ foo$var3 < 5 ] = NA
foo$var2[ is.na(foo$var3) ] = NA

Вам необходимо удалить строки, содержащие NA, которые также являются дублирующими значениями var1:

foo[!(!complete.cases(foo) & duplicated(foo$var1)), ]

Думайте об этой строке как идентифицирующие строки, содержащие NAзначения И дублируйте значения var1, затем выберите все остальное.

Редактировать: Если первая строка в кадре данных для данного значения var1 имеет значение var3, которое вы хотите исключить, мое решение не работает.Сначала вам нужно заказать data.frame, чтобы убедиться, что на первом месте стоят полные кейсы:

foo <- foo[order(foo$var2),]   # ordering on var3 should be the same
foo[!(!complete.cases(foo) & duplicated(foo$var1)), ]
2 голосов
/ 16 января 2011
rbind(r <- subset(foo, (foo$var3>=5)), 
      unique(transform(subset(foo, !var1%in%r$var1), var2=NA, var3=NA)))

шаг за шагом:

r <- subset(foo, (foo$var3>=5))

r2 <- subset(foo, !var1%in%r$var1) # extract var1 != r$var1
r3 <- transform(r2, var2=NA, var3=NA) # replace var2 and var3 with NA
r4 <- unique(r3) # remove duplicates

rbind(r, r4) # bind them
1 голос
/ 16 января 2011

Вот способ использования функций пакета plyr ddply и colwise и функции subset. Сначала определите вспомогательную функцию null2na:

null2na <- function(x) if ( length(x) == 0 ) NA else x

Затем определите функцию filter, которую мы хотим применить к каждому субкадру, который имеет определенное значение для var1:

filter <- function(df) cbind( data.frame( var1 = df[1,1]),
                              colwise(null2na) (subset(df, var3 >= 5)[,-1]))

Теперь сделайте ddply на foo на var1:

> ddply(foo, .(var1), filter)
  var1 var2 var3
1    1    1    7
2    5    8    6
3    8   NA   NA
0 голосов
/ 16 января 2011

Попробуйте это:

foo <- data.frame(var1= c(1, 1, 2, 3, 3, 4, 4, 5), 
     var2=c(9, 5, 13, 9, 12, 11, 13, 9), 
     var3=c(6, 8, 3, 6, 4, 7, 2, 9))
f2=foo[which(foo$var3>5),]

missing = which(!(foo$var1 %in% f2$var1))
f3 = rbind(f2, list(foo$var1[missing], rep(NA, length(missing)),rep(NA,length(missing))))
f3[order(f3$var1),]

Последняя строка нужна только в том случае, если вы заботитесь о порядке (при условии, что данные упорядочены по var1, в первую очередь =.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...