给定不同的开始和结束日期,找出每个变量的日平均值
Given different start and end dates, find the daily average of each variable
我有不同开始日期和结束日期的数据。
mydata <- data.frame(id=c(1,2,3), start=c("2010/01/01","2010/01/01","2010/01/02"), end=c("2010/01/01","2010/01/05","2010/01/03"), a=c(140,750,56),b=c(48,25,36))
mydata
id start end a b
1 1 2010-01-01 2010-01-01 140 48
2 2 2010-01-01 2010-01-05 750 25
3 3 2010-01-02 2010-01-03 56 36
我想求每天变量 a 和 b 的平均值。下面我通过展开具有不同开始和结束日期的每一行来执行它,然后将其折叠回每日级别。
mydata$subt <- as.numeric(as.Date(mydata$end, "%Y/%m/%d") - as.Date(mydata$start, "%Y/%m/%d") + 1)
require(data.table)
mydata <- setDT(mydata)[ , list(idnum = id, date = seq(start, end, by = "day"), a=a/subt, b=b/subt), by = 1:nrow(mydata)]
mydata
nrow idnum date a b
1: 1 1 2010-01-01 140 48
2: 2 2 2010-01-01 150 5
3: 2 2 2010-01-02 150 5
4: 2 2 2010-01-03 150 5
5: 2 2 2010-01-04 150 5
6: 2 2 2010-01-05 150 5
7: 3 3 2010-01-02 28 18
8: 3 3 2010-01-03 28 18
mydata %>%
group_by(date) %>%
summarize(a = sum(a),
b = sum(b))
期望的结果:
date a b
<date> <dbl> <dbl>
1 2010-01-01 290 53
2 2010-01-02 178 23
3 2010-01-03 178 23
4 2010-01-04 150 5
5 2010-01-05 150 5
但是,我有很多行的开始日期和结束日期不同,有时差异的长度很长。我想知道是否有更简单的方法(即不展开每一行)来查找每个变量的日平均值。如果有一种方法可以在不首先找到每日数据的情况下找到每周平均值,那就太好了。谢谢!
这是 tidyverse
的选项。我们将 'start' 'end' 列转换为 Date
class 和 ymd
(来自 lubridate
),创建 seq
日期从 'start' 到 'end' 与 map2
、mutate
和 'a'、'b' 对应的元素除以 lengths
list
列 'date'、unnest
'date' 并按 'date' 分组,我们得到 'a'、[=29 的 sum
=]
library(dplyr)
library(tidyr)
library(lubridate)
library(purrr)
mydata %>%
mutate(across(c(start, end), ymd)) %>%
transmute(id, date = map2(start, end, seq, by = 'day'), a, b) %>%
mutate(across(c(a, b), ~ ./lengths(date))) %>%
unnest(date) %>%
group_by(date) %>%
summarise(across(c(a, b), sum, na.rm = TRUE))
# A tibble: 5 x 3
# date a b
# <date> <dbl> <dbl>
#1 2010-01-01 290 53
#2 2010-01-02 178 23
#3 2010-01-03 178 23
#4 2010-01-04 150 5
#5 2010-01-05 150 5
我有不同开始日期和结束日期的数据。
mydata <- data.frame(id=c(1,2,3), start=c("2010/01/01","2010/01/01","2010/01/02"), end=c("2010/01/01","2010/01/05","2010/01/03"), a=c(140,750,56),b=c(48,25,36))
mydata
id start end a b
1 1 2010-01-01 2010-01-01 140 48
2 2 2010-01-01 2010-01-05 750 25
3 3 2010-01-02 2010-01-03 56 36
我想求每天变量 a 和 b 的平均值。下面我通过展开具有不同开始和结束日期的每一行来执行它,然后将其折叠回每日级别。
mydata$subt <- as.numeric(as.Date(mydata$end, "%Y/%m/%d") - as.Date(mydata$start, "%Y/%m/%d") + 1)
require(data.table)
mydata <- setDT(mydata)[ , list(idnum = id, date = seq(start, end, by = "day"), a=a/subt, b=b/subt), by = 1:nrow(mydata)]
mydata
nrow idnum date a b
1: 1 1 2010-01-01 140 48
2: 2 2 2010-01-01 150 5
3: 2 2 2010-01-02 150 5
4: 2 2 2010-01-03 150 5
5: 2 2 2010-01-04 150 5
6: 2 2 2010-01-05 150 5
7: 3 3 2010-01-02 28 18
8: 3 3 2010-01-03 28 18
mydata %>%
group_by(date) %>%
summarize(a = sum(a),
b = sum(b))
期望的结果:
date a b
<date> <dbl> <dbl>
1 2010-01-01 290 53
2 2010-01-02 178 23
3 2010-01-03 178 23
4 2010-01-04 150 5
5 2010-01-05 150 5
但是,我有很多行的开始日期和结束日期不同,有时差异的长度很长。我想知道是否有更简单的方法(即不展开每一行)来查找每个变量的日平均值。如果有一种方法可以在不首先找到每日数据的情况下找到每周平均值,那就太好了。谢谢!
这是 tidyverse
的选项。我们将 'start' 'end' 列转换为 Date
class 和 ymd
(来自 lubridate
),创建 seq
日期从 'start' 到 'end' 与 map2
、mutate
和 'a'、'b' 对应的元素除以 lengths
list
列 'date'、unnest
'date' 并按 'date' 分组,我们得到 'a'、[=29 的 sum
=]
library(dplyr)
library(tidyr)
library(lubridate)
library(purrr)
mydata %>%
mutate(across(c(start, end), ymd)) %>%
transmute(id, date = map2(start, end, seq, by = 'day'), a, b) %>%
mutate(across(c(a, b), ~ ./lengths(date))) %>%
unnest(date) %>%
group_by(date) %>%
summarise(across(c(a, b), sum, na.rm = TRUE))
# A tibble: 5 x 3
# date a b
# <date> <dbl> <dbl>
#1 2010-01-01 290 53
#2 2010-01-02 178 23
#3 2010-01-03 178 23
#4 2010-01-04 150 5
#5 2010-01-05 150 5