每周聚合包含许多列的数据框

Aggregate dataframe with many columns per week

我有一个包含许多列和时间戳的大型数据框 (see picture) 我要做的是每周汇总所有列的数据。有什么建议吗?

亲切的问候, 丹尼尔

如果没有最小的可重现示例,则很难确切知道使用哪个函数来汇总数据(总和、平均值、中位数等)。

现在我们假设每一行代表一天或更细粒度的单位(因为日期列称为 Timestamp,我们看不到该字段中是否有实际时间值) .

我们使用 tidyrdplyrlubridate 的组合来创建汇总数据框,对列中的数据求和。

首先,我们生成了一些格式类似于屏幕截图中数据的原始数据,并将其读入 R。

rawData <- "Timestamp,Var.2,Amazonas,Antioquia,Arauca
2022-01-01,0,0,0,1
2022-01-02,0,0,1,3
2022-01-03,0,1,1,2
2022-01-04,0,0,1,0
2022-01-05,0,2,0,0
2022-01-06,3,0,2,2
2022-01-07,2,3,0,2
2022-01-08,1,0,0,0
2022-01-09,0,1,3,0
2022-01-10,0,0,0,0
2022-01-11,0,2,0,5
2022-01-12,0,0,3,0
2022-01-13,0,3,0,4
2022-01-14,0,0,4,0
2022-01-15,0,0,0,3
2022-01-16,0,0,0,0
2022-01-17,0,3,0,0
2022-01-18,0,0,2,3
2022-01-19,0,0,0,0
2022-01-20,0,2,0,0
2022-01-21,0,0,5,2
2022-01-22,0,0,0,0
2022-01-23,0,1,0,0
2022-01-24,0,0,3,1
2022-01-25,0,1,0,1
2022-01-26,0,0,0,1
2022-01-27,0,2,0,0
2022-01-28,0,2,0,1
2022-01-29,0,0,1,0
2022-01-30,0,0,1,0"

df <- read.csv(text = rawData,
               colClasses = c("Date","numeric","numeric","numeric","numeric"))

接下来,我们加载所需的库。在 lubridate 包中,我们将使用 year()week() 函数按一年中的一周对数据进行分组。

library(lubridate)
library(tidyr)
library(dplyr)

最后,我们使用 tidyr::pivot_longer() 创建长格式整洁数据,其中每一行代表宽格式数据框中一列一天的观察结果,创建 YearWeek列,以及 summarise() 数据框中的其余列。

df %>% pivot_longer(-Timestamp,names_to="Area") %>%
     mutate(Year = year(Timestamp),
            Week = week(Timestamp)) %>%
     group_by(Year,Week,Area) %>%
     summarise(summedValue = sum(value)) -> summarisedData

head(summarisedData)

...以及输出的前几行:

> head(summarisedData)
# A tibble: 6 × 4
# Groups:   Year, Week [2]
   Year  Week Area      summedValue
  <dbl> <dbl> <chr>           <dbl>
1  2022     1 Amazonas            6
2  2022     1 Antioquia           5
3  2022     1 Arauca             10
4  2022     1 Var.2               5
5  2022     2 Amazonas            6
6  2022     2 Antioquia          10
> 

如果我们需要原始格式的数据(宽格式整洁数据),我们可以使用pivot_wider()将数据恢复到原来的形状。

# if necessary, pivot_wider() to restore data to original format
summarisedData %>%
     pivot_wider(id_cols=c("Year","Week"),
                 names_from=Area,
                 values_from=summedValue)

...以及输出:

# A tibble: 5 × 6
# Groups:   Year, Week [5]
   Year  Week Amazonas Antioquia Arauca Var.2
  <dbl> <dbl>    <dbl>     <dbl>  <dbl> <dbl>
1  2022     1        6         5     10     5
2  2022     2        6        10      9     1
3  2022     3        5         7      8     0
4  2022     4        6         3      4     0
5  2022     5        0         2      0     0
> 

两件事:

[1] 绝不提供数据图片;提供数据。

[2] 答案取决于你如何定义“周”。例如,2022-01-01 是星期六。 ISO 8601 标准定义了从星期一开始的一周,因此 2022 年的第 1 周从 1 月 3 日开始。从技术上讲,1 月 1 日和 2 日是 2021 年最后一周的一部分。lubridate 中的 week(...) 函数以 7 天为增量计数从一年的第一天开始。所以很明显你会得到不同的答案。

这是使用 data.table 执行此操作的一种非常简单的方法,借用了@LenGreski 友情提供的最小可重现示例( 应该这样做)。

library(data.table)
setDT(df)[, lapply(.SD, sum), by=.(year=year(Timestamp), week=isoweek(Timestamp))]

##    year week Var.2 Amazonas Antioquia Arauca
## 1: 2022   52     0        0         1      4
## 2: 2022    1     6        7         7      6
## 3: 2022    2     0        5         7     12
## 4: 2022    3     0        6         7      5
## 5: 2022    4     0        5         5      4

第一个子句 setDT(df)df 转换为 data.table。其余部分将 sum(...) 函数应用于 .SD 引用的 data.table 中的列子集。默认子集是除 by=... 子句中引用的列之外的所有列(因此,除 Timestamp 之外的所有列)。