今週も特にありません

進捗どうですか?

tidy時系列データにおける相関計算 corrr

時系列データに対して相関を出す場面で、毎回どういう変換するんだっけを調べている気がするためメモします。

corrrパッケージでどのようなことができるのかについては、kazutanさんのページが大変参考になります。 kazutan.github.io

データ

店舗ごとの何らかの商品の売り上げのようなデータがあり、各店舗間の売り上げが相関しているのか分析したいということを想定しています。

library(tidyverse)
library(lubridate)
library(corrr)

set.seed(12345)
store_sales_tbl <- tibble(
  date = rep(seq(ymd("2019-01-01"), ymd("2019-12-31"), by = "1 week"), 5),
  store_name = c(rep("A", 53), rep("B", 53), rep("C", 53), rep("D", 53), rep("E", 53)),
  sales = rpois(53 * 5, 10)
)

データの形式としては、SQLでそのままの抽出してきたような状態が想定されます。

> store_sales_tbl
# A tibble: 265 x 3
   date       store_name sales
   <date>     <chr>      <int>
 1 2019-01-01 A             11
 2 2019-01-08 A             12
 3 2019-01-15 A              9
 4 2019-01-22 A              8
 5 2019-01-29 A             11
 6 2019-02-05 A              4
 7 2019-02-12 A             11
 8 2019-02-19 A              7
 9 2019-02-26 A              8
10 2019-03-05 A             11
# … with 255 more rows

相関計算

このようなデータに対して、tidyverse的にstats::corを適用するには意外と面倒です。corrr::correlateが適用できる形に持っていくのが早いです。

ここでは、時系列データの相関について、細かい考慮することはしませんが、変化率を計算する関数などを用意しておきます(ファイナンス関連だと対数変化率などの関数を利用することを想定します)。

cr <- function(x) {
  (x - lag(x)) / lag(x) * 100
}

あとは、このデータを一度、横持ちのデータに変換してから、変化率の系列に置き換え、corrr::correlateに繋げれば相関行列を算出できます。

store_sales_cor_df <- store_sales_tbl %>%
  spread(store_name, sales) %>%
  transmute_if(is.integer, cr) %>%
  correlate()

算出された相関行列を確認します。

> store_sales_cor_df
# A tibble: 5 x 6
  rowname        A        B        C        D       E
  <chr>      <dbl>    <dbl>    <dbl>    <dbl>   <dbl>
1 A        NA        0.118   -0.0512  -0.102    0.241
2 B         0.118   NA       -0.0853   0.0214   0.128
3 C        -0.0512  -0.0853  NA       -0.304   -0.212
4 D        -0.102    0.0214  -0.304   NA        0.158
5 E         0.241    0.128   -0.212    0.158   NA    

可視化

ここまでくると、ggplot2で可視化することもできますが、corrr::rplotを使えば、簡単に相関行列を可視化することができます。

store_sales_cor_df %>%
  rplot(print_cor = TRUE)

f:id:masaqol:20190414215924p:plain

corrplotの方が使い慣れているという場合には、corrr::as_matrixを利用すれば可視化まで持っていけます。

library(corrplot)

store_sales_cor_df %>%
  as_matrix() %>%
  corrplot.mixed(lower = "number", upper = "square")

f:id:masaqol:20190414215956p:plain

github.com