Как найти первый элемент в столбце по группе, который удовлетворяет условию? Если условие выполнено, запустите счетчик с 0 в R - PullRequest
1 голос
/ 15 февраля 2020

У меня есть большой набор данных, похожий на этот. Я пытался добавить счетчик с нуля в зависимости от состояния первого элемента в столбце по группе. Я хочу, чтобы мне понравилось это:

ID YEAR STOf counter
1 2000 0     0
1 2001 1     0
1 2002 0     1
1 2003 0     2
2 2000 0     0
2 2001 0     0
2 2002 1     0
2 2003 0     1
2 2004 0     2

Я пробовал этот код:

ov28<- ov27 %>% group_by(ID, idx = cumsum(STOf == 1L)) %>% 
       mutate(counter = row_number()) %>% 
       ungroup %>% 
       select(-idx)

Проблема: счетчик начинается с 1, и счетчик должен запускаться только в зависимости от условия в противоположность чтобы начать с нового идентификатора, а также условия. Короче говоря, я хочу, чтобы счетчик запускался, только если условие выполнено, что тоже с 0.

Спасибо!

Ответы [ 3 ]

1 голос
/ 15 февраля 2020

Мы можем найти номер строки при STOf == 1 и увеличить счетчик из этой строки.

library(dplyr)

ov27 %>% 
  group_by(ID) %>%
  mutate(counter1 = cumsum(row_number() > which.max(STOf == 1))
  #Can also use which
  #mutate(counter1 = cumsum(row_number() > which(STOf == 1)[1])

#     ID  YEAR  STOf counter counter1
#  <int> <int> <int>   <int>    <dbl>
#1     1  2000     0       0        0
#2     1  2001     1       0        0
#3     1  2002     0       1        1
#4     1  2003     0       2        2
#5     2  2000     0       0        0
#6     2  2001     0       0        0
#7     2  2002     1       0        0
#8     2  2003     0       1        1
#9     2  2004     0       2        2
1 голос
/ 15 февраля 2020

Другой вариант data.table:

DT[, cnt := DT[, pmax(seq(.N) - match(1L, STOf), 0L), ID]$V1]

данные:

library(data.table)
DT <- fread("ID YEAR STOf counter
1 2000 0     0
1 2001 1     0
1 2002 0     1
1 2003 0     2
2 2000 0     0
2 2001 0     0
2 2002 1     0
2 2003 0     1
2 2004 0     2")
1 голос
/ 15 февраля 2020

Мы можем сделать двойное cumsum после группировки по 'ID' и затем взять lag вывода

library(dplyr)
ov27 %>% 
   group_by(ID) %>%
   mutate(counter2 = lag(cumsum(cumsum(STOf == 1)), default = 0))
# A tibble: 9 x 5
# Groups:   ID [2]
#     ID  YEAR  STOf counter counter2
#  <int> <int> <int>   <int>    <dbl>
#1     1  2000     0       0        0
#2     1  2001     1       0        0
#3     1  2002     0       1        1
#4     1  2003     0       2        2
#5     2  2000     0       0        0
#6     2  2001     0       0        0
#7     2  2002     1       0        0
#8     2  2003     0       1        1
#9     2  2004     0       2        2

Или создать логическое условие и применить cumsum один раз

ov27 %>% 
    group_by(ID) %>% 
    mutate(counter2 = cumsum(row_number() > match(1, STOf)))

Если совпадений нет, т. Е. В группе нет единиц, укажите nomatch = n()

ov27 %>% 
 group_by(ID) %>% 
 mutate(counter2 = cumsum(row_number() > match(1, STOf, nomatch = n())))

ПРИМЕЧАНИЕ. Оба метода также работают, если в группе нет совпадений


Или используя те же логи c с data.table

library(data.table)
setDT(ov27)[, counter2 := cumsum(seq_len(.N) > match(1, STOf)), ID]

data

ov27 <- structure(list(ID = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L), YEAR = c(2000L, 
2001L, 2002L, 2003L, 2000L, 2001L, 2002L, 2003L, 2004L), STOf = c(0L, 
1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L), counter = c(0L, 0L, 1L, 2L, 
0L, 0L, 0L, 1L, 2L)), class = "data.frame", row.names = c(NA, 
-9L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...