我有一个用户ID和帐户登录表,该表的运行时间为2017年1月1日至2018年5月1日。这种情况很少见,所以我想看看他们是否每年登录同一日期的+/- 45天(在下面的代码中,我使用的是320/410,除非需要进行此操作,否则我将在稍后进行整理)。>
loginID userID date
1 a 2017-01-03
2 b 2017-01-12
3 c 2017-01-14
4 d 2017-01-19
5 d 2017-10-18
6 a 2017-11-30
7 b 2017-12-09
8 c 2017-12-17
9 a 2017-12-30
10 b 2018-01-15
我正在尝试编写一个循环,其中表引用了自己。我所拥有的最好的(不工作,但经过几次尝试)是:
for (row in 1:nrow(df)){
target <- subset(df, date < (row$date+410))
target <- subset(target, date > (row$date+320))
target <- target$userID
df$ninety <- row$userID %in% target
}
我正在寻找的结果是:
loginID userID date repeat_oneyr
1 a 2017-01-03 TRUE
2 b 2017-01-12 TRUE
3 c 2017-01-14 TRUE
4 d 2017-01-19 FALSE
5 d 2017-10-18 FALSE
6 a 2017-11-30 FALSE
7 b 2017-12-09 FALSE
8 c 2017-12-17 FALSE
9 a 2017-12-30 FALSE
10 b 2018-01-15 FALSE
(之所以将2017年10月18日(含2017年10月18日)视为FALSE,是因为我们没有登录数据来表明他们是否在此之后的320到410天之间登录)。
(从其他SO问题/答案中)我知道,如果我可以对每个loginID进行TRUE / FALSE迭代,则可以使用match()
来加入数据框,因此我不必担心那部分-首先获得TRUE / FALSE。
欢迎/感谢任何建议。
答案 0 :(得分:0)
您可以使用data.table
做一些事情。首先,我按用户ID排序data.table
。其次,我将date列转换为date对象。第三,我使用shift(, type="lead")
创建一个fwd_date列。最后,我使用ifelse
创建了repeat_oneyr列。
library(data.table)
setDT(df)
setorder(df,userID)
df[,date:=as.Date(df$date)]
df[,fwd_date:=shift(date,type="lead"),by=userID]
df[,repeat_oneyr:=ifelse( (fwd_date-date < 410 & fwd_date-date > 320)
& !is.na(fwd_date) ,TRUE, FALSE)]
loginID userID date fwd_date repeat_oneyr
1: 1 a 2017-01-03 2017-11-30 TRUE
2: 6 a 2017-11-30 2017-12-30 FALSE
3: 9 a 2017-12-30 <NA> FALSE
4: 2 b 2017-01-12 2017-12-09 TRUE
5: 7 b 2017-12-09 2018-01-15 FALSE
6: 10 b 2018-01-15 <NA> FALSE
7: 3 c 2017-01-14 2017-12-17 TRUE
8: 8 c 2017-12-17 <NA> FALSE
9: 4 d 2017-01-19 2017-10-18 FALSE
10: 5 d 2017-10-18 <NA> FALSE
数据
df<-read.table(text="loginID userID date
1 a 2017-01-03
2 b 2017-01-12
3 c 2017-01-14
4 d 2017-01-19
5 d 2017-10-18
6 a 2017-11-30
7 b 2017-12-09
8 c 2017-12-17
9 a 2017-12-30
10 b 2018-01-15",header=T)
答案 1 :(得分:0)
这是一种dplyr
的方法:
library(dplyr)
df %>%
group_by(userID) %>%
mutate(date = as.Date(date),
l45 = lead(between(c(0, diff.Date(date)), 320, 410), default = FALSE))
# A tibble: 10 x 4
# Groups: userID [4]
loginID userID date l45
<int> <fct> <date> <lgl>
1 1 a 2017-01-03 TRUE
2 2 b 2017-01-12 TRUE
3 3 c 2017-01-14 TRUE
4 4 d 2017-01-19 FALSE
5 5 d 2017-10-18 FALSE
6 6 a 2017-11-30 FALSE
7 7 b 2017-12-09 FALSE
8 8 c 2017-12-17 FALSE
9 9 a 2017-12-30 FALSE
10 10 b 2018-01-15 FALSE