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)
corrplot
の方が使い慣れているという場合には、corrr::as_matrix
を利用すれば可視化まで持っていけます。
library(corrplot) store_sales_cor_df %>% as_matrix() %>% corrplot.mixed(lower = "number", upper = "square")