corrplot

Author

データサイエンス関連基礎調査WG

Published

August 1, 2025

パッケージの概要

corrplotは、相関行列の可視化に特化したパッケージです。 デフォルトの設定でも相関行列を見やすい形で表示できるほか、 50を超えるパラメータにより見た目を自由にカスタマイズできます。

library(corrplot) 
library(Lahman) #今回使用するデータセット 
library(data.table) #データの成形に使用
library(lsr) #相関行列以外の例に使用

データセットの準備

今回は公開されているデータセットでもカラム数の多い、’Sean Lahman’s Baseball Database’というデータセットを使用します。

これはMLBの選手別・チーム別の成績等を蓄積したデータベースで、 今回は選手情報が格納されたPeople、各年度の打撃成績が格納されたBatting、 年俸が格納されたSalariesの3つのテーブルを結合して使用します。

データセットの詳細についてはパッケージ付属のDocumentationを参照してください。

まず、上記テーブルの読み込み・結合と、最低限の前処理を行います。

#大規模データの処理に向くdata.tableとしてデータを保持
dt_mlb_people <- as.data.table(People)
dt_mlb_batting <- as.data.table(Batting)
dt_mlb_salaries <- as.data.table(Salaries)
#People(選手情報)からは一部の列のみを取得
dt_mlb_people <- dt_mlb_people[,.(playerID, birthCountry, birthState, weight, height, bats, throws, birthDate)]
#Salaries(年俸)テーブルとBatting(打撃成績)をLeft join
dt_mlb <- dt_mlb_batting[dt_mlb_salaries, on = .(yearID, teamID, lgID, playerID)]
#上記テーブルとPeopleをLeft join
dt_mlb <- dt_mlb_people[dt_mlb, on = .(playerID)]
#文字列型となっている列などをfactor型に変換
dt_mlb$playerID <- as.factor(dt_mlb$playerID)
dt_mlb$birthCountry <- as.factor(dt_mlb$birthCountry)
dt_mlb$birthState <- as.factor(dt_mlb$birthState)
dt_mlb$stint <- as.factor(dt_mlb$stint)
#日付型となっている列を数値型に変換
dt_mlb$birthDate <- as.numeric(dt_mlb$birthDate)

出来上がったテーブルの概要は以下のとおり。

#レコード数
nrow(dt_mlb)
## [1] 26437
#列名リスト
names(dt_mlb)
##  [1] "playerID"     "birthCountry" "birthState"   "weight"       "height"      
##  [6] "bats"         "throws"       "birthDate"    "yearID"       "stint"       
## [11] "teamID"       "lgID"         "G"            "AB"           "R"           
## [16] "H"            "X2B"          "X3B"          "HR"           "RBI"         
## [21] "SB"           "CS"           "BB"           "SO"           "IBB"         
## [26] "HBP"          "SH"           "SF"           "GIDP"         "salary"
#テーブル表示
dt_mlb
##         playerID birthCountry birthState weight height   bats throws birthDate
##           <fctr>       <fctr>     <fctr>  <int>  <int> <fctr> <fctr>     <num>
##     1: barkele01          USA         KY    225     77      R      R     -5292
##     2: bedrost01          USA         MA    200     75      R      R     -4409
##     3: benedbr01          USA         AL    175     73      R      R     -5250
##     4:  campri01          USA         GA    195     73      R      R     -6049
##     5: ceronri01          USA         NJ    192     71      R      R     -5706
##    ---                                                                        
## 26433: strasst01          USA         CA    239     77      R      R      6775
## 26434: taylomi02          USA         FL    215     76      R      R      7754
## 26435: treinbl01          USA         KS    225     77      R      R      6755
## 26436: werthja01          USA         IL    235     77      R      R      3426
## 26437: zimmery01          USA         NC    215     75      R      R      5384
##        yearID  stint teamID   lgID     G    AB     R     H   X2B   X3B    HR
##         <int> <fctr> <fctr> <fctr> <int> <int> <int> <int> <int> <int> <int>
##     1:   1985      1    ATL     NL    20    17     0     0     0     0     0
##     2:   1985      1    ATL     NL    37    64     3     5     0     0     0
##     3:   1985      1    ATL     NL    70   208    12    42     6     0     0
##     4:   1985      1    ATL     NL    66    13     1     3     0     0     1
##     5:   1985      1    ATL     NL    96   282    15    61     9     0     3
##    ---                                                                      
## 26433:   2016      1    WAS     NL    24    48     3    10     1     0     0
## 26434:   2016      1    WAS     NL    76   221    28    51    11     0     7
## 26435:   2016      1    WAS     NL    73     0     0     0     0     0     0
## 26436:   2016      1    WAS     NL   143   525    84   128    28     0    21
## 26437:   2016      1    WAS     NL   115   427    60    93    18     1    15
##          RBI    SB    CS    BB    SO   IBB   HBP    SH    SF  GIDP   salary
##        <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>    <int>
##     1:     0     0     1     0     7     0     0     0     0     0   870000
##     2:     1     0     0     1    22     0     0     6     0     0   550000
##     3:    20     0     1    22    12     1     1     4     2     8   545000
##     4:     2     0     0     1     5     0     0     1     0     0   633333
##     5:    25     0     3    29    25     1     1     0     4    15   625000
##    ---                                                                     
## 26433:     2     0     0     2    11     0     0     7     0     2 10400000
## 26434:    16    14     3    14    77     0     1     0     1     2   524000
## 26435:     0     0     0     0     0     0     0     0     0     0   524900
## 26436:    69     5     1    71   139     0     4     0     6    17 21733615
## 26437:    46     4     1    29   104     1     5     0     6    12 14000000
#サマリを表示
summary(dt_mlb)
##       playerID        birthCountry     birthState        weight     
##  moyerja01:   25   USA      :20505   CA     : 4872   Min.   :140.0  
##  vizquom01:   24   D.R.     : 2140   TX     : 1551   1st Qu.:185.0  
##  glavito02:   23   Venezuela: 1107   FL     : 1490   Median :195.0  
##  bondsba01:   22   P.R.     :  892   NY     :  984   Mean   :199.2  
##  griffke02:   22   Mexico   :  333   IL     :  963   3rd Qu.:215.0  
##  rodrial01:   22   CAN      :  304   (Other):15534   Max.   :315.0  
##  (Other)  :26299   (Other)  : 1156   NA's   : 1043                  
##      height     bats      throws      birthDate            yearID    
##  Min.   :66.0   B: 2579   B:    0   Min.   :-16407.0   Min.   :1985  
##  1st Qu.:72.0   L: 7488   L: 5660   1st Qu.: -1918.0   1st Qu.:1994  
##  Median :74.0   R:16370   R:20777   Median :   575.0   Median :2001  
##  Mean   :73.5             S:    0   Mean   :   693.7   Mean   :2001  
##  3rd Qu.:75.0                       3rd Qu.:  3426.0   3rd Qu.:2009  
##  Max.   :83.0                       Max.   :  9168.0   Max.   :2016  
##                                                                      
##   stint           teamID      lgID             G                AB       
##  1   :25263   LAN    :  958   AL:12962   Min.   :  1.00   Min.   :  0.0  
##  2   :  163   CLE    :  950   NL:13475   1st Qu.: 29.00   1st Qu.:  1.0  
##  3   :   14   PHI    :  949              Median : 56.00   Median : 63.0  
##  4   :    1   BOS    :  945              Mean   : 67.84   Mean   :173.1  
##  NA's:  996   SLN    :  943              3rd Qu.:107.00   3rd Qu.:331.0  
##               BAL    :  940              Max.   :163.00   Max.   :716.0  
##               (Other):20752              NA's   :996      NA's   :996    
##        R                H               X2B              X3B         
##  Min.   :  0.00   Min.   :  0.00   Min.   : 0.000   Min.   : 0.0000  
##  1st Qu.:  0.00   1st Qu.:  0.00   1st Qu.: 0.000   1st Qu.: 0.0000  
##  Median :  5.00   Median : 11.00   Median : 2.000   Median : 0.0000  
##  Mean   : 23.35   Mean   : 45.64   Mean   : 8.816   Mean   : 0.9713  
##  3rd Qu.: 41.00   3rd Qu.: 85.00   3rd Qu.:16.000   3rd Qu.: 1.0000  
##  Max.   :152.00   Max.   :262.00   Max.   :59.000   Max.   :23.0000  
##  NA's   :996      NA's   :996      NA's   :996      NA's   :996      
##        HR              RBI               SB                CS        
##  Min.   : 0.000   Min.   :  0.00   Min.   :  0.000   Min.   : 0.000  
##  1st Qu.: 0.000   1st Qu.:  0.00   1st Qu.:  0.000   1st Qu.: 0.000  
##  Median : 0.000   Median :  5.00   Median :  0.000   Median : 0.000  
##  Mean   : 5.133   Mean   : 22.28   Mean   :  3.323   Mean   : 1.419  
##  3rd Qu.: 7.000   3rd Qu.: 38.00   3rd Qu.:  3.000   3rd Qu.: 2.000  
##  Max.   :73.000   Max.   :165.00   Max.   :110.000   Max.   :29.000  
##  NA's   :996      NA's   :996      NA's   :996       NA's   :996     
##        BB               SO             IBB               HBP        
##  Min.   :  0.00   Min.   :  0.0   Min.   :  0.000   Min.   : 0.000  
##  1st Qu.:  0.00   1st Qu.:  0.0   1st Qu.:  0.000   1st Qu.: 0.000  
##  Median :  4.00   Median : 17.0   Median :  0.000   Median : 0.000  
##  Mean   : 16.93   Mean   : 32.4   Mean   :  1.434   Mean   : 1.554  
##  3rd Qu.: 28.00   3rd Qu.: 55.0   3rd Qu.:  1.000   3rd Qu.: 2.000  
##  Max.   :232.00   Max.   :223.0   Max.   :120.000   Max.   :35.000  
##  NA's   :996      NA's   :996     NA's   :996       NA's   :996     
##        SH               SF              GIDP            salary        
##  Min.   : 0.000   Min.   : 0.000   Min.   : 0.000   Min.   :       0  
##  1st Qu.: 0.000   1st Qu.: 0.000   1st Qu.: 0.000   1st Qu.:  293750  
##  Median : 0.000   Median : 0.000   Median : 1.000   Median :  550000  
##  Mean   : 1.637   Mean   : 1.463   Mean   : 3.915   Mean   : 2085160  
##  3rd Qu.: 2.000   3rd Qu.: 2.000   3rd Qu.: 7.000   3rd Qu.: 2350000  
##  Max.   :39.000   Max.   :17.000   Max.   :35.000   Max.   :33000000  
##  NA's   :996      NA's   :996      NA's   :996

使用例

相関行列を計算するには数値型である必要があるため、factor型となっている特徴量は除いておきます。

cols_factor <- names(dt_mlb)[sapply(dt_mlb, is.factor)]
cols_nonfactor <- setdiff(names(dt_mlb), cols_factor)
dt <- dt_mlb[,.SD,.SDcol = c(cols_nonfactor)]

cor関数で相関行列を計算し、corrplot関数を用いて相関行列を可視化します。

salaryとの相関を確認してみると、打撃成績の中ではHR(ホームラン)との相関が相対的に強いように見えます。

mat_cor <- cor(dt, 
               method = 'pearson', #ピアソンの積率相関係数。順位相関係数(ケンドール、スピアマン)も使用できる。
               use = 'pairwise.complete.obs')
#NAとなっているデータの取り扱い。
#デフォルトはNAが混ざっている列の相関係数をNAとするものであったので、
#NAとなっているデータを無視して計算するように設定。
corrplot(mat_cor)

以下、いくつか見た目のカスタマイズ例を紹介します。

corrplot(mat_cor[c(1:12,22), c(1:12,22)],
         method = 'color', #単純な色分けのみにする
         tl.cex = 0.75, #特徴量名のフォント大きさ調節(小さめ)
         addCoef.col = 'black', #相関係数を指定した色で表示
         number.cex = 0.65, #相関係数のフォント大きさ調節(小さめ)
         order = 'AOE', #相関の高いもの同士が近くになるように表示順序を変更
         col = adjustcolor(COL2('BrBG', 200),#色合いを変更 200は色の段階数
                           offset = c(1/5, 1/5, 1/5, 0), #相関係数が見えやすいよう少し薄く色を調節
                           transform = diag(c(4/5, 4/5, 4/5, 1))) 
         )

mat_p <- cor.mtest(dt, conf.level = 0.95)$p #p値の計算
corrplot(mat_cor[c(1:12,22), c(1:12,22)],
         method = 'square', #正方形で表示
         diag = FALSE, #対角線は表示しない
         tl.pos = 'd', #特徴量名を対角線に表示
         tl.cex = 0.6, #特徴量名のフォント大きさ調節(小さめ)
         order = 'hclust', #相関の高いもの同士が近くになるように表示順序を変更
         addrect = 3, #hclustを選択した時のみ指定可能、近いもの同士を3つに分類して正方形の枠で囲む
         rect.col = 'gray40', #前述の枠の色
         p.mat = mat_p[c(1:12,22), c(1:12,22)], #p値行列を与える
         sig.level = 0.10, #p値が0.1以上であれば×を表示
         )

mat_p = cor.mtest(dt, conf.level = 0.95)$p #p値の計算
corrplot(mat_cor[c(1:12,22), c(1:12,22)],
         type = 'lower', #下半分のみ表示
         method = 'shade', #単純な色分けだが、指定した条件を満たすの場合は斜め線を入れる
         addshade = 'negative', #斜め線を入れる条件
         tl.cex = 0.6, #特徴量名のフォント大きさ調節(小さめ)
         order = 'alphabet', #名前順
         p.mat = mat_p[c(1:12,22), c(1:12,22)], #p値行列を与える
         insig ='label_sig', #p値に応じて*を入れる
         sig.level = c(0.001, 0.01, 0.05), #*の数のしきい値
         pch.cex = 0.9, #*の大きさ
         )

corrplot.mixed(mat_cor[c(1:12,22), c(1:12,22)], #corrplot.mixedとすると二つの表示形式をミックスできる
         lower = 'number', #下半分は相関係数を表示する
         upper = 'ellipse', #上半分は楕円で表示する
         tl.cex = 0.6, #特徴量名のフォント大きさ調節(小さめ)
         number.cex = 0.55, #相関係数のフォント大きさ調節(小さめ)
         order = 'AOE', #相関の高いもの同士が近くになるように表示順序を変更
         )

相関行列ではないものを表示することも可能です。

例えば、質的変数と量的変数の組に対して分散分析のイプシロンを表示してみます。

mat_nf <- matrix(nrow = length(cols_nonfactor), ncol = length(cols_factor))
rownames(mat_nf) <- cols_nonfactor
colnames(mat_nf) <- cols_factor

dt <- dt_mlb
for(c_r in cols_nonfactor){
  for(c_c in cols_factor){
    dt_tmp <- dt[!is.na(dt[[c_r]]) & !is.na(dt[[c_c]]),.SD, .SDcols = c(c_r, c_c)]
    mu <- mean(dt_tmp[[c_r]])
    ss_t <- sum((dt_tmp[[c_r]]-mu)^2)
    ss_m <- sum(dt_tmp[, .(ss = .N * (mean(.SD[[1]]) - ..mu)^2), by = c_c, .SDcols = c_r]$ss)
    ss_e <- ss_t - ss_m
    dig_free <- length(unique(dt_tmp[[c_c]]))-1
    ms_e <- ss_e/(nrow(dt_tmp)-dig_free-1)
    mat_nf[c_r, c_c] <- sqrt(max((ss_m - dig_free*ms_e)/ss_t, 0))
  }
}
corrplot(mat_nf[,setdiff(cols_factor, c('playerID'))],
         is.corr = FALSE, #相関行列ではない場合 (数値の範囲が[-1, 1]固定ではなくなる)
         col.lim = c(0, 1), #数値の範囲指定 
         method = 'color', tl.cex = 0.8,
         col = COL1('YlGn'),
         cl.ratio = 0.4 #凡例の幅調節 そのままだと細すぎたので太目に変更
         )
Warning in corrplot(mat_nf[, setdiff(cols_factor, c("playerID"))], is.corr =
FALSE, : col.lim interval too wide, please set a suitable value

また別の例として、質的変数同士の組に対してはクラメールの連関係数を表示してみます。

mat_ff <- matrix(nrow = length(cols_factor), ncol = length(cols_factor))
rownames(mat_ff) <- cols_factor
colnames(mat_ff) <- cols_factor

dt <- dt_mlb
for(c_r in cols_factor){
  for(c_c in cols_factor){
    #非常に小さいカテゴリがある場合は検定の仮定となる近似が満たされなくなるため、警告が表示される
    suppressWarnings(mat_ff[c_r, c_c] <- lsr::cramersV(dt[[c_r]], dt[[c_c]]))
  }
}
corrplot(mat_ff[setdiff(cols_factor, c('playerID')), setdiff(cols_factor, c('playerID'))],
         is.corr = FALSE, #相関行列ではない場合 (数値の範囲が[-1, 1]固定ではなくなる)
         col.lim = c(0, 1), #数値の範囲指定 
         method = 'color',
         addgrid.col = 'white', #罫線を白色で表示する
         tl.cex = 0.8, addCoef.col = 'black', number.cex = 0.65, 
         col = COL1('Blues'),
         )

参考