2016-10-12 26 views
1

我在数据中为各个客户ID的多个时间段创建三种类型的变量。这些新变量包括价格向量的总和,价格向量的均值以及日期向量中连续日期之间的平均差异。Data.table:通过各种数据子集动态创建变量并通过变量x进行分组,对最终结果进行子集

使用data.table,我循环了多个时间段,在每个时间段内对数据进行子集化,并计算各个客户ID的变量。这些变量中的每一个都是随着我在时间段内循环而动态命名的。就目前而言,这些变量正在被正确计算。

这里是我陷入困境的地方:在计算完所有这些变量后,我希望将数据子集包括新聚合变量以及每个客户的最近购买价格和日期元素。

我认为data.table可能会复制所有行对应每个客户的计算总数。但是,它仅复制与表i的索引中指定的时间间隔相对应的行中的总数。由于它不会在每个客户的所有行上复制这些总计,因此我的最终dplyr块无法实现。

在第二个和第三个代码块中,我将给出最终dplyr代码的输出,然后输出我想实现的输出。

这个问题源于一个类似的问题,我们在subsetting over fewer variables that are not being created dynamically

library(lubridate) 
library(data.table) 
library(dplyr) 

data <- data.frame(custid = c(rep(1, 25), rep(2, 25), rep(1, 25), rep(2, 25)), 
        purchase.price = seq(1, 200, by=2), 
        date = seq.Date(from=as.Date("2015-01-01"), to=as.Date("2015-04-10"), by="days")) 

period_intervals <- list(period_one = interval(as.Date("2015-01-01"), as.Date("2015-01-30")), 
         period_two = interval(as.Date("2015-02-01"), as.Date("2015-02-28")), 
         period_three = interval(as.Date("2015-03-01"), as.Date("2015-03-31")), 
         period_four = interval(as.Date("2015-04-01"), as.Date("2015-04-28"))) 


data <- as.data.table(data) 
data <- data[order(date)] 
setkey(data, custid) 

time_periods <- c(1:4) 

for(i in time_periods[1]:max(time_periods)){ 
    data <- data[date %within% period_intervals[[i]], 
       paste("period", i, "price.sum", sep="."):= sum(purchase.price), 
       by = custid] 

    data <- data[date %within% period_intervals[[i]], 
       paste("period", i, "price.mean", sep="."):= mean(purchase.price), 
       by = custid] 

    data <- data[date %within% period_intervals[[i]], 
       paste("period", i, "mean.diff.date", sep="."):= mean(as.numeric(diff(purchase.price))), 
       by = custid] 
} 

data_sub <- data %>% 
    group_by(custid) %>% 
    arrange(desc(date)) %>% 
    filter(row_number() == 1) 

从dplyr子集当前结果(显示前7列):

custid purchase.price  date period.1.price.sum period.1.price.mean period.1.mean.diff.date period.2.price.sum ... 
    <dbl>   <dbl>  <date>    <dbl>    <dbl>     <dbl>    <dbl> ... 
1  2   199 2015-04-10     NA     NA      NA     NA ... 
2  1   149 2015-03-16     NA     NA      NA     NA ... 

这是我所期待的(显示第7列):

 custid purchase.price  date period.1.price.sum period.1.price.mean period.1.mean.diff.date period.2.price.sum ... 
     <dbl>   <dbl>  <date>    <dbl>    <dbl>     <dbl>    <dbl> ... 
    1  2   199 2015-04-10    625     25      2    981 ... 
    2  1   149 2015-03-16    275     55      2    1539 ... 

注意:

在我完整的数据集中,我在10-20个时间段之间的任何地方循环。要计算的期数可能会发生变化,因此我的方法是动态创建新变量。

回答

2

我们可以用Map如在以前的帖子

nm1 <- sprintf("%s.%d.%s", "period", seq_along(period_intervals), "price.sum") 
nm2 <- sprintf("%s.%d.%s", "period", seq_along(period_intervals), "price.mean") 
nm3 <- sprintf("%s.%d.%s", "period", seq_along(period_intervals), "mean.diff.date") 
data[, c(rbind(nm1, nm2, nm3)) := unlist(Map(function(x,y) { 
     x1 <- purchase.price[x %within% y] 
     list(sum(x1), mean(x1), mean(as.numeric(diff(x1))))}, 
        list(date), period_intervals), recursive = FALSE), by = custid] 
data[order(custid, -date)][,.SD[1] , custid] 
+1

@Frank是的,你是对的。谢谢 – akrun

+0

看起来不错!我想知道为什么期间3中客户1的平均日期差异是NaN。查看'cust1_period3 <- data %>% 过滤器(%period_intervals [[3]]内的custid == 1和date%)%>% mutate(period.3.mean.diff.date = mean(as.numeric(diff(date ))))'返回1的平均日期差异? –

+0

@ToddYoung我认为列名已互换 – akrun

相关问题