2022/11/27

【備忘録】時系列データの編集方法(R言語, tidyverse)

TimeSeries.knit

日付情報を含むデータの編集方法についての備忘録。

1 サンプルデータ作成

以下のようなサンプルデータ(100万件)を用意する。

  • date : 日付情報(YYYY-mm-dd形式)
  • sex : 性別 (Male | Female)
  • age : 年齢

このサンプルデータはコロナウィルス感染者情報のようなデータをイメージしている。

library(tidyverse)
library(lubridate)

x <- seq.Date(from=ymd('2022/1/1'), to=ymd('2023/12/31'), by='day')
size <- 1e6

### サンプルデータ作成
(f <- tibble(
     date=sample(
         x, size=size, replace=TRUE,
         prob=dnorm(0:(length(x)-1), mean=length(x)/2, sd=360)
     ),
     sex=sample(
         as.factor(c("Male", "Female")), size=size, replace=TRUE
     ),
     age=sample(
         0:120, size=size, replace=TRUE,
         prob=dnorm(0:120, mean=50, sd=12)
     )
 ))
## # A tibble: 1,000,000 × 3
##    date       sex      age
##    <date>     <fct>  <int>
##  1 2023-01-07 Female    65
##  2 2023-10-01 Male      38
##  3 2022-07-03 Female    21
##  4 2022-08-18 Female    32
##  5 2023-01-28 Female    30
##  6 2023-06-12 Female    40
##  7 2022-02-21 Male      59
##  8 2022-11-04 Male      59
##  9 2023-08-26 Female    58
## 10 2022-11-06 Male      35
## # … with 999,990 more rows

2 日付単位に集計する

サンプルデータを月単位、四半期毎に集計したい場合がある。この時に役に立つのが dplyr::count()lubridate::floor_date() 関数だ。

この関数はdate-timeオブジェクトの切り下げをしてくれる。切り下げる単位はunitで指定することができる。unitに指定できるキーワードは ‘second’, ‘minute’, ‘hour’, ‘day’, ‘week’, ‘month’, ‘bimonth’, ‘quarter’, ‘season’, ‘halfyear’, ’year’である。

2.1 月毎集計

(m1 <- f %>% count(date=floor_date(date, unit='month')))
## # A tibble: 24 × 2
##    date           n
##    <date>     <int>
##  1 2022-01-01 30988
##  2 2022-02-01 30411
##  3 2022-03-01 36084
##  4 2022-04-01 36886
##  5 2022-05-01 40681
##  6 2022-06-01 40937
##  7 2022-07-01 44938
##  8 2022-08-01 46297
##  9 2022-09-01 45799
## 10 2022-10-01 48739
## # … with 14 more rows
ggplot(data=m1) +
    aes(x=date, y=n) +
    geom_col(alpha=0.7) +
    scale_x_date(date_labels='%Y-%m')

2.2 四半期毎集計

(q1 <- f %>% count(date=floor_date(date, unit='quarter')))
## # A tibble: 8 × 2
##   date            n
##   <date>      <int>
## 1 2022-01-01  97483
## 2 2022-04-01 118504
## 3 2022-07-01 137034
## 4 2022-10-01 147193
## 5 2023-01-01 143190
## 6 2023-04-01 136268
## 7 2023-07-01 120621
## 8 2023-10-01  99707
ggplot(data=q1) +
    aes(x=date, y=n) +
    geom_col(alpha=0.7) +
    scale_x_date(date_labels='%Y-%m')

2.3 半期毎集計

(h1 <- f %>% count(date=floor_date(date, unit='halfyear')))
## # A tibble: 4 × 2
##   date            n
##   <date>      <int>
## 1 2022-01-01 215987
## 2 2022-07-01 284227
## 3 2023-01-01 279458
## 4 2023-07-01 220328
ggplot(data=h1) +
    aes(x=date, y=n) +
    geom_col(alpha=0.7) +
    scale_x_date(date_labels='%Y-%m')

2.4 年毎集計

(y1 <- f %>% count(date=floor_date(date, unit='year')))
## # A tibble: 2 × 2
##   date            n
##   <date>      <int>
## 1 2022-01-01 500214
## 2 2023-01-01 499786
ggplot(data=y1) +
    aes(x=date, y=n) +
    geom_col(alpha=0.7) +
    scale_x_date(date_labels='%Y', date_breaks='1 years')

3 年代別に集計する

サンプルデータを年代別に集計するには dplyr::count()dplyr::case_when() 関数を使う。

(a1 <- f %>%
    mutate(
        age2=case_when(
            age < 10  ~ "000~009歳",
            age < 20  ~ "010~019歳",
            age < 30  ~ "020~029歳",
            age < 40  ~ "030~039歳",
            age < 50  ~ "040~049歳",
            age < 60  ~ "050~059歳",
            age < 70  ~ "060~069歳",
            age < 80  ~ "070~079歳",
            age < 90  ~ "080~089歳",
            age < 100 ~ "090~099歳",
            age < 999 ~ "100~歳",
            TRUE ~ "その他"
        )
    )
)
## # A tibble: 1,000,000 × 4
##    date       sex      age age2      
##    <date>     <fct>  <int> <chr>     
##  1 2023-01-07 Female    65 060~069歳
##  2 2023-10-01 Male      38 030~039歳
##  3 2022-07-03 Female    21 020~029歳
##  4 2022-08-18 Female    32 030~039歳
##  5 2023-01-28 Female    30 030~039歳
##  6 2023-06-12 Female    40 040~049歳
##  7 2022-02-21 Male      59 050~059歳
##  8 2022-11-04 Male      59 050~059歳
##  9 2023-08-26 Female    58 050~059歳
## 10 2022-11-06 Male      35 030~039歳
## # … with 999,990 more rows
(a1 <- a1 %>% count(age2))
## # A tibble: 11 × 2
##    age2            n
##    <chr>       <int>
##  1 000~009歳    357
##  2 010~019歳   5131
##  3 020~029歳  38492
##  4 030~039歳 146958
##  5 040~049歳 292607
##  6 050~059歳 302126
##  7 060~069歳 162312
##  8 070~079歳  45045
##  9 080~089歳   6470
## 10 090~099歳    492
## 11 100~歳        10
ggplot(data=a1) +
    aes(x=fct_rev(age2), y=n) +
    geom_col(alpha=0.7) +
    coord_flip() +
    labs(x=NULL, y=NULL)

4 組み合わせる

サンプルデータを月別、男女別に集計する。

f %>%
    count(date=floor_date(date, unit='month'), sex) %>%
    ggplot() +
    aes(x=date, y=n, fill=sex) +
    geom_col(alpha=0.7) +
    facet_grid(rows=vars(sex)) +
    scale_x_date(date_labels='%Y-%m') +
    labs(x=NULL, y=NULL) +
    guides(fill='none')

【備忘録】時系列データの編集方法(R言語, tidyverse)

TimeSeries.knit 1 サンプルデータ作成 2 日付単位に集計する 2.1 月毎集計 2.2 四半期毎集計 ...