计算先前的事件

时间:2018-07-03 21:05:48

标签: r tidyverse lubridate

第一次问这里:

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

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中逐行工作的经验(也许是答案吗?),但到目前为止,使用dplyr summary和group_by来思考这个问题都失败了。

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

3 个答案:

答案 0 :(得分:2)

尝试一下,提供我认为您期望的数量。

使用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

答案 1 :(得分:2)

这是另一个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

答案 2 :(得分:0)

使用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