Data.table:在各种数据子集上动态创建变量,并按变量x进行分组,对最终结果进行分组

时间:2016-10-12 14:57:38

标签: r data.table

我在多个时间段内为我的数据中的各个客户ID创建了三种类型的变量。这些新变量包括价格向量的总和,价格向量的平均值,以及日期向量中连续日期之间的平均差异。

使用data.table,我循环遍历多个时间段,对每个时段中的数据进行子集化,并为各个客户ID计算这些变量。当I循环遍历时间段时,这些变量中的每一个都是动态命名的。目前,这些变量正在正确计算。

这就是我陷入困境的地方:在计算完所有这些变量后,我希望将数据子集化,以包含新的聚合变量以及每个客户的最新purchase.price和date元素。

我认为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个时间段内循环。要计算的周期数可能会发生变化,因此我的方法是动态创建新变量。

1 个答案:

答案 0 :(得分: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]