Как условно удалить строки из фрейма данных - PullRequest
2 голосов
/ 29 февраля 2012

У меня есть следующий фрейм данных

id<-c(1,1,1,1,2,2,2,2,3,3,3,3)
time<-c(0,1,2,3,0,1,2,3,0,1,2,3)
value<-c(1,1,6,1,2,6,2,2,1,1,6,1)

d<-data.frame(id, time, value)

Значение 6 появляется только один раз для каждого идентификатора.Для каждого идентификатора я хотел бы удалить все строки со временем, превышающим время значения 6

. Я бы хотел, чтобы в конечном кадре данных были все наблюдения для всех идентификаторов без «6».Для тех идентификаторов, у которых есть «6» наблюдение, я хотел бы, чтобы все наблюдения со временем <того времени, когда наблюдалось 6. </p>

Я искал SO, есть несколько вопросов (и ответов) об условной строкеудаление, но я не нашел ничего близкого к тому, что мне нужно.

В приведенном выше случае окончательный кадр данных должен быть

  id time value
1   1    0     1
2   1    1     1
3   1    2     6
5   2    0     2
6   2    1     6
9   3    0     1
10  3    1     1
11  3    2     6

Большое спасибо.

Ответы [ 3 ]

1 голос
/ 29 февраля 2012

Выберите время со значением 6 для каждого идентификатора:

mt <- d[d$value == 6, c("id","time")]
names(mt) <- c("id", "max.time")

Объедините d и mt, чтобы иметь максимальное время для идентификатора:

d <- merge(d,mt)

Подмножество и очистка:

d <- subset(d, time <= max.time)
d$max.time <- NULL
1 голос
/ 29 февраля 2012

Это основано на ответе Андрея с использованием plyr:

library(plyr)
ddply(d, "id", function(x) subset(x, time <= x[x$value == 6, "time"]))
  id time value
1  1    0     1
2  1    1     1
3  1    2     6
4  2    0     2
5  2    1     6
6  3    0     1
7  3    1     1
8  3    2     6

ОБНОВЛЕНО ДЛЯ ОБРАЩЕНИЯ С КОММЕНТАРИИМИ В ЗАМЕЧАНИЯХ

Пример набора данных для соответствия описанию ниже:

id<-c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4)
time<-c(0,1,2,3,0,1,2,3,0,1,2,3,3,2,1)
value<-c(1,1,6,1,2,6,2,2,1,1,6,1,1,2,3)
d<-data.frame(id, time, value)

Добавьте дополнительную проверку в анонимную функцию:

ddply(d, "id", 
      function(x) {
        if (any(x$value == 6)) {
          subset(x, time <= x[x$value == 6, "time"])
        } else {
          x
        }
      }
)

Результаты проверки

   id time value
1   1    0     1
2   1    1     1
3   1    2     6
4   2    0     2
5   2    1     6
6   3    0     1
7   3    1     1
8   3    2     6
9   4    3     1
10  4    2     2
11  4    1     3
0 голосов
/ 29 февраля 2012

Я не уверен, что понимаю ваш метод выбора для 6. Если он определен пользователем, то следующие строки дадут вам выбранные строки:

x <- max(d[d$value==6, 'time']) #find the max time associate with value =6
subset(d, time<=x)   #subset and select only time less than or = to 6

Если вы хотите автоматизировать значение6 и ищем наибольшую долю стоимости по всем идентификаторам ровно один раз, вот тот извилистый способ, которым я это сделал.Каждый раз, когда вы видите список, который, как я часто знаю, sapply будет лучшим выбором и, вероятно, совершенно другим подходом, но я не знаю наверняка, как выбран 6, вот что я выдвинул сейчас:

y <- with(d, by(value, id, FUN=rle))
z <- lapply(seq_along(y), function(x) unlist(y[[x]][1])==1)
j <- lapply(seq_along(y), function(x) unlist(y[[x]][2])[z[[x]]])
mv <- max(as.numeric(as.character(unlist(subset(data.frame(table(unlist(j))), 
    Freq==length(j))['Var1']))))

x <- max(d[d$value==mv, 'time'])
subset(d, time<=x)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...