问题描述
我正在 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
,然后使用 rank
或 dense_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)