Данные подмножества, основанные на первом появлении флага состояния - PullRequest
0 голосов
/ 25 сентября 2018

Мои данные выглядят так:

dfin <- 
ID   TIME   CONC   STATUS
 1    0      5      0
 1    1      4      1
 1    2      3      0
 2    0      2      0 
 2    10     2      0
 2    15     1      0

Я хочу установить подмножество dfin для первого вхождения (для каждого ID), когда STATUS==1 и TIME > 0.Если у субъекта ID нет записанного STATUS==1 в любое время, то мне нужно указать последнее сырье этого субъекта.

вывод здесь должен быть:

dfout <- 
ID   TIME   CONC   STATUS
 1    1      4      1
 2    15     1      0

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

Вот один подход с data.table.Преобразуйте data.frame в «data.table» (setDT(dfin)), сгруппированный по «ID», if, где any «STATUS» равен 1, затем получите логическое выражение, где «TIME» больше 0или else получить последнюю строку (.N) и подмножество с .SD

library(data.table)
setDT(dfin)[,  .SD[if(any(STATUS == 1)) STATUS == 1& TIME  > 0 else .N], ID]
#   ID TIME CONC STATUS
#1:  1    1    4      1
#2:  2   15    1      0

Это также может быть записано как

setDT(dfin)[, .SD[(STATUS == 1 & TIME > 0)| (!any(STATUS) & seq_len(.N) == .N)], ID]

data

dfin <- structure(list(ID = c(1L, 1L, 1L, 2L, 2L, 2L), TIME = c(0L, 1L, 
 2L, 0L, 10L, 15L), CONC = c(5L, 4L, 3L, 2L, 2L, 1L), STATUS = c(0L, 
 1L, 0L, 0L, 0L, 0L)), class = "data.frame", row.names = c(NA, 
 -6L))
0 голосов
/ 25 сентября 2018

В одну сторону с dplyr мы можем group_by ID и проверить, есть ли какая-либо строка, которая удовлетворяет нашему условию (STATUS == 1 & TIME > 0), если это так, мы получаем первую строку, которая удовлетворяет условию, используя which.max, если такой строки нет, мы просто возвращаем последнюю строку, используя n().

library(dplyr)
df %>%
  group_by(ID) %>%
  slice(ifelse(any(STATUS == 1 & TIME > 0), which.max(STATUS == 1 & TIME > 0), n()))

#     ID  TIME  CONC STATUS
#  <int> <int> <int>  <int>
#1     1     1     4      1
#2     2    15     1      0

Другой подход, использующий только базу R. Это фактически следует той же логике, что и в dplyr но ave возвращает длину, такую ​​же, что и для ввода, поэтому мы сохраняем только unique значения и берем кумулятивную сумму (cumsum), чтобы получить соответствующие строки из фрейма данных.

df[cumsum(unique(with(df, ave(STATUS == 1 & TIME > 0, ID, FUN = function(x) 
         if(any(x)) which.max(x) else length(x))))), ]

#  ID TIME CONC STATUS
#2  1    1    4      1
#5  2   10    2      0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...