查找每个类别滚动总和最高的时期
Finding the period with the highest rolling sum per category
事情是这样的。
我有相当大的数据集(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
提取他们 "life" 的 X
个月期间,在所有 X
个月中总和最大的 VALUE
数据集中可用的时间段。
从某种意义上说,这个 X
月份是连续的,即使对于给定 CLIENTID
.[=31 的特定 MONTHID
没有行=]
以下是我如何在脑海中想象自己的过程的逻辑分解:
从数据集中提取第一个 X
MONTHID
周期,并为每个 CLIENTID
求和 VALUE
以获得每个 CLIENTID
的一个数字在那段时间并将其与 CLIENTID
、一些新的 PERIODID
和我的特征的 VALUE
相加。
通过将周期的开始 MONTHID
增加一个,遍历每个周期的所有周期 CLIENTID
并在给定 [=11= 的新值时替换存储集中的这些值]比之前存储的
大
所以这是我的问题:
首先:这种方法在逻辑上是否有效?我认为它应该可行,但也许有更简单的解决方案可用于这种情况
其次也是最重要的:如何在R中实现?我仍在学习 R 语言,我知道如何对数据进行子集化、汇总等……但我正在使用 apply/mapply/etcpply (:P) 等循环函数。
如果不知道你的数据是什么样子,测试这个有点困难,我不能说它有多快,但这是一个可能的解决方案。
创建示例数据框:
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.grid
和 merge
.
创建它
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)
此代码 returns 具有 CLIENTID 列的数据框、包含指定 x 个月期间 VALUE 的最大累积和的 periodSUM 列以及包含该月末的 MONTHID 的 endMONTH 列x 个月期间。如果有关系(即相同的最大值可以由多个月份序列产生),每个 CLIENTID 将有不止一行。
我使用值 5 来查找最大 5 个月的总数,但您可以将其更改为其他值。
事情是这样的。
我有相当大的数据集(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
提取他们 "life" 的 X
个月期间,在所有 X
个月中总和最大的 VALUE
数据集中可用的时间段。
从某种意义上说,这个 X
月份是连续的,即使对于给定 CLIENTID
.[=31 的特定 MONTHID
没有行=]
以下是我如何在脑海中想象自己的过程的逻辑分解:
从数据集中提取第一个
X
MONTHID
周期,并为每个CLIENTID
求和VALUE
以获得每个CLIENTID
的一个数字在那段时间并将其与CLIENTID
、一些新的PERIODID
和我的特征的VALUE
相加。通过将周期的开始
MONTHID
增加一个,遍历每个周期的所有周期CLIENTID
并在给定 [=11= 的新值时替换存储集中的这些值]比之前存储的 大
所以这是我的问题:
首先:这种方法在逻辑上是否有效?我认为它应该可行,但也许有更简单的解决方案可用于这种情况
其次也是最重要的:如何在R中实现?我仍在学习 R 语言,我知道如何对数据进行子集化、汇总等……但我正在使用 apply/mapply/etcpply (:P) 等循环函数。
如果不知道你的数据是什么样子,测试这个有点困难,我不能说它有多快,但这是一个可能的解决方案。
创建示例数据框:
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.grid
和 merge
.
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)
此代码 returns 具有 CLIENTID 列的数据框、包含指定 x 个月期间 VALUE 的最大累积和的 periodSUM 列以及包含该月末的 MONTHID 的 endMONTH 列x 个月期间。如果有关系(即相同的最大值可以由多个月份序列产生),每个 CLIENTID 将有不止一行。
我使用值 5 来查找最大 5 个月的总数,但您可以将其更改为其他值。