Удалить прогоны определенного значения до и после указанного c значения - PullRequest
2 голосов
/ 18 июня 2020

У меня есть фрейм данных с несколькими столбцами. На основе столбца «активность» я хочу удалить целые непрерывные прогоны указанного c значения «pt», но только тогда, когда они происходят непосредственно перед или после прогона «за пределами».

In В приведенных ниже упрощенных данных есть один прогон, в котором «активность» находится «снаружи», и перед и после него есть фрагменты «pt». Эти два фрагмента "pt" следует удалить.

   activity dist
1      home    1
2        pt    2 # <- run of 'pt' before run of 'outside': remove
3        pt    3 # <-
4        pt    4 # <- 
5   outside    5
6   outside    6
7        pt    7 # <- run of 'pt' after run of 'outside': remove
8        pt    8 # <-
9      work    9
10       pt   10
11       pt   11
12     home   12

Таким образом, желаемый результат:

    activity dist 
 1      home    1 
 2   outside    5 
 3   outside    6 
 4      work    9 
 5        pt   10 
 6        pt   11 
 7      home   12 

Как это может быть достигнуто?


dput данных:

structure(list(activity = c("home", "pt", "pt", "pt", "outside", "outside", "pt", "pt", "work", "pt", "pt", "home"),
              dist = 1:12),
          class = "data.frame", row.names = c(NA, -12L))

1 Ответ

2 голосов
/ 18 июня 2020

Вы можете использовать некоторые вспомогательные функции из data.table package: rleid до «[g] enerate run-length type group id» и shift для получения значений до и после фокального индекса в векторе.

library(data.table)
setDT(d)
d[ , r := rleid(activity)]

d[!(r %in% r[activity == "pt" & shift(activity, type = "lead") == "outside" |
               shift(activity) == "outside" & activity == "pt"])]

#    activity dist r
# 1:     home    1 1
# 2:  outside    5 3
# 3:  outside    6 3
# 4:     work    9 5
# 5:       pt   10 6
# 6:       pt   11 6
# 7:     home   12 7

Пояснение:

Приведите data.frame к data.table (setDT(d)). Создайте индекс продолжительности выполнения «активности» (rleid). Проверьте, является ли текущее значение «pt», а следующее значение - «за пределами» (activity == "pt" & shift(activity, type = "lead") == "outside") или (|), если текущее значение равно «pt», а предыдущее значение - «за пределами» (activity == "pt" & shift(activity) == "outside").

Если это условие TRUE, захватите группы запусков, которые нужно удалить (r[<condition>]). Проверьте, есть ли прогоны в удаляемых группах (r %in% <run groups to be removed>). Если это так, не (!) сохраняйте эти строки при индексировании данных (d[<condition>])

base альтернатива с использованием rle.

Значения прогонов 'pt' до или после 'outside' заменяются на NA. Значение преобразуется обратно в вектор (inverse.rle), а строки с NA удаляются (na.omit).

Очевидно, если в исходном наборе данных есть строки с NA, которые вы хотите сохранить, вам нужно использовать другое значение для замены.

with(rle(d$activity),
     values[c(which(head(values, -1) == "pt" & tail(values, -1) == "outside"),
              which(head(values, -1) == "outside" & tail(values, -1) == "pt") + 1)]) <- NA

d$activity = inverse.rle(r)
na.omit(d)  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...