R: частота подсчета категориальной переменной (условно по дате)

У меня есть три столбца «Имя», «Манекен успеха» и «Дата». Для каждого ИМЯ я хочу проверить ПРОШЛЫЙ УСПЕХ для этого ИМЯ.

Так, например, если имя «Питер» встречается три раза, каждый раз я хочу подсчитать количество «Питер» с «Успехом == 1», а дата произошла раньше.

Пример вывода, который мне нужно получить для столбца «Прошлый успех».

Name    Success Date   Past Success
David      1    2018    1
Peter      0    2017    3
Peter      1    2016    2
David      1    2017    0
Peter      1    2015    1
Peter      0    2010    1
Peter      1    2005    0
Peter     NA    2004    0

Есть ли способ сделать это быстро?

Также мне нужно, чтобы это было очень быстро, потому что мои данные огромны.

Что я сделал, так это отсортировал свои данные на основе имен и дат и сравнил каждое наблюдение со 100 наблюдениями ранее (поскольку максимальная частота имен составляет 100).

Пожалуйста, сообщите, если есть лучший способ сделать это.


person useR    schedule 04.04.2019    source источник
comment
Привет, UseR, можешь ли ты предоставить нам минимальный воспроизводимый пример? Я хотел бы скопировать и вставить код для создания вашего фрейма данных (или его подмножества) в мой сеанс R и иметь возможность воспроизвести то, что вы получаете, а затем порекомендовать решение. Спасибо :)   -  person mysteRious    schedule 04.04.2019
comment
Можете ли вы предоставить образцы данных?   -  person FALL Gora    schedule 04.04.2019
comment
Посмотрите на функцию rle()   -  person DanY    schedule 05.04.2019
comment
@FALLGora: строки 6 и 7 моего вопроса на самом деле представляют собой таблицу образцов данных и вывода. Он не отображается правильно в столбцах. Есть ли способ это исправить? Я скопировал вставку из таблицы excel   -  person useR    schedule 05.04.2019
comment
Это также может быть полезно: stackoverflow.com/questions/44665944/   -  person divibisan    schedule 05.04.2019
comment
@mysteRious: теперь он там   -  person useR    schedule 05.04.2019


Ответы (3)


Вот два способа сделать это. Один из них почти как @FALL Гора, а другой из базы R

# these two steps are assuming you have data.table
# modify them accordingly if you have data.frame
data <- data[order(Name, Date)]
data[is.na(Success), Success := 0]

### tapply
data$past_success <- unlist(with(data, tapply(Success, Name, cumsum)))

### data.table
data[, past_success_dt := cumsum(Success), by = Name]

data

    Name Success Date past_success past_success_dt
1: David       1 2017            1               1
2: David       1 2018            2               2
3: Peter       0 2004            0               0
4: Peter       1 2005            1               1
5: Peter       0 2010            1               1
6: Peter       1 2015            2               2
7: Peter       1 2016            3               3
8: Peter       0 2017            3               3
person cropgen    schedule 04.04.2019

Попробуйте этот подход к таблице данных:

library(data.table)
data <-data.table(Name = rep(c("David","Peter","David","Peter"), c(1,2,1,4)),
                  Success = c(1,0,1,1,1,0,1,NA),
                  Date = c(2018,2017,2016,2017,2015,2010,2005,2004)
                  )
data <- data[order(Date)]
data[Success == 1,"Past Success":= cumsum(Success), by = 'Name']
person FALL Gora    schedule 04.04.2019
comment
Он генерирует NA для трех столбцов. Но спасибо, это хороший способ закодировать его. - person useR; 05.04.2019
comment
NA — это значения, которые предполагаются равными нулю. вы можете обновить их, выполнив после: data[ ,"Past Success":= ifelse(is.na(`Past Success`),0,`Past Success`)] - person FALL Gora; 05.04.2019

Для справки: подход dplyr для фрейма данных

library(tidyverse)
data<-data%>%
  arrange(Name, Date) %>%
  group_by(Name) %>%
  mutate(Success = replace_na(Success, 0),
         PastSuccess = cumsum(Success))
data
> data
# A tibble: 8 x 4
# Groups:   Name [2]
  Name  Success  Date PastSuccess
  <fct>   <dbl> <dbl>        <dbl>
1 David       1  2017            1
2 David       1  2018            2
3 Peter       0  2004            0
4 Peter       1  2005            1
5 Peter       0  2010            1
6 Peter       1  2015            2
7 Peter       1  2016            3
8 Peter       0  2017            3
person 23stacks1254    schedule 04.04.2019