dplyr r中的时间序列分组和过滤器
我试图在一个数据帧内的组中找到特定的模式。获取以下数据框,其中包括通过电子邮件下的订单、下订单的人和金额dplyr r中的时间序列分组和过滤器,r,filter,group-by,dplyr,R,Filter,Group By,Dplyr,我试图在一个数据帧内的组中找到特定的模式。获取以下数据框,其中包括通过电子邮件下的订单、下订单的人和金额 set.seed(123) dates = sample(seq(as.Date("2017-01-01"),as.Date("2017-12-31"), by = 'day'), 2000, replace = TRUE) amount <- sample(-50:100, 2000, replace = TRUE) placedorder <- sample(c(NA, NA
set.seed(123)
dates = sample(seq(as.Date("2017-01-01"),as.Date("2017-12-31"), by = 'day'), 2000, replace = TRUE)
amount <- sample(-50:100, 2000, replace = TRUE)
placedorder <- sample(c(NA, NA, NA, "jeff", "alex", "steve", "amy", "john", "larry", "ryan"), 2000, replace = TRUE)
email <- sample(paste0(1:200, "@gmail.com"), 2000, replace = TRUE)
df <- data.frame(dates, email, placedorder, amount, stringsAsFactors = FALSE)
上面的示例都在同一封电子邮件中,并且3个过滤器中的每一个都会在时间上一个接一个地出现
我的尝试,我认为找到了这些发生的地方,但没有考虑到日期和连续发生的情况。而且,事实上,将其过滤到这些订单是最好的
df2 <- df %>%
group_by(email) %>%
filter(any(is.na(placedorder) & amount > 0),
any(is.na(placedorder) & amount < 0),
any(!is.na(placedorder) & amount > 0)
)
df2%
分组人(电子邮件)%>%
过滤器(任何(是.na(placedorder)和数量>0),
任何(是不适用的,且金额<0),
任何(!is.na(placedorder)&金额>0)
)
提前谢谢 假设我对“一阶”和“二阶”的解释是正确的,下面是在dplyr中设置命令的一种方法
library(dplyr)
df %>% group_by(email) %>%
arrange(email, dates) %>%
mutate(order_num=1:n()) %>%
#An order was placed with a positive value and where placedorder is NA
filter((is.na(placedorder) & amount>0) |
# An order was placed after the first one, with a negative value and where placedorder is NA
(is.na(placedorder) & amount <0 & order_num >1) |
# An order was placed after the second order, with a positive value and where placeholder is not NA
(!is.na(placedorder) & amount >0 & order_num > 2)
)
库(dplyr)
df%%>%group_by(电子邮件)%%>%
安排(电子邮件、日期)%>%
变异(顺序数=1:n())%>%
#订单为正值,其中placedorder为NA
过滤器((is.na(placedorder)&数量>0)|
#在第一个订单之后下订单,订单值为负值,其中placedorder为NA
(is.na(placedorder)和金额1)|
#在第二个订单之后放置了一个订单,该订单的值为正值,且占位符不是NA
(!is.na(placedorder)&金额>0&订单数量>2)
)
更新:
非常感谢你澄清这个问题。基本上,您希望“观察客户状态”,并且仅在观察到前一种类型的事件之后才开始跟踪下一种类型的事件。这里有一个(略显冗长,但希望可以理解)尝试跟踪通过这些“状态”转换的客户:
df%>%groupby(email)%>%
安排(电子邮件、日期)%>%
突变(event_1=ifelse(is.na(placedorder)&amount>0,1,0),
事后事件1=累计金额(事件1),
#仅当至少发生了一个事件_1时
事件\u 2=ifelse(事件后\u 1>=1&is.na(placedorder)&amount=1&!is.na(placedorder)&amount>0,1,0))%>%
#仅对事件_1和事件_3之前的事件_2的首次发生感兴趣
过滤器((事件_1==1和事件后_1==1)|(事件_2==1和事件后_2==1)|事件_3==1)
#一个tibble:390x9
#分组:电邮[165]
日期电子邮件地址订单金额事件\u 1发布事件\u 1事件\u 2发布事件\u 2事件\u 3
1 2017-01-29 1@gmail.com 76 1 1 0 0 0
2 2017-05-25 1@gmail.com -37 0 1 1 1 0
3 2017-08-14 1@gmail.com史蒂夫53 01 02 1
4 2017-12-21 1@gmail.com约翰9202041
5 2017-02-08 100@gmail.com 89 1 1 0 0 0
6 2017-01-16 101@gmail.com 40 1 1 0 0 0
7 2017-03-18 102@gmail.com 20 1 1 0 0 0
8 2017-05-16 102@gmail.com -45 0 2 1 1 0
9 2017-06-08 102@gmail.com拉里4602021
10 2017-07-22 102@gmail.com约翰9303021
# ... 还有380行
存在一些“未完成链”,例如,当客户进展到状态_1,但不进一步时。不确定是否要删除这些记录(为此,您可以计算每封电子邮件的观察次数,并删除少于3条记录的记录)。几个问题。当你说“之后”或仅仅根据数据集行数时,你在谈论时间序列?如果是暂时的,则首先对日期和电子邮件的数据集进行排序(对电子邮件进行排序以节省计算时间)。其次,是否要进行过滤,以便同时满足所有三个条件?此外,如果您的问题是由于日期是POSIXct而引起的,您可能希望将其转换为字符,然后根据需要再次转换,这很麻烦,但更容易在以后调试(如果有注释的话)。我的意思是“之后”,因为它发生在第一次发生的日期之后。我确实希望过滤,以便在给定的组内同时满足所有三个条件,并在一个接一个的日期发生(可以是日期之间的任意距离,只需在之后发生)编辑后显示ExampleThank@dmi3kno。所以首先,我需要通过电子邮件进行分组。它必须发生在同一封电子邮件中。但除此之外,我认为我没有澄清“一阶”和“二阶”。11月1日至20日可能有20个订单。我想找出在任何给定的日期发生1次,然后发生2次,然后发生3次的情况,但这些日期必须是一个接一个的。我想OP希望&而不是|,从他的评论来看。非常好的回答,顺便说一句。是的,我确实想要和,但是,order\u num
不起作用。我已经在我的帖子中添加了更多的说明,提供了更多的细节!基本上,按日期排序,然后添加订单号的helper列可以达到您需要的效果。@MattW。添加带有df$ORDER\u NUM的helper列
library(dplyr)
df %>% group_by(email) %>%
arrange(email, dates) %>%
mutate(order_num=1:n()) %>%
#An order was placed with a positive value and where placedorder is NA
filter((is.na(placedorder) & amount>0) |
# An order was placed after the first one, with a negative value and where placedorder is NA
(is.na(placedorder) & amount <0 & order_num >1) |
# An order was placed after the second order, with a positive value and where placeholder is not NA
(!is.na(placedorder) & amount >0 & order_num > 2)
)
df %>% group_by(email) %>%
arrange(email, dates) %>%
mutate(event_1=ifelse(is.na(placedorder) & amount>0, 1, 0),
post_event_1=cumsum(event_1),
# only if at least one event_1 has happened
event_2=ifelse(post_event_1>=1 & is.na(placedorder) & amount <0, 1,0),
post_event_2=cumsum(event_2),
# only if at least one event_2 has happened
event_3=ifelse(post_event_2>=1 & !is.na(placedorder) & amount >0, 1, 0)) %>%
# only interested in first occurance of event_1 and event_2 preceding event_3
filter((event_1==1 & post_event_1==1) | (event_2==1 & post_event_2==1) | event_3 ==1)
# A tibble: 390 x 9
# Groups: email [165]
dates email placedorder amount event_1 post_event_1 event_2 post_event_2 event_3
<date> <chr> <chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2017-01-29 1@gmail.com <NA> 76 1 1 0 0 0
2 2017-05-25 1@gmail.com <NA> -37 0 1 1 1 0
3 2017-08-14 1@gmail.com steve 53 0 1 0 2 1
4 2017-12-21 1@gmail.com john 92 0 2 0 4 1
5 2017-02-08 100@gmail.com <NA> 89 1 1 0 0 0
6 2017-01-16 101@gmail.com <NA> 40 1 1 0 0 0
7 2017-03-18 102@gmail.com <NA> 20 1 1 0 0 0
8 2017-05-16 102@gmail.com <NA> -45 0 2 1 1 0
9 2017-06-08 102@gmail.com larry 46 0 2 0 2 1
10 2017-07-22 102@gmail.com john 93 0 3 0 2 1
# ... with 380 more rows