2016-12-07 4 views
1

Я пытаюсь проанализировать данные игры, но мне нужно удалить все строки после указанной строки.Удаление всех строк в указанной строке во временном ряду

В следующем случае я хочу удалить все строки после EVENT «Die» для каждого пользователя. Данные сортируются по UID, TIME.HOUR.

ДФ:

UID TIME.HOUR EVENT 
    1  5  Run 
    1  5  Run 
    1  6  Run 
    1  7  Die 
    1  8  Run 
    1  9  Run 
    2  14  Jump 
    2  15  Die 
    2  16  Run 
    2  17  Run 

Ожидаемый результат:

UID TIME.HOUR EVENT 
    1  5  Run 
    1  5  Run 
    1  6  Run 
    1  7  Die 
    2  14  Jump 
    2  15  Die 

Я думаю, что я нахожусь на правильном пути с ниже код, но не изо всех сил к следующему шагу.

args <- which(df$EVENT== "Die") 
df[,c(sapply(args, function(x) ???), by = UID] #seq? range? 

спасибо.

ответ

3

Мы можем использовать data.table. Преобразуйте «data.frame» в «data.frame» в «data.table», сгруппированный по «UID», получите двойной логический вектор cumsum (EVENT == "Die"), проверьте, меньше ли это 2 для подмножества Data.table (.SD)

library(data.table) 
setDT(df)[, .SD[cumsum(cumsum(EVENT=="Die"))<2] , UID] 
# UID TIME.HOUR EVENT 
#1: 1   5 Run 
#2: 1   5 Run 
#3: 1   6 Run 
#4: 1   7 Die 
#5: 2  14 Jump 
#6: 2  15 Die 

Or a faster approach: чтобы получить индекс строки, извлечь этот столбец ($V1) для подмножества данных

setDT(df)[df[, .I[cumsum(cumsum(EVENT=="Die"))<2] , UID]$V1] 

или модифицированную @ Psidom подход

setDT(df)[df[, .I[seq(match("Die", EVENT, nomatch = .N))] , UID]$V1] 

Или используйте dplyr

library(dplyr) 
df %>% 
    group_by(UID) %>% 
    slice(seq(match("Die", EVENT, nomatch = n()))) 
# UID TIME.HOUR EVENT 
# <int>  <int> <chr> 
#1  1   5 Run 
#2  1   5 Run 
#3  1   6 Run 
#4  1   7 Die 
#5  2  14 Jump 
#6  2  15 Die 

В случае, нам нужен data.frame выход, цепь с %>% as.data.frame (от @ R, S. комментарии)

+0

Это о 'dplyr' part-- Это превосходно и довольно гибко. Часть 'slice' нуждается в' seq', потому что в противном случае она вернет только соответствующую строку. Правильно ли я понял? И 'nomatch = n()' означает идти до конца в случае отсутствия соответствия? Кстати, возможно, вы также можете предложить добавить '%>% ungroup()%>% as.data.frame()' в конце, чтобы получить очищенный фрейм. –

+0

@ R.S. Вы правы, он получит только соответствующую строку, если вы не используете 'seq', а' nomatch = n() '- для особых случаев, когда совпадений нет для определенного UID. Некоторые люди предпочитают выводить их как 'tbl_df'. Итак, я оставлю это как это и добавлю ваши комментарии – akrun

+1

Ah. Благодарю. Проницательность помогает. –

2

Другой вариант, вы можете использовать head() с match() (найти первый Die индекс):

dt[, head(.SD, match("Die", EVENT, nomatch = .N)), UID] # if no match is found within the 
                  # group, return the whole group 

# UID TIME.HOUR EVENT 
#1: 1   5 Run 
#2: 1   5 Run 
#3: 1   6 Run 
#4: 1   7 Die 
#5: 2  14 Jump 
#6: 2  15 Die 
3

Это, вероятно, не столь эффективно, но вы могли бы сделать фантазии присоединиться:

mdf = df[EVENT == "Die", head(.SD, 1L), by=UID, .SDcols = "TIME.HOUR"] 
df[!mdf, on=.(UID, TIME.HOUR > TIME.HOUR)] 

    UID TIME.HOUR EVENT 
1: 1   5 Run 
2: 1   5 Run 
3: 1   6 Run 
4: 1   7 Die 
5: 2  14 Jump 
6: 2  15 Die 

Вам, собственно, не нужно сохранять таблицу mdf как отдельный объект.


Как это работает

  • x[!i], где i еще один data.table или список векторов, является анти-соединения, говоря R, чтобы исключить строки x на основе i, подобно тому, как он работает с векторами (где i должен быть логическим вектором).

  • Опция on=.(ID, v >= v) сообщает R, что мы делаем «соединение без соединения»."v >= v часть означает, что v от i (на левой стороне) должно быть больше, чем v от x (на правой стороне).

Сочетание этих двух, мы за исключением .. строки, которые соответствуют критериям, указанным в on=


стороны отмечает есть пару вещей, которые я не уверен, что: у нас есть лучшее название, чем не присоединиться Почему оборудования д является v на осталось от i, хотя x[i] имеет x слева от i?

Я позаимствовал как ответ Psidom, так и akrun, используя head и неравенство. Одно (может быть?) Преимущество здесь в том, что head(.SD, 1L)is optimized пока head(.SD, expr) еще нет.

+0

Хорошее использование неравновесных соединений – akrun

Смежные вопросы