根据日期和 R 中的排名回顾列
Look back column based on date and rank in R
我正在尝试创建一个基于排名的新列,每个月都会更改。以下是示例输入数据。
df <- data.frame(id=c(1,1,1,1,1,1,1,2,2,2,3,3,4),
rank=c(3,1,1,1,1,1,2,2,3,1,1,2,3),
dates=c('2019-06-15','2019-07-15','2019-08-15','2019-09-15','2019-10-15','2019-11-15','2019-12-15',
'2019-10-15','2019-11-15','2019-12-15',
'2019-11-15','2019-12-15','2019-12-15'))
这是预期的输出,我想要最新日期的行。
id rank dates new_col
1 2 2019-12-15 0
2 1 2019-12-15 0
3 2 2019-12-15 1
4 3 2019-12-15 0
new_col
将表明 rank
从 6 个月的回顾中有所增加?
例如,如果某行来自 12 月 2
但它们在 10 月的行中为 1
,则
在 December 行中,我们可以输入 new_col
= 1.
我们必须将回顾日期限制在 6 个月。
假设您愿意使用data.table。首先在时间变量之后对数据进行排序。使用 shift 获取最后 2 个可用值(在您的情况下为 6),并取最大值。需要确保每个 ID 都有完整的时间序列,否则,我认为它将采用最后可用的值。通过将排名与 rank_max 进行比较,您可以确定排名是否发生变化。
library(data.table)
df <- data.table(id=c(1,1,1,2,2,2,3,3,3) %>% as.character,
rank=c(1,3,2,2,3,1,1,2,3),
time=rep(1:3,3))
setorder(df, time)
df[, rank_max := do.call(pmax, shift(rank, 1:2, type = "lag")), by=id]
id rank time rank_max
1: 1 1 1 NA
2: 2 2 1 NA
3: 3 1 1 NA
4: 1 3 2 NA
5: 2 3 2 NA
6: 3 2 2 NA
7: 1 2 3 3
8: 2 1 3 3
9: 3 3 3 2
这是在 data.table
中使用非等值连接的选项:
#convert into IDate and get dates from 6m ago
DT[, dates := as.IDate(dates, format="%Y-%m-%d")][, c("start", "end") :=
.(as.IDate(sapply(dates, function(x) seq(x, by="-6 months", length.out=2L)[2L])), dates)]
#extract latest rows for each id
latest <- DT[DT[, .I[.N], id]$V1]
#non-equi join and for each latest date of each id, check if the current rank is the highest over last 6m
DT[latest, on=.(id, dates>=start, dates<end),
by=.EACHI, {
a <- +all(i.rank > x.rank)
.(new_col=replace(a, is.na(a), 0L))
}]
输出:
id dates dates new_col
1: 1 2019-06-15 2019-12-15 0
2: 2 2019-06-15 2019-12-15 0
3: 3 2019-06-15 2019-12-15 1
4: 4 2019-06-15 2019-12-15 0
数据:
library(data.table)
DT <- data.table(id=c(1,1,1,1,1,1,1,2,2,2,3,3,4),
rank=c(3,1,1,1,1,1,2,2,3,1,1,2,3),
dates=c('2019-06-15','2019-07-15','2019-08-15','2019-09-15','2019-10-15','2019-11-15','2019-12-15',
'2019-10-15','2019-11-15','2019-12-15',
'2019-11-15','2019-12-15','2019-12-15'))
我正在尝试创建一个基于排名的新列,每个月都会更改。以下是示例输入数据。
df <- data.frame(id=c(1,1,1,1,1,1,1,2,2,2,3,3,4),
rank=c(3,1,1,1,1,1,2,2,3,1,1,2,3),
dates=c('2019-06-15','2019-07-15','2019-08-15','2019-09-15','2019-10-15','2019-11-15','2019-12-15',
'2019-10-15','2019-11-15','2019-12-15',
'2019-11-15','2019-12-15','2019-12-15'))
这是预期的输出,我想要最新日期的行。
id rank dates new_col
1 2 2019-12-15 0
2 1 2019-12-15 0
3 2 2019-12-15 1
4 3 2019-12-15 0
new_col
将表明 rank
从 6 个月的回顾中有所增加?
例如,如果某行来自 12 月 2
但它们在 10 月的行中为 1
,则
在 December 行中,我们可以输入 new_col
= 1.
我们必须将回顾日期限制在 6 个月。
假设您愿意使用data.table。首先在时间变量之后对数据进行排序。使用 shift 获取最后 2 个可用值(在您的情况下为 6),并取最大值。需要确保每个 ID 都有完整的时间序列,否则,我认为它将采用最后可用的值。通过将排名与 rank_max 进行比较,您可以确定排名是否发生变化。
library(data.table)
df <- data.table(id=c(1,1,1,2,2,2,3,3,3) %>% as.character,
rank=c(1,3,2,2,3,1,1,2,3),
time=rep(1:3,3))
setorder(df, time)
df[, rank_max := do.call(pmax, shift(rank, 1:2, type = "lag")), by=id]
id rank time rank_max
1: 1 1 1 NA
2: 2 2 1 NA
3: 3 1 1 NA
4: 1 3 2 NA
5: 2 3 2 NA
6: 3 2 2 NA
7: 1 2 3 3
8: 2 1 3 3
9: 3 3 3 2
这是在 data.table
中使用非等值连接的选项:
#convert into IDate and get dates from 6m ago
DT[, dates := as.IDate(dates, format="%Y-%m-%d")][, c("start", "end") :=
.(as.IDate(sapply(dates, function(x) seq(x, by="-6 months", length.out=2L)[2L])), dates)]
#extract latest rows for each id
latest <- DT[DT[, .I[.N], id]$V1]
#non-equi join and for each latest date of each id, check if the current rank is the highest over last 6m
DT[latest, on=.(id, dates>=start, dates<end),
by=.EACHI, {
a <- +all(i.rank > x.rank)
.(new_col=replace(a, is.na(a), 0L))
}]
输出:
id dates dates new_col
1: 1 2019-06-15 2019-12-15 0
2: 2 2019-06-15 2019-12-15 0
3: 3 2019-06-15 2019-12-15 1
4: 4 2019-06-15 2019-12-15 0
数据:
library(data.table)
DT <- data.table(id=c(1,1,1,1,1,1,1,2,2,2,3,3,4),
rank=c(3,1,1,1,1,1,2,2,3,1,1,2,3),
dates=c('2019-06-15','2019-07-15','2019-08-15','2019-09-15','2019-10-15','2019-11-15','2019-12-15',
'2019-10-15','2019-11-15','2019-12-15',
'2019-11-15','2019-12-15','2019-12-15'))