2015-10-19 87 views
0

df是显示不同客户的访问和购买时间的数据框。计算采购之间的时差(日期时间变量与NAs)

id<-c(1,1,1,1,1,1,2,2,2,2,2) 
visit<-rep("yes",11) 
purchase<-c("2015-04-27 13:57:06","2015-04-27 13:59:19","2015-04-27 14:03:35","NA","NA","2015-04-27 16:59:42","2015-05-18 17:01:09","2015-05-18 17:03:40","2015-05-18 17:04:00","NA","NA") 
df<-data.frame(id,visit,purchase) 

purchase变量是NA这意味着客户访问了网站,但没有进行购买。

现在我需要创建一个名为time.gap来计算每个客户如下购买之间的时间差距的新变量:

id visit   purchase time.gap 
1 1 yes 2015-04-27 13:57:06  NA 
2 1 yes 2015-04-27 13:59:19  133 
3 1 yes 2015-04-27 14:03:35  256 
4 1 yes     NA  NA 
5 1 yes     NA  NA 
6 1 yes 2015-04-27 16:59:42 10567 
7 2 yes 2015-05-18 17:01:09  NA 
8 2 yes 2015-05-18 17:03:40  151 
9 2 yes 2015-05-18 17:04:00  20 
10 2 yes     NA  NA 
11 2 yes     NA  NA 

会感谢你的帮助

回答

1
df$purchase <- strptime(df$purchase, "%Y-%m-%d %H:%M:%S") 
df1 <- df 

library(dplyr) 
df %>% 
    filter(!is.na(purchase)) %>% 
    group_by(id) %>% 
    mutate(time.gap = c(NA, difftime(purchase[-1], 
            purchase[-length(purchase)], units="secs"))) %>% 
    left_join(df1, .) 
# id visit   purchase time.gap 
# 1 1 yes 2015-04-27 13:57:06  NA 
# 2 1 yes 2015-04-27 13:59:19  133 
# 3 1 yes 2015-04-27 14:03:35  256 
# 4 1 yes    <NA>  NA 
# 5 1 yes    <NA>  NA 
# 6 1 yes 2015-04-27 16:59:42 10567 
# 7 2 yes 2015-05-18 17:01:09  NA 
# 8 2 yes 2015-05-18 17:03:40  151 
# 9 2 yes 2015-05-18 17:04:00  20 
# 10 2 yes    <NA>  NA 
# 11 2 yes    <NA>  NA 

这是一个dplyr方法与添加的合并。而difftime代替diff,因为它允许单位参数。

数据

id<-c(1,1,1,1,1,1,2,2,2,2,2) 
visit<-rep("yes",11) 
purchase<-c("2015-04-27 13:57:06","2015-04-27 13:59:19","2015-04-27 14:03:35","NA","NA","2015-04-27 16:59:42","2015-05-18 17:01:09","2015-05-18 17:03:40","2015-05-18 17:04:00","NA","NA") 
df<-data.frame(id,visit,purchase) 
is.na(df$purchase) <- df$purchase == "NA" 
df$purchase <- as.POSIXct(df$purchase) 

故障排除

如果遇到与你的真实数据有问题,我们可以分离其中的问题是从一个测试来:

s <- split(df, df$id) 
test <- list() 
for(i in 1:length(s)) { 
    s1 <- s[[i]] 
test[[i]] <- s[[i]] %>% 
    filter(!is.na(purchase)) %>% 
    group_by(id) %>% 
    mutate(time.gap = c(NA, difftime(purchase[-1], 
            purchase[-length(purchase)], units="secs"))) %>% 
    left_join(s1, .) 

} 

现在test是一个包含所有迭代的列表代码。如果发生错误,我们会知道发生了什么,因为所有其他成功的运行都将被保存。所以,如果我得到一个错误,并看看test,它的所有ID都达到ID 3,我知道ID 4导致了错误。

+0

您的代码完全适用于此示例,但是当我在我的工作数据上运行它们时,它会返回以下错误:不兼容的大小(16737151),期望47(组大小)或1.任何想法可能是什么问题? – AliCivil

+0

我尝试了不同的场景,我无法重现错误。您将不得不排查数据。尝试通过id s < - split(df,df $ id)分割数据'并在每个id test' - list()上运行代码。 for(i in 1:length(s))test [[i]] < - **我们上面的代码**'。当出现错误消息时,您将知道哪个ID创建了它,因为'test'的最后一个条目将是最后一个成功的轮流。 –

+0

btw当你测试它时,用's'代替代码中的所有'df'。 –

1

我想说的是时间上的差距每个用户ID都需要一个额外的步骤,在id级别进行分组。

-EDITED错过了日期转换。

A和dplyr lubridate和zoo

# libraries 
library(dplyr) 
library(zoo) 
library(lubridate) 

# the data 
id<-c(1,1,1,1,1,1,2,2,2,2,2) 
visit<-rep("yes",11) 
purchase<-c("2015-04-27 13:57:06","2015-04-27 13:59:19","2015-04-27 14:03:35","NA","NA","2015-04-27 16:59:42","2015-05-18 17:01:09","2015-05-18 17:03:40","2015-05-18 17:04:00","NA","NA") 
df<-data.frame(id,visit,purchase) 
df$purchase <- lubridate::ymd_hms(df$purchase) 
# helper column 
df$purch <- zoo::na.locf(df$purchase) 
df 

#> df 
# id visit   purchase    purch 
#1 1 yes 2015-04-27 13:57:06 2015-04-27 13:57:06 
#2 1 yes 2015-04-27 13:59:19 2015-04-27 13:59:19 
#3 1 yes 2015-04-27 14:03:35 2015-04-27 14:03:35 
#4 1 yes    <NA> 2015-04-27 14:03:35 
#5 1 yes    <NA> 2015-04-27 14:03:35 
#6 1 yes 2015-04-27 16:59:42 2015-04-27 16:59:42 
#7 2 yes 2015-05-18 17:01:09 2015-05-18 17:01:09 
#8 2 yes 2015-05-18 17:03:40 2015-05-18 17:03:40 
#9 2 yes 2015-05-18 17:04:00 2015-05-18 17:04:00 
#10 2 yes    <NA> 2015-05-18 17:04:00 
#11 2 yes    <NA> 2015-05-18 17:04:00 

# run it 
df%>% 
    group_by(id)%>% 
    mutate(dif=c(NA, diff(purch)))%>% 
    select(-purch) 

#Source: local data frame [11 x 4] 
#Groups: id 
# 
# id visit   purchase dif 
#1 1 yes 2015-04-27 13:57:06 NA 
#2 1 yes 2015-04-27 13:59:19 133 
#3 1 yes 2015-04-27 14:03:35 256 
#4 1 yes    <NA>  0 
#5 1 yes    <NA>  0 
#6 1 yes 2015-04-27 16:59:42 10567 
#7 2 yes 2015-05-18 17:01:09 NA 
#8 2 yes 2015-05-18 17:03:40 151 
#9 2 yes 2015-05-18 17:04:00 20 
#10 2 yes    <NA>  0 
#11 2 yes    <NA>  0 

或用一个非常简洁的方式拍摄

df%>% 
    mutate(purch=zoo::na.locf(lubridate::ymd_hms(df$purchase))) %>% 
    group_by(id) %>% 
    mutate(dif=c(NA, diff(purch))) %>% 
    select(-purch) 

# packages [1] lubridate_1.3.3 zoo_1.7-12  dplyr_0.4.2  
+0

检查你的输出与预期的 –

+0

@Paulo问题在于第6行没有给出时间间隔。 – AliCivil

+0

是真的。它对'c(NA,diff(as.POSIXct(df $ purchase)))''也是有效的...... –