【发布时间】:2020-08-29 09:09:38
【问题描述】:
首先,我对 R 有点陌生,并且在管理一些时间序列数据时遇到了麻烦。我找到了一个可行的解决方案(代码如下),但在较大的数据集上速度非常慢(750k 行上的 1 个变量需要 35 分钟)。
我想要实现的是,每当USAGE 的值超过某个预定义的值 (usage_limit) 时,它就会开始计算行数,直到它再次超过相同的值,然后重置计数器。对于每个客户端,它以 NA 开头并且是 NA,直到它通过 usage_limit,此时计数器更改为 0。如果当计数器已更改为 0 时,NA 现在出现在 USAGE 中,它会正常计数。或者更简单地说,我正在尝试创建一个变量来显示过去USAGE 超过usage_limit 的行数(或者在我的情况下是几个月)。
这是用于计算USAGE_35PCT_MTH 的虚拟数据和预期输出和循环。这是在 R 3.5.1、lubridate 1.7.4 和 tidyverse 1.3.0 上完成的
library(lubridate)
library(tidyverse)
dummy_tb <- tibble("USER_ID"=c("000001", "000001", "000001", "000001", "000001", "000001", "000001", "000001", "000001", "000001", "000001", "000001", "000001", "000001", "000001", "200000", "200000", "200000", "200000", "200000", "200000", "200000", "200000"),
"REFERENCE_DATE"=c("31.01.2016", "29.02.2016", "31.03.2016", "30.04.2016", "31.05.2016", "30.06.2016", "31.07.2016", "31.08.2016", "30.09.2016", "31.10.2016", "30.11.2016", "31.12.2016", "31.01.2017", "28.02.2017", "31.03.2017", "31.03.2014", "30.04.2014", "31.05.2014", "30.06.2014", "31.07.2014", "31.08.2014", "30.09.2014", "31.10.2014"),
"USAGE"=c(0.30, 0.35, 0.34, 0.38, 0.40, 0.70, 0.78, 0.95, 0.36, 0.22, 0.11, 0.01, 0.1, 0.1, 0.1, NA, 0.36, 0.2, NA, 0.2, 0.2, NA, 0.2),
"USAGE_35PCT_MTH"=c(NA, 0, 1, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, NA, 0, 1, 2, 3, 4, 5, 6))
dummy_tb$REFERENCE_DATE <- as_datetime(dummy_tb$REFERENCE_DATE, format="%d.%m.%Y")
dummy_tb$REFERENCE_DATE <- as_date(dummy_tb$REFERENCE_DATE)
dummy_tb <- dummy_tb %>%
arrange(USER_ID, REFERENCE_DATE) %>%
mutate("USAGE_35PCT_MTH"=NA)
counter <- NA
user_curr <- ""
user_prev <- ""
usage_limit <- 0.35
for (row in 1:nrow(dummy_tb)){
user_curr <- dummy_tb[row, "USER_ID"]
if (user_curr != user_prev ) {
counter <- NA
}
checking_value <- dummy_tb[row, "USAGE"]
if (!is.na(checking_value)){
if (checking_value >= usage_limit) {
counter <- 0
}
}
dummy_tb[row, "USAGE_35PCT_MTH"] <- counter
counter <- counter + 1
user_prev <- user_curr
}
所以我的问题是,有没有办法加快速度?我一直在想办法使用 Dplyr,但还没有找到成功。
感谢您的帮助!
【问题讨论】: