计算一段时间后的累计和
Calculate cumulative sum after a set period of time
我有一个包含 COVID 数据的数据框,我正在尝试制作一个列,根据阳性测试的数量计算康复人数。
我的数据有位置、日期和每天的测试数量 administered/positive results/negative 结果。这里有几行以一个位置为例(真实数据有几个月的日期):
loc date tests pos neg active
spot1 2020-04-10 1 1 0 5
spot1 2020-04-11 2 1 1 6
spot1 2020-04-12 0 0 0 6
spot1 2020-04-13 11 1 10 7
我想创建一个新列,在记录 14 天后累计计算每个位置的每个阳性测试。在 2020-04-24,5 个活动 类 不再活动,所以我想要一个包含 5 个的恢复列。对于每个日期,我都希望添加新的非活动案例。
我的第一个想法是循环尝试:
df1 <- df %>%
mutate(date = as.Date(date)) %>%
group_by(loc) %>%
mutate(rec = for (i in 1:nrow(df)) {
#getting number of new cases
x <- df$pos[i]
#add 14 days to the date
d <- df$date + 14
df$rec <- sum(x)
})
如您所见,我不是最擅长编写 for 循环的。这给了我一堆数字,但与数据没有什么有意义的关系。
也尝试过 map_dbl:
df1 <- df %>%
mutate(date = as.Date(date)) %>%
group_by(loc) %>%
mutate(rec = map_dbl(date, ~sum(pos[(date <= . + 14) & date >= .])))
这导致在整个 rec 列上打印相同的数字。
有什么建议吗? (抱歉解释冗长,只是想确保这一切都有意义)
library(tidyverse)
library(lubridate)
data %>%
mutate(date = as_date(date),
cut = cut(date, '14 days') %>%
group_by(loc) %>%
arrange(cut) %>%
mutate(cum_pos = accumulate(pos, `+`)) # accumulate(pos, sum) should also work
作为一般经验法则,避免循环,尤其是在 mutate 中——那是行不通的。你应该查看 purrr::accumulate
而不是 map_dbl
。在 R 的基础库中有专门的函数,例如 cumsum
和 cummin
,但它们的行为与 purrr 的行为相比更难预测。
您可以使用聚合对特定列求和然后应用
cut 以便为每个金额设置 14 天的时间范围:
df <- data.frame(loc = rep("spot1", 30),
date = seq(as.Date('2020-04-01'), as.Date('2020-04-30'),by = 1),
test = seq(1:30),
positive = seq(1:30),
active = seq(1:30))
output <- aggregate(positive ~ cut(date, "14 days"), df, sum)
output
控制台输出:
cut(date, "14 days") positive
1 2020-04-01 105
2 2020-04-15 301
3 2020-04-29 59
我的解决方案:
library(dplyr)
date_seq <- seq(as.Date("2020/04/01"), by = "day", length.out = 30)
pos <- rpois(n = 60, lambda = 10)
mydf <-
data.frame(loc = c(rep('loc1', 30), rep('loc2', 30)),
date = date_seq,
pos = pos)
head(mydf)
getPosSum <- function(max, tbl, myloc, daysBack = 14) {
max.Date <- as.Date(max)
sum(tbl %>%
filter(date >= max.Date - (daysBack - 1) &
date <= max.Date & loc == myloc) %>%
select(pos))
}
result <-
mydf %>%
group_by(date, loc) %>%
mutate(rec = getPosSum(max = date, tbl = mydf, myloc = loc))
您的示例数据显示 -
- 尽管
0
测试(4 月 12 日),您的所有日期都是连续的
Active
列似乎已经是 cumsum
因此我认为您可以简单地使用带有参数 14
的 lag
函数
示例代码
df %>% group_by(loc) %>% mutate(recovered = lag(active, 14)) %>% ungroup()
我有一个包含 COVID 数据的数据框,我正在尝试制作一个列,根据阳性测试的数量计算康复人数。
我的数据有位置、日期和每天的测试数量 administered/positive results/negative 结果。这里有几行以一个位置为例(真实数据有几个月的日期):
loc date tests pos neg active
spot1 2020-04-10 1 1 0 5
spot1 2020-04-11 2 1 1 6
spot1 2020-04-12 0 0 0 6
spot1 2020-04-13 11 1 10 7
我想创建一个新列,在记录 14 天后累计计算每个位置的每个阳性测试。在 2020-04-24,5 个活动 类 不再活动,所以我想要一个包含 5 个的恢复列。对于每个日期,我都希望添加新的非活动案例。
我的第一个想法是循环尝试:
df1 <- df %>%
mutate(date = as.Date(date)) %>%
group_by(loc) %>%
mutate(rec = for (i in 1:nrow(df)) {
#getting number of new cases
x <- df$pos[i]
#add 14 days to the date
d <- df$date + 14
df$rec <- sum(x)
})
如您所见,我不是最擅长编写 for 循环的。这给了我一堆数字,但与数据没有什么有意义的关系。
也尝试过 map_dbl:
df1 <- df %>%
mutate(date = as.Date(date)) %>%
group_by(loc) %>%
mutate(rec = map_dbl(date, ~sum(pos[(date <= . + 14) & date >= .])))
这导致在整个 rec 列上打印相同的数字。
有什么建议吗? (抱歉解释冗长,只是想确保这一切都有意义)
library(tidyverse)
library(lubridate)
data %>%
mutate(date = as_date(date),
cut = cut(date, '14 days') %>%
group_by(loc) %>%
arrange(cut) %>%
mutate(cum_pos = accumulate(pos, `+`)) # accumulate(pos, sum) should also work
作为一般经验法则,避免循环,尤其是在 mutate 中——那是行不通的。你应该查看 purrr::accumulate
而不是 map_dbl
。在 R 的基础库中有专门的函数,例如 cumsum
和 cummin
,但它们的行为与 purrr 的行为相比更难预测。
您可以使用聚合对特定列求和然后应用 cut 以便为每个金额设置 14 天的时间范围:
df <- data.frame(loc = rep("spot1", 30),
date = seq(as.Date('2020-04-01'), as.Date('2020-04-30'),by = 1),
test = seq(1:30),
positive = seq(1:30),
active = seq(1:30))
output <- aggregate(positive ~ cut(date, "14 days"), df, sum)
output
控制台输出:
cut(date, "14 days") positive
1 2020-04-01 105
2 2020-04-15 301
3 2020-04-29 59
我的解决方案:
library(dplyr)
date_seq <- seq(as.Date("2020/04/01"), by = "day", length.out = 30)
pos <- rpois(n = 60, lambda = 10)
mydf <-
data.frame(loc = c(rep('loc1', 30), rep('loc2', 30)),
date = date_seq,
pos = pos)
head(mydf)
getPosSum <- function(max, tbl, myloc, daysBack = 14) {
max.Date <- as.Date(max)
sum(tbl %>%
filter(date >= max.Date - (daysBack - 1) &
date <= max.Date & loc == myloc) %>%
select(pos))
}
result <-
mydf %>%
group_by(date, loc) %>%
mutate(rec = getPosSum(max = date, tbl = mydf, myloc = loc))
您的示例数据显示 -
- 尽管
0
测试(4 月 12 日),您的所有日期都是连续的 Active
列似乎已经是cumsum
因此我认为您可以简单地使用带有参数 14
lag
函数
示例代码
df %>% group_by(loc) %>% mutate(recovered = lag(active, 14)) %>% ungroup()