R:对日期使用 doBy

问题描述

我正在 R 中进行一些编码。我正在尝试使用 doby 包通过日期(日期)和 ID(id)获得变量 (x) 的总分。 doby 命令工作正常,我得到了这个输出

data
id date       x
1  01/01/2021 1
1  01/02/2021 2
1  01/03/2021 3
2  02/01/2021 2
2  02/02/2021 3
2  02/02/2021 4
3  03/11/2021 3
3  03/12/2021 3
3  03/13/2021 2

我想重新编码日期,以便每个人的第一个按时间顺序排列的日期 1 为 1,按时间顺序排列的第二个日期为 2,按时间顺序排列的第三个日期为 3,等等。我希望我的日期看起来像这样。

data2
id daycount x
1  1        1
1  2        2
1  3        3
2  1        2
2  2        3
2  3        4
3  1        3
3  2        3
3  3        2

我可以使用 order() 对日期进行排序,但我不确定如何使日期匹配。我想我需要某种序列或自动编号。此外,一些参与者可能有不同的天数。一些参与者可能有 1 天,其他参与者可能有 10 天。

解决方法

您可能希望通过 group_by 使用 id,然后使用 rankdense_rank 创建一个新列(注意它们与处理重复项的区别)。

为了重新创建您的数据,我使用了:

# recreate data frame
id_vec <- rep(c(1,2,3),each = 3)
date_vec <- c(
  '01/01/2021','01/02/2021','01/03/2021','02/01/2021','02/02/2021','03/11/2021','03/12/2021','03/13/2021' 
)
x_vec <- rep(c(1,times = 3)
data <- data.frame(id = id_vec,date = date_vec,x = x_vec)

为了您的方便,我还将 data 列转换为实际日期格式:

# convert string to date object
library(lubridate)
library(dplyr)
data <- data %>% mutate(date_formatted = mdy(date)) 

使用 rank 创建列:

data %>%
  group_by(id) %>%
  mutate(day_count = rank(date_formatted,ties.method = "first")) %>%
  ungroup()
# # A tibble: 9 x 5
# id date           x date_formatted day_count
# <dbl> <chr>      <dbl> <date>             <int>
# 1     1 01/01/2021     1 2021-01-01             1
# 2     1 01/02/2021     2 2021-01-02             2
# 3     1 01/03/2021     3 2021-01-03             3
# 4     2 02/01/2021     1 2021-02-01             1
# 5     2 02/02/2021     2 2021-02-02             2
# 6     2 02/02/2021     3 2021-02-02             3
# 7     3 03/11/2021     1 2021-03-11             1
# 8     3 03/12/2021     2 2021-03-12             2
# 9     3 03/13/2021     3 2021-03-13             3

使用 dense_rank 创建新列:

data %>%
  group_by(id) %>%
  mutate(day_count = dense_rank(date_formatted)) %>%
  ungroup()
# # A tibble: 9 x 5
# id date           x date_formatted day_count
# <dbl> <chr>      <dbl> <date>             <int>
# 1     1 01/01/2021     1 2021-01-01             1
# 2     1 01/02/2021     2 2021-01-02             2
# 3     1 01/03/2021     3 2021-01-03             3
# 4     2 02/01/2021     1 2021-02-01             1
# 5     2 02/02/2021     2 2021-02-02             2
# 6     2 02/02/2021     3 2021-02-02             2
# 7     3 03/11/2021     1 2021-03-11             1
# 8     3 03/12/2021     2 2021-03-12             2
# 9     3 03/13/2021     3 2021-03-13             3
,

1) doBy 假设日期已经在 id 内排序:

library(doBy)
transform_by(data,~ id,countdays = seq_along(id))

给予:

  id       date x countdays
1  1 01/01/2021 1         1
2  1 01/02/2021 2         2
3  1 01/03/2021 3         3
4  2 02/01/2021 2         1
5  2 02/02/2021 3         2
6  2 02/02/2021 4         3
7  3 03/11/2021 3         1
8  3 03/12/2021 3         2
9  3 03/13/2021 2         3

2) Base R 也可以使用 base R 中的 transform 和 ave 来完成。

transform(data,daycount = ave(id,id,FUN = seq_along))

给予:

  id       date x daycount
1  1 01/01/2021 1        1
2  1 01/02/2021 2        2
3  1 01/03/2021 3        3
4  2 02/01/2021 2        1
5  2 02/02/2021 3        2
6  2 02/02/2021 4        3
7  3 03/11/2021 3        1
8  3 03/12/2021 3        2
9  3 03/13/2021 2        3

注意

data 以可重现的形式:

Lines <- "id date       x
1  01/01/2021 1
1  01/02/2021 2
1  01/03/2021 3
2  02/01/2021 2
2  02/02/2021 3
2  02/02/2021 4
3  03/11/2021 3
3  03/12/2021 3
3  03/13/2021 2"
data <- read.table(text = Lines,header = TRUE)