计算以前的事件

Counting previous incidents

这里是第一次提问:

我有代表事件的日期和人物的数据。我想找到一种方法来计算一个人以前参与的次数。所以我想要这样的数据:

df <- data.frame(date = seq(ymd('2018-01-01'),ymd('2018-01-10'), by = '1 day'),
             id = c(1, 2, 3, 4, 3, 5, 2, 2, 1, 4),
             # how many previous times has this id been seen?
             count_before = c(0, 0, 0, 0, 1, 0, 2, 1, 1, 1))

df

   date          person_id count_before
 1 2018-01-01    1.           0.
 2 2018-01-02    2.           0.
 3 2018-01-03    3.           0.
 4 2018-01-04    4.           0.
 5 2018-01-05    3.           1.
 6 2018-01-06    5.           0.
 7 2018-01-07    2.           1.
 8 2018-01-08    2.           2.
 9 2018-01-09    1.           1.
10 2018-01-10    4.           1.

我没有在 R 中按行工作的经验(sapply 可能是答案?)但是使用 dplyr summarize 思考这个问题并且 group_by 到目前为止都失败了。

编辑:修复了预期输出中的不一致。

试试这个,提供我认为你想要的作为你的预期计数。

使用dplyr:

library(lubridate)
library(dplyr)
df <- data.frame(date = seq(ymd('2018-01-01'),ymd('2018-01-10'), by = '1 day'),
             id = c(1, 2, 3, 4, 3, 5, 2, 2, 1, 4))
df %>%
   arrange(date) %>%
   group_by(id) %>%
   mutate(count_before = row_number() - 1L) %>%
   ungroup()
# # A tibble: 10 × 3
#          date    id count_before
#        <date> <dbl>        <int>
# 1  2018-01-01     1            0
# 2  2018-01-02     2            0
# 3  2018-01-03     3            0
# 4  2018-01-04     4            0
# 5  2018-01-05     3            1
# 6  2018-01-06     5            0
# 7  2018-01-07     2            1
# 8  2018-01-08     2            2
# 9  2018-01-09     1            1
# 10 2018-01-10     4            1

基数 R:

do.call(rbind, by(df, df$id, function(a) { a$count <- seq.int(nrow(a))-1L; a;}))
#            date id count
# 1.1  2018-01-01  1     0
# 1.9  2018-01-09  1     1
# 2.2  2018-01-02  2     0
# 2.7  2018-01-07  2     1
# 2.8  2018-01-08  2     2
# 3.3  2018-01-03  3     0
# 3.5  2018-01-05  3     1
# 4.4  2018-01-04  4     0
# 4.10 2018-01-10  4     1
# 5    2018-01-06  5     0

这是另一个 base R 解决方案。正如@r2evans 所提到的,还认为您的预期输出有错字。

transform(df, count_new = ave(person_id, person_id, FUN = function(x) cumsum(x == x) - 1))
#         date person_id count_before count_new
#1  2018-01-01         1            0         0
#2  2018-01-02         2            0         0
#3  2018-01-03         3            0         0
#4  2018-01-04         4            0         0
#5  2018-01-05         3            1         1
#6  2018-01-06         5            0         0
#7  2018-01-07         2            2         1
#8  2018-01-08         2            1         2
#9  2018-01-09         1            1         1
#10 2018-01-10         4            1         1

使用 data.table 的解决方案。

library(tidyverse)
library(data.table)

df <- data.frame(date = seq(ymd('2018-01-01'),ymd('2018-01-10'), by = '1 day'),
                 id = c(1, 2, 3, 4, 3, 5, 2, 2, 1, 4))

setDT(df)

df[, count_before := seq_len(.N) - 1, by = id]
df
#           date id count_before
#  1: 2018-01-01  1            0
#  2: 2018-01-02  2            0
#  3: 2018-01-03  3            0
#  4: 2018-01-04  4            0
#  5: 2018-01-05  3            1
#  6: 2018-01-06  5            0
#  7: 2018-01-07  2            1
#  8: 2018-01-08  2            2
#  9: 2018-01-09  1            1
# 10: 2018-01-10  4            1

我们还可以进行以下操作。

df[, count_before := rowid(id) - 1]
df
#           date id count_before
#  1: 2018-01-01  1            0
#  2: 2018-01-02  2            0
#  3: 2018-01-03  3            0
#  4: 2018-01-04  4            0
#  5: 2018-01-05  3            1
#  6: 2018-01-06  5            0
#  7: 2018-01-07  2            1
#  8: 2018-01-08  2            2
#  9: 2018-01-09  1            1
# 10: 2018-01-10  4            1