查找每个类别的滚动总和最高的期间

时间:2015-03-11 11:23:29

标签: r rstudio

这就是事情。

我拥有相当大的数据集(150万行),代表40,000个客户端以及40个月以上的一些指标,因此数据看起来或多或少是这样的:

CLIENTID| MONTHID| VALUE
--------|--------|-------
client1 | month1 | value1
client1 | month2 | value2
client1 | month3 | value3
client2 | month1 | value4
client2 | month2 | value5
client3 | month1 | value6
client4 | month1 | value7
etc... 

并非每个CLIENTID都包含所有MONTHID,许多只在几个月内出现。

所以我正在尝试使用它:

我需要提取数据集中所有CLIENTID个月期间X的最大总和为VALUE的{​​{1}}个{生命期'X个月

这个X个月的期限是连续的,即使对于给定的MONTHID,特定的CLIENTID没有特定的X行,我会查看并发月数。

以下是我在心理上对自己进行可视化处理的逻辑细分:

  1. 从数据集中提取第一个MONTHID CLIENTID句点,并为每个VALUECLIENTID提取一个数字,以获得该期间每个CLIENTID的一个数字将其存储为PERIODID,新功能VALUE以及我的功能总结MONTHID

  2. 通过将句点的起始CLIENTID增加1,循环到每个CLIENTID的所有句点,并在给定{{1}}的新值大于的情况下替换存储集中的值以前存储的

  3. 所以这是我的问题:

    1. 首先:这种方法在逻辑上是否有效?我认为它应该可行,但也许在这种情况下可以使用更容易的解决方案

    2. 其次,最重要的是:如何在R中实现它?我还在学习R语言,我知道如何对数据进行子集化,总结它们等...但我正在使用像apply / mapply / etcpply(:P)这样的循环函数。

1 个答案:

答案 0 :(得分:1)

如果不知道你的数据是什么样的话,测试它有点困难,我不能说它的速度有多快,但这是一个可能的解决方案。

创建样本数据框:

set.seed(123)

df <- data.frame(
    CLIENTID = rep(c("a", "b", "c", "d"), each=10), 
    MONTHID = as.vector(replicate(4, sample(1:40, 10))), 
    VALUE = sample(100:500, 40, replace = T))

根据您在问题中的说法,对于某些CLIENTID,没有给定MONTHID的条目。我认为这意味着那个月的价值是0?在这种情况下,最简单的方法是拥有一个表示这些零值的数据框,我们可以使用expand.gridmerge来创建。

clientmonths <- expand.grid(
    CLIENTID = unique(df$CLIENTID), 
    MONTHID = seq(from=min(df$MONTHID), to=max(df$MONTHID)))

df2 <- merge(clientmonths, df, all = T)

df2$VALUE[is.na(df2$VALUE)] <- 0

在下文中,我使用base-R中的filter函数创建滚动总和,并使用dplyr包中完全不相关的filter函数...

library(dplyr)

getPeriodSum <- function(x, period) {
    x %>% 
    mutate(periodSUM = as.vector(stats::filter(VALUE, rep(1, period), sides=1))) %>%
    filter(periodSUM == max(periodSUM, na.rm = T)) %>%
    select(endMONTH = MONTHID, periodSUM)
}

df2 %>% arrange(MONTHID) %>% group_by(CLIENTID) %>% getPeriodSum(5)

此代码返回一个带有CLIENTID列的数据框,一个包含指定x月期间的最大累计值VALUE的periodSUM列,以及一个包含x月月末结束的MONTHID的endMONTH列。如果存在联系(即,可以通过多个月的序列生成相同的最大值),则每个CLIENTID将有多个行。

我使用值5来查找最多5个月的总数,但您可以将其更改为其他值。