describe()で平均値や標準偏差を確認したあとに、「売上と広告費には関係があるの?」「どの列とどの列が一緒に動いているの?」と気になることはありませんか?
そんなときに使えるのが、Pandasのcorr()です。corr()を使うと、複数の数値列の関係を相関係数としてまとめた「相関行列」を作れます。
ただし、df.corr()を実行して表を出すだけでは十分ではありません。大切なのは、相関係数の符号と大きさを読み、気になる組み合わせを散布図でも確認することです。
この記事では、Google Colabでそのまま試せる小さなDataFrameを使って、corr()の基本から相関行列の読み方、散布図との使い分けまで順番に解説します。
この記事でわかること
corr()を何のために使うのか- 相関係数の「1・0・-1」の意味
- DataFrameから相関行列を作り、どこを見ればよいか
- Pearson・Spearman・Kendallの基本的な違い
corr()とdescribe()・散布図の使い分け- 文字列型や欠損値があるときの注意点
- 相関係数だけで判断せず、散布図へ進む分析の流れ
この記事のゴールは、corr()で相関行列を作って正しく読み、気になる関係を散布図で確かめられるようになることです。
まず結論:corr()は「列と列の関係」をまとめて確認するときに使う
データを確認するときは、知りたいことによって使う方法を変えると迷いにくくなります。
| 知りたいこと | 主に使う方法 | 見えるもの |
|---|---|---|
| 1列の値を要約したい | describe() |
平均・標準偏差・四分位数など |
| 複数の数値列の関係を一覧で見たい | corr() |
相関係数・相関行列 |
| 2列の関係を目で確かめたい | 散布図(scatter) |
点の散らばり・外れ値・曲線的な関係 |
つまり、corr()は1列ずつを見るdescribe()と、2列を図で見る散布図の間をつなぐ役割があります。
基本統計量の確認方法を先に知りたい方は、pandas describe()の使い方も参考にしてください。DataFrameそのものがまだ不慣れな場合は、Pandas DataFrame入門から確認すると流れをつかみやすくなります。
相関係数とは?-1〜1の値をどう読むか
相関係数は、2つの数値がどの程度一緒に動くかを**-1から1の範囲**で表した値です。
| 相関係数の状態 | 読み方 | イメージ |
|---|---|---|
| 1に近い | 正の相関が強い | 一方が大きいほど、もう一方も大きい傾向 |
| 0付近 | 直線的な相関が弱い | 一方が変わっても、もう一方の増減がはっきりしない |
| -1に近い | 負の相関が強い | 一方が大きいほど、もう一方は小さい傾向 |
| 1または-1 | 完全な正・負の相関 | 点が完全に一直線に並ぶ関係 |
ここで重要なのは、符号は関係の向き、絶対値は直線的な関係の強さを見る手がかりだということです。たとえば-0.9は「マイナスだから弱い」のではなく、強い負の相関を示します。
また、「0.7以上なら必ず強い」のように数値だけで機械的に判断するのはおすすめできません。何を強いとみなすかは、データの種類や分析目的によって変わります。まずは相関係数で候補を見つけ、元データや散布図も確認するのが基本です。
相関を確認するサンプルDataFrameを作る
ここからは、ある店舗の12期間分のデータを例にします。広告費、売上、気温、返品件数という4つの数値列を用意します。
今回は相関の違いを確認しやすいように、関係がはっきり表れる練習用データを使用します。
この例で知りたいのは、どの列同士が一緒に増減しているのかです。まずは元データを確認しましょう。
import pandas as pd
df = pd.DataFrame({
"広告費": [10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65],
"売上": [82, 95, 103, 119, 128, 142, 151, 165, 172, 188, 197, 211],
"気温": [18, 25, 12, 28, 16, 22, 30, 14, 26, 19, 24, 20],
"返品件数": [42, 39, 37, 35, 32, 31, 28, 26, 24, 21, 19, 17]
})
df
| 広告費 | 売上 | 気温 | 返品件数 | |
|---|---|---|---|---|
| 0 | 10 | 82 | 18 | 42 |
| 1 | 15 | 95 | 25 | 39 |
| 2 | 20 | 103 | 12 | 37 |
| 3 | 25 | 119 | 28 | 35 |
| 4 | 30 | 128 | 16 | 32 |
| 5 | 35 | 142 | 22 | 31 |
| 6 | 40 | 151 | 30 | 28 |
| 7 | 45 | 165 | 14 | 26 |
| 8 | 50 | 172 | 26 | 24 |
| 9 | 55 | 188 | 19 | 21 |
| 10 | 60 | 197 | 24 | 19 |
| 11 | 65 | 211 | 20 | 17 |
元のDataFrameは、1行が1期間の観測データです。この12行から、列同士の関係をまとめた表へ変換するのが次のcorr()です。
pandas corr()の基本的な使い方
DataFrameの相関係数をまとめて求める基本形は、次の1行です。
corr_matrix = df.corr()
corr_matrix.round(3)
| 広告費 | 売上 | 気温 | 返品件数 | |
|---|---|---|---|---|
| 広告費 | 1.000 | 0.999 | 0.121 | -0.999 |
| 売上 | 0.999 | 1.000 | 0.122 | -0.998 |
| 気温 | 0.121 | 0.122 | 1.000 | -0.114 |
| 返品件数 | -0.999 | -0.998 | -0.114 | 1.000 |
実行すると、元の12行×4列のデータから、次のような4列×4列の相関行列が得られます。小数第3位に丸めると、おおよそ次の値です。
| 広告費 | 売上 | 気温 | 返品件数 | |
|---|---|---|---|---|
| 広告費 | 1.000 | 0.999 | 0.121 | -0.999 |
| 売上 | 0.999 | 1.000 | 0.122 | -0.998 |
| 気温 | 0.121 | 0.122 | 1.000 | -0.114 |
| 返品件数 | -0.999 | -0.998 | -0.114 | 1.000 |
これが「処理前→処理後」の大きな変化です。corr()は各行を個別に表示するのではなく、列と列の組み合わせごとに1つの相関係数を計算します。
相関行列は「対角線以外」を見る
相関行列を初めて見ると、1.000がたくさん並んでいて戸惑うかもしれません。見るポイントは2つです。
- 対角線はすべて1になる
広告費と広告費のように、同じ列を自分自身と比較しているためです。
- 上下には同じ組み合わせが重複する
広告費×売上と売上×広告費は同じ関係なので、同じ値になります。
そのため、初心者のうちは対角線ではなく、異なる列同士の値を見ると考えれば十分です。
特定の列との相関だけを確認する
相関行列全体ではなく、たとえば「売上とほかの列の関係だけを見たい」という場合は、列名を指定します。
# 「売上」とほかの列との相関だけを確認
corr_matrix["売上"].drop("売上")
| 売上 | |
|---|---|
| 広告費 | 0.999175 |
| 気温 | 0.122452 |
| 返品件数 | -0.998055 |
corr_matrix["売上"]で売上の列だけを取り出し、drop("売上")で売上自身との相関係数1.0を除いています。特定の指標と関係が強い列を探したいときに便利です。
ヒートマップで相関行列を視覚的に捉える
列数が多いDataFrameでは、相関行列をヒートマップにすると、相関の強さと向きを色で見分けやすくなります。ここでは、先ほど作ったcorr_matrixをそのまま可視化します。
seabornライブラリのheatmap関数を使うと、簡単にヒートマップを作成できます。
!pip install japanize_matplotlib
import seaborn as sns
import matplotlib.pyplot as plt
import japanize_matplotlib # 日本語フォントを有効にする
plt.figure(figsize=(8, 6))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', fmt='.3f', linewidths=.5)
plt.title('相関行列のヒートマップ')
plt.show()
このcoolwarm配色では、赤系が正の相関、青系が負の相関、白に近い色が0付近を示します。まず色で気になる組み合わせを見つけ、annot=Trueで表示した数値を確認しましょう。
正の相関・負の相関・弱い相関を同じデータで読む
先ほどの相関行列から、特徴の異なる3つの組み合わせを見てみましょう。
print("広告費と売上 :", round(corr_matrix.loc["広告費", "売上"], 3))
print("広告費と返品件数 :", round(corr_matrix.loc["広告費", "返品件数"], 3))
print("売上と気温 :", round(corr_matrix.loc["売上", "気温"], 3))
広告費と売上 : 0.999
広告費と返品件数 : -0.999
売上と気温 : 0.122
このサンプルでは、次のように読めます。
- 広告費と売上:0.999 → 強い正の相関がある
- 広告費と返品件数:-0.999 → 強い負の相関がある
- 売上と気温:0.122 → 少なくとも強い直線的な相関は見られない
ここで、0.122だから「売上と気温には絶対に何の関係もない」とは断定できません。corr()が捉える関係、とくに標準のPearson相関は直線的な関係が中心です。曲線的な関係や外れ値の影響は、相関係数だけでは見落とすことがあります。
このため、corr()は結論を自動的に出す道具ではなく、詳しく見る組み合わせを探す道具として使うと理解しやすいです。
Pearson・Spearman・Kendallはどう使い分ける?
DataFrame.corr()は、標準ではPearson(ピアソン)の相関係数を計算します。初心者が連続した数値データの直線的な関係を見るなら、まずPearsonから始めればよいでしょう。
| method | ざっくりした考え方 | 初心者が使う場面 |
|---|---|---|
pearson |
数値の直線的な関係を見る | まず基本として使う |
spearman |
値の順位にもとづいて単調な関係を見る | 順位関係を重視したいとき |
kendall |
順位の一致・不一致にもとづいて見る | 順位データなどで候補になる |
指定するときはmethod引数を使います。違いが見えやすいよう、ここだけ小さな比較用データを使います。xが増えるにつれてyも必ず増えますが、最後の値だけ大きく離れています。
method_df = pd.DataFrame({
"x": [1, 2, 3, 4, 5, 6, 7, 8],
"y": [1, 2, 3, 4, 5, 6, 7, 100]
})
print("Pearson :", round(method_df.corr(method="pearson").loc["x", "y"], 3))
print("Spearman:", round(method_df.corr(method="spearman").loc["x", "y"], 3))
print("Kendall :", round(method_df.corr(method="kendall").loc["x", "y"], 3))
Pearson : 0.624
Spearman: 1.0
Kendall : 1.0
この例では順位そのものは完全に同じ方向へ動いているため、SpearmanやKendallでは強い関係として表れます。一方、Pearsonは数値の直線的な関係を見るため、最後の大きな値の影響を受けます。
ここでは**「methodによって見ている関係が違う」**と分かれば十分です。Spearman・Kendallの統計理論や数式には深入りしません。通常の数値データで迷ったら、まずPearsonで確認し、分析目的に応じて別の方法を検討しましょう。
corr()でつまずきやすい3つのポイント
corr()は短いコードで使えますが、実際のCSVやExcelから読み込んだデータでは、データ型や欠損値に注意が必要です。
1. 数字に見えても文字列型になっていることがある
たとえばCSVから読み込んだ広告費が文字列になっていると、そのまま数値列として分析できないことがあります。まずdtypesで型を確認する習慣をつけましょう。
df_text = df.copy()
df_text["広告費"] = df_text["広告費"].astype(str)
df_text.dtypes
| 0 | |
|---|---|
| 広告費 | object |
| 売上 | int64 |
| 気温 | int64 |
| 返品件数 | int64 |
型が混在するDataFrameでは、初心者には数値列を明示してからcorr()を使う方法が分かりやすく、安全です。
numeric_df = df_text.select_dtypes(include="number")
numeric_df.corr().round(3)
| 売上 | 気温 | 返品件数 | |
|---|---|---|---|
| 売上 | 1.000 | 0.122 | -0.998 |
| 気温 | 0.122 | 1.000 | -0.114 |
| 返品件数 | -0.998 | -0.114 | 1.000 |
DataFrame.corr()にはnumeric_onlyという引数もあります。数値列だけを対象にする書き方としてdf.corr(numeric_only=True)もありますが、なぜ列が対象外になったのかを理解するためにも、先にdtypesで型を確認するのがおすすめです。
数値列だけを選ぶ方法はpandas select_dtypes()の使い方、文字列になった数字を数値型へ直す方法はpandas to_numeric()の使い方で詳しく解説しています。
2. 欠損値があっても「0」として計算されるわけではない
実データには欠損値が含まれることがあります。corr()では、対象となる2列について利用できる観測値を使って相関を計算します。欠損値を勝手に0へ置き換えて計算するわけではありません。
たとえば一部の売上を欠損値にして確認します。
df_missing = df.copy()
df_missing.loc[[2, 7], "売上"] = pd.NA
print(df_missing[["広告費", "売上"]].isna().sum())
df_missing[["広告費", "売上"]].corr().round(3)
広告費 0
売上 2
dtype: int64
| 広告費 | 売上 | |
|---|---|---|
| 広告費 | 1.000 | 0.999 |
| 売上 | 0.999 | 1.000 |
相関係数の計算に必要な最小データ数を決めたい場合は、min_periodsを指定できます。次の例では、広告費と売上の有効な組み合わせが10件しかないのに11件以上を必要とするため、この2列間の相関係数はNaNになります。
# 計算に必要な有効データ数を11件以上に指定
df_missing[["広告費", "売上"]].corr(min_periods=11)
| 広告費 | 売上 | |
|---|---|---|
| 広告費 | 1.0 | NaN |
| 売上 | NaN | NaN |
min_periodsは、少ないデータだけで相関係数が計算されるのを避けたい場合に便利です。PandasではPearson相関とSpearman相関で利用できます。
欠損が多いほど、組み合わせによって計算に使えるデータ数が変わる可能性があります。相関係数を見る前に「何件のデータが残っているのか」を意識しましょう。欠損値の場所や件数の確認は、Pandas isnull()で欠損値を確認する記事につなげて学べます。
なお、isnull()記事で扱っているmissingnoの「欠損パターン同士の相関」と、ここで扱う売上・広告費など通常の数値変数同士の相関は目的が異なります。
3. NaNが出たら「計算できる変化があるか」を確認する
相関係数がNaNになる代表例の1つが、すべて同じ値の列です。値が変化しない列では、通常の相関係数を計算できません。
df_constant = df[["広告費", "売上"]].copy()
df_constant["固定値"] = 1
df_constant.corr().round(3)
| 広告費 | 売上 | 固定値 | |
|---|---|---|---|
| 広告費 | 1.000 | 0.999 | NaN |
| 売上 | 0.999 | 1.000 | NaN |
| 固定値 | NaN | NaN | NaN |
corr()でNaNを見つけたら、エラーだと決めつけず、列の値がすべて同じではないか、欠損値が多すぎないか、計算に使えるデータが十分あるかを確認してください。
corr()だけで判断せず、散布図で形を確認する
相関係数は複数列を一覧で比較するのに便利ですが、点がどのように散らばっているかまでは分かりません。
たとえば広告費と売上は相関係数が約0.999でした。この関係を散布図でも確認してみましょう。
import matplotlib.pyplot as plt
plt.scatter(df["広告費"], df["売上"])
plt.xlabel("Ad cost")
plt.ylabel("Sales")
plt.title("Ad cost vs Sales")
plt.grid(alpha=0.3)
plt.show()
点が右上がりに並んでいれば、「広告費が大きい期間ほど売上も大きい」という傾向を目でも確認できます。
散布図には、相関係数だけでは気づきにくい次の情報があります。
- 外れた点がないか
- 点が直線ではなく曲線のように並んでいないか
- 一部の点だけが相関係数を大きく動かしていないか
したがって、corr()で候補を探す → 散布図で実際の形を見るという順番が実践的です。散布図の色・サイズ・凡例などは、Matplotlib scatter入門で詳しく解説しています。この記事ではcorr()の結果を確かめるための最小限の描画にとどめます。
データ分析では「確認→相関→可視化」の流れで使う
実際の分析では、いきなりcorr()だけを実行するより、次の順番で進めると迷いにくくなります。
head()やdtypesでDataFrameの中身と型を確認するdescribe()で各数値列の分布をざっくり確認する- 必要なら文字列の数字や欠損値を整える
corr()で列同士の相関を一覧する- 気になる組み合わせを散布図で確認する
つまり、corr()は前処理そのものではなく、整えたDataFrameを探索し、次に詳しく見るべき関係を見つける段階に位置づきます。
この流れを意識すると、df.corr()で表を出して終わるのではなく、分析の次の一手を決められるようになります。
注意:相関が高くても因果関係があるとは限らない
相関係数を読むときに、最も大切な注意点の1つです。
たとえば、このサンプルでは広告費と売上に強い正の相関があります。しかし、この結果だけから**「広告費を増やしたことが売上増加の原因である」**とは断定できません。季節、キャンペーン、来店客数など、別の要因が両方に影響している可能性もあります。
corr()が示すのは、あくまでデータ上の関係です。相関関係と因果関係は別物として扱いましょう。
まとめ:corr()で関係を見つけ、散布図で確かめよう
この記事では、Pandasのcorr()を使って相関係数・相関行列を確認する方法を解説しました。
corr()は列と列の関係を数値でまとめて確認するメソッド- 相関係数は-1〜1で、符号は向き、絶対値は直線的な関係の強さを見る手がかり
- 相関行列では、同じ列同士の対角線より異なる列同士を見る
- 標準のPearsonを基本にし、必要に応じてSpearman・Kendallを検討する
- 文字列型や欠損値がある場合は、計算前にデータを確認する
- 相関係数だけでは点の散らばりや外れ値が見えないため、散布図も組み合わせる
- 強い相関があっても、因果関係があるとは限らない
初心者のうちは、describe()で各列を確認 → corr()で列同士の関係を探す → scatterで形を確認という流れを覚えておくと、データ分析を一段進めやすくなります。
関連記事
pandas corr()とは何ですか?
corr()は、DataFrameやSeriesの数値データについて相関係数を計算するためのメソッドです。DataFrameに使うと、複数の列同士の相関係数をまとめた相関行列を作れます。
相関係数が1、-1、0に近い場合はどういう意味ですか?
1に近いほど強い正の相関、-1に近いほど強い負の相関を示します。0付近なら、少なくとも強い直線的な相関は見られません。ただし、0に近いからといって「あらゆる関係がない」とは断定できません。
corr()で文字列列がある場合はどうすればよいですか?
まずdtypesで型を確認してください。数値に見える文字列は必要に応じてto_numeric()で数値型へ変換します。分析対象を数値列に限定したい場合は、select_dtypes(include="number")で選択してからcorr()を使う方法が分かりやすいです。numeric_only=Trueを指定する方法もあります。
corr()でNaNが出るのはなぜですか?
すべて同じ値の列など、相関係数を計算できない場合はNaNになることがあります。欠損値が多く、2列の組み合わせで利用できるデータが十分にないケースにも注意してください。
PearsonとSpearmanはどう使い分けますか?
通常の数値について直線的な関係を見るなら、まず標準のPearsonが基本です。値そのものより順位関係・単調な関係を重視したい場合にはSpearmanが候補になります。Kendallも順位にもとづく方法ですが、この記事では統計理論の詳細には深入りしません。
DataFrame.corr()とSeries.corr()の違いは何ですか?
DataFrame.corr()は複数列の組み合わせをまとめて相関行列にします。2つのSeriesだけの相関係数が欲しい場合は、たとえばdf["広告費"].corr(df["売上"])のようにSeries.corr()を使えます。複数列を探索するならDataFrame、特定の2列だけならSeriesと考えると分かりやすいです。
corr()と散布図はどちらを使えばよいですか?
どちらか一方ではなく、組み合わせるのがおすすめです。まずcorr()で複数列から気になる組み合わせを見つけ、次に散布図で点の散らばり・外れ値・曲線的な関係を確認します。
相関係数が高ければ因果関係があると言えますか?
言えません。強い相関があっても、別の要因が両方に影響している可能性があります。corr()の結果だけから原因と結果を決めないようにしましょう。
pandasの相関行列はヒートマップにしたほうがよいですか?
列数が少なければ、まずcorr()の表を読めれば十分です。列数が多い場合はヒートマップで色分けすると全体を見やすくできますが、高度な装飾はこの記事の範囲外です。なお、通常の数値列の相関ヒートマップと、missingnoで見る欠損パターンの相関ヒートマップは目的が異なります。
コメント