在 R 中将每日数据转换为每周数据
Convert Daily Data into Weekly Data in R
我有 7 年的每日数据。我想将其分组为每周数据(基于实际日期)并对频率求和。
Date Frequency
1 2014-01-01 179
2 2014-01-02 82
3 2014-01-03 89
4 2014-01-04 109
5 2014-01-05 90
6 2014-01-06 66
7 2014-01-07 75
8 2014-01-08 106
9 2014-01-09 89
10 2014-01-10 82
实现该目标的最佳方法是什么?谢谢
我会用 library(lubridate)
.
df <- read.table(header = TRUE,text = "date Frequency
2014-01-01 179
2014-01-02 82
2014-01-03 89
2014-01-04 109
2014-01-05 90
2014-01-06 66
2014-01-07 75
2014-01-08 106
2014-01-09 89
2014-01-10 82")
您可以使用基数 R 或 library(dplyr)
:
碱基R:
确保日期确实是一个日期:
df$date <- ymd(df$date)
df$week <- week(df$date)
或简称:
df$week <- week(ymd(df$date))
或 dplyr:
library(dplyr)
df %>%
mutate(week = week(ymd(date))) %>%
group_by(week)
输出:
除非有充分的理由不这样做,否则您应该确保使用 ISO weeks 来确保聚合间隔的大小相同。
data.table
使这项工作像这样:
library(data.table)
setDT(myDF) # convert to data.table
myDF[ , .(weekly_freq = sum(Frequency)), by = isoweek(Date)]
也许你可以尝试使用 aggregate
+ format
的基本 R 代码,即
dfout <- aggregate(Frequency ~ yearweek,within(df,yearweek <- format(Date,"%Y,%W")),sum)
这样
> dfout
yearweek Frequency
1 2014,00 549
2 2014,01 418
数据
df <- structure(list(Date = structure(c(16071, 16072, 16073, 16074,
16075, 16076, 16077, 16078, 16079, 16080), class = "Date"), Frequency = c(179L,
82L, 89L, 109L, 90L, 66L, 75L, 106L, 89L, 82L)), row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10"), class = "data.frame")
这些解决方案都使用 base R,仅在周的定义和标记上有所不同。
1) cut
将日期转换为周,然后汇总这些日期。周从星期一开始,但如果您愿意,可以将 start.on.monday=FALSE
添加到 cut
以在星期日开始。
Week <- as.Date(cut(DF$Date, "week"))
aggregate(Frequency ~ Week, DF, sum)
## Week Frequency
## 1 2013-12-30 549
## 2 2014-01-06 418
2) 如果您希望将一周定义为从 DF$Date[1] 开始的 7 天,并根据该周的第一个日期标记它们,那么使用它。 (如果您喜欢一周中的最后一个日期,请将 6 添加到 Week
。)
weekno <- as.numeric(DF$Date - DF$Date[1]) %/% 7
Week <- DF$Date[1] + 7 * weekno
aggregate(Frequency ~ Week, DF, sum)
## Week Frequency
## 1 2014-01-01 690
## 2 2014-01-08 277
3) 或者如果您更喜欢用该周 DF
中存在的第一个日期来标记它,那么使用它。如果没有缺失日期,那么这个和上周的定义给出相同的结果,就像这里的情况一样。 (如果您想要一周中的最后一个现有日期而不是第一个,则将 match
替换为 findInterval
。)
weekno <- as.numeric(DF$Date - DF$Date[1]) %/% 7
Week <- DF$Date[match(weekno, weekno)]
aggregate(Frequency ~ Week, DF, sum)
## Week Frequency
## 1 2014-01-01 690
## 2 2014-01-08 277
备注
假定可重现形式的输入为:
Lines <- "Date Frequency
1 2014-01-01 179
2 2014-01-02 82
3 2014-01-03 89
4 2014-01-04 109
5 2014-01-05 90
6 2014-01-06 66
7 2014-01-07 75
8 2014-01-08 106
9 2014-01-09 89
10 2014-01-10 82"
DF <- read.table(text = Lines)
DF$Date <- as.Date(DF$Date)
来自 RStudio 的新包 slider
直接解决了这个问题,包括每周周期开始的规范。假设每周周期从星期一开始,那么第一周的开始时间为 Monday, 2013-12-30
。那么滑块解决方案将是
library(slider)
slide_period_dfr(.x = DF, .i=as.Date(DF$Date),
.period = "week",
.f = ~data.frame(week_ending = tail(.x$Date,1),
week_freq = sum(.x$Frequency)),
.origin = as.Date("2013-12-30"))
结果
week_ending week_freq
1 2014-01-05 549
2 2014-01-10 418
我有 7 年的每日数据。我想将其分组为每周数据(基于实际日期)并对频率求和。
Date Frequency
1 2014-01-01 179
2 2014-01-02 82
3 2014-01-03 89
4 2014-01-04 109
5 2014-01-05 90
6 2014-01-06 66
7 2014-01-07 75
8 2014-01-08 106
9 2014-01-09 89
10 2014-01-10 82
实现该目标的最佳方法是什么?谢谢
我会用 library(lubridate)
.
df <- read.table(header = TRUE,text = "date Frequency
2014-01-01 179
2014-01-02 82
2014-01-03 89
2014-01-04 109
2014-01-05 90
2014-01-06 66
2014-01-07 75
2014-01-08 106
2014-01-09 89
2014-01-10 82")
您可以使用基数 R 或 library(dplyr)
:
碱基R: 确保日期确实是一个日期:
df$date <- ymd(df$date)
df$week <- week(df$date)
或简称:
df$week <- week(ymd(df$date))
或 dplyr:
library(dplyr)
df %>%
mutate(week = week(ymd(date))) %>%
group_by(week)
输出:
除非有充分的理由不这样做,否则您应该确保使用 ISO weeks 来确保聚合间隔的大小相同。
data.table
使这项工作像这样:
library(data.table)
setDT(myDF) # convert to data.table
myDF[ , .(weekly_freq = sum(Frequency)), by = isoweek(Date)]
也许你可以尝试使用 aggregate
+ format
的基本 R 代码,即
dfout <- aggregate(Frequency ~ yearweek,within(df,yearweek <- format(Date,"%Y,%W")),sum)
这样
> dfout
yearweek Frequency
1 2014,00 549
2 2014,01 418
数据
df <- structure(list(Date = structure(c(16071, 16072, 16073, 16074,
16075, 16076, 16077, 16078, 16079, 16080), class = "Date"), Frequency = c(179L,
82L, 89L, 109L, 90L, 66L, 75L, 106L, 89L, 82L)), row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10"), class = "data.frame")
这些解决方案都使用 base R,仅在周的定义和标记上有所不同。
1) cut
将日期转换为周,然后汇总这些日期。周从星期一开始,但如果您愿意,可以将 start.on.monday=FALSE
添加到 cut
以在星期日开始。
Week <- as.Date(cut(DF$Date, "week"))
aggregate(Frequency ~ Week, DF, sum)
## Week Frequency
## 1 2013-12-30 549
## 2 2014-01-06 418
2) 如果您希望将一周定义为从 DF$Date[1] 开始的 7 天,并根据该周的第一个日期标记它们,那么使用它。 (如果您喜欢一周中的最后一个日期,请将 6 添加到 Week
。)
weekno <- as.numeric(DF$Date - DF$Date[1]) %/% 7
Week <- DF$Date[1] + 7 * weekno
aggregate(Frequency ~ Week, DF, sum)
## Week Frequency
## 1 2014-01-01 690
## 2 2014-01-08 277
3) 或者如果您更喜欢用该周 DF
中存在的第一个日期来标记它,那么使用它。如果没有缺失日期,那么这个和上周的定义给出相同的结果,就像这里的情况一样。 (如果您想要一周中的最后一个现有日期而不是第一个,则将 match
替换为 findInterval
。)
weekno <- as.numeric(DF$Date - DF$Date[1]) %/% 7
Week <- DF$Date[match(weekno, weekno)]
aggregate(Frequency ~ Week, DF, sum)
## Week Frequency
## 1 2014-01-01 690
## 2 2014-01-08 277
备注
假定可重现形式的输入为:
Lines <- "Date Frequency
1 2014-01-01 179
2 2014-01-02 82
3 2014-01-03 89
4 2014-01-04 109
5 2014-01-05 90
6 2014-01-06 66
7 2014-01-07 75
8 2014-01-08 106
9 2014-01-09 89
10 2014-01-10 82"
DF <- read.table(text = Lines)
DF$Date <- as.Date(DF$Date)
来自 RStudio 的新包 slider
直接解决了这个问题,包括每周周期开始的规范。假设每周周期从星期一开始,那么第一周的开始时间为 Monday, 2013-12-30
。那么滑块解决方案将是
library(slider)
slide_period_dfr(.x = DF, .i=as.Date(DF$Date),
.period = "week",
.f = ~data.frame(week_ending = tail(.x$Date,1),
week_freq = sum(.x$Frequency)),
.origin = as.Date("2013-12-30"))
结果
week_ending week_freq
1 2014-01-05 549
2 2014-01-10 418