高校倫理1440914 views
英語614322 views
教育149564 views
LaTeX962713 views
小学社会310647 views
ヒストリア291310 views
高校生物551985 views
高校日本史190639 views
数学講師2890703 views
中学社会669002 views
Help
Tools
NewsSpreadsheetCalendarBookkeepingMarkdown TablesLanguage Model NewsLinux CommandsSlidesTier ListPen ToolIllustrationCrayonWatercolorPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchSwirl EffectLine ArtOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksCherry BlossomWater RippleWater SplashBreaking GlassGlass TextureFabric TextureWood GrainMarble TextureBrick Wall TextureMetal TextureWashi Paper TextureCardboard TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalUniversity Entrance Exam MathColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsRolling DiceCross SectionsMotion PathMechanicsWavesUniversity Entrance Exam Physics解析力学Quantum MechanicsStatistical MechanicsRelativityCelestial MechanicsAstrophysicsCosmologyElectromagnetic WavesCapacitorsLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHOrganic Reaction MapPeriodic TableComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseMuscle ContractionHormones and HomeostasisRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic TheoryShogi StrategyPiano Rhythm Game

English

点を 1 つ足すと相関が 0.98 から -0.29 へ……Python で散布図を描く

10 個の点から相関係数を出すと 0.980238 でした。ここに点を 1 つ足しただけで、値が になります。

正の強い関係が、負の弱い関係に変わりました。データは 10 個から 11 個になっただけです。

数字を出す前に散布図を描く理由が、この 1 例に入っています。

相関係数を出す

NumPy には相関行列を返す関数があります。

import numpy as np

x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
y = np.array([38, 38, 42, 54, 53, 58, 69, 67, 73, 83])

print(np.corrcoef(x, y))
[[1.       0.980238]
 [0.980238 1.      ]]

の行列が返ります。対角線は自分自身との相関なので 、知りたい値は非対角の位置にあります。

print(round(float(np.corrcoef(x, y)[0, 1]), 6))       # 0.980238
print(round(float(np.corrcoef(x, y)[0, 1]) ** 2, 6))  # 0.960867

2 乗すると決定係数になります。この 10 点では、 のばらつきの 96% が で説明できる形です。

pandas でも同じ値

表として持っているなら、pandas のメソッドが使えます。

import pandas as pd

frame = pd.DataFrame({'x': x, 'y': y})

print(frame.corr())
x         y
x  1.000000  0.980238
y  0.980238  1.000000

列が 3 つ以上あっても、すべての組み合わせが一度に出ます。列名がそのまま行と列の見出しになるので、読みやすい。

順位で測る相関

値そのものではなく順位で計算する方法もあります。引数で切りかえます。

print(frame.corr(method='spearman'))
x         y
x  1.000000  0.972649
y  0.972649  1.000000

0.972649 で、ふつうの相関係数 0.980238 とわずかに違います。

順位に直してから計算するので、外れ値の影響が小さくなります。値が 200 でも 2000 でも、順位が同じなら結果は変わらない。

ふつうの相関係数

値の大きさをそのまま使う。直線の当てはまり具合を測る

順位相関

順位だけを使う。単調に増えているかどうかを測る

曲がっていても単調に増えていれば、順位相関は に近くなります。直線かどうかを問わない形です。

差がはっきり出る例を作ってみます。 を 1 から 10、 とすると、順位はぴったり対応しているのに、値は右へ行くほど急に増える。

x = np.arange(1, 11)
y = 2 ** x
f = pd.DataFrame({'x': x, 'y': y})

print(round(float(f.corr().loc['x', 'y']), 4))                    # 0.7988
print(round(float(f.corr(method='spearman').loc['x', 'y']), 4))   # 1.0

ふつうの相関係数は 0.7988、順位相関は 1.0 でした。順位で見れば完全に対応しているので になります。

0.7988 という値だけを見ると「そこそこの関係」に見えますが、実際は が決まれば が一意に決まる関係です。どちらの数字も嘘ではなく、測っているものが違う。

散布図を描く

matplotlib で点を打ちます。

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(6, 4))
ax.scatter(x, y)
ax.set_xlabel('x')
ax.set_ylabel('y')
fig.savefig('scatter.png', dpi=100)

matplotlib.use(‘Agg’) は、画面を持たない環境で画像だけを作るための指定です。ファイルに保存するだけなら、これで足ります。

figsize は横と縦の長さをインチで、dpi は 1 インチあたりの画素数を指定します。 画素の横幅になる。

回帰直線を重ねる

最小二乗の直線は np.polyfit で出せます。次数に 1 を渡すと 1 次式になります。

slope, cut = np.polyfit(x, y, 1)

print(round(slope, 4), round(cut, 4))    # 5.0 30.0

ax.plot(x, cut + slope * x)

傾き 5.0、切片 30.0 でした。散布図の上にこの直線を重ねると、点が直線のまわりにどう散っているかが見えます。

相関係数 0.980238 という 1 つの数は、この散らばり方を要約したものです。要約する前の形は、図でしか確かめられません。

点が多いときの描き方

数千点を打つと、点が重なって形が見えなくなります。大きさと透明度を下げると、密度が読めるようになる。

rng = np.random.default_rng(0)
x = rng.normal(50, 10, 2000)
y = 0.6 * x + rng.normal(0, 8, 2000)

fig, ax = plt.subplots(figsize=(6, 4))
ax.scatter(x, y, s=8, alpha=0.2)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.grid(True, linewidth=0.3)
fig.tight_layout()
fig.savefig('dense.png', dpi=100)

print(round(float(np.corrcoef(x, y)[0, 1]), 4))   # 0.593

s は点の面積、alpha は透明度です。alpha を 0.2 にすると、5 個重なったところでちょうど濃くなります。

default_rng(0) の 0 は乱数の種で、これを固定すると毎回同じデータが出ます。結果を再現できるようにしておくと、あとで確かめ直せる。

grid の線は 0.3 と細くしています。目盛りの線が太いと、点より線のほうが目立ってしまう。

例:1 点で符号が変わる

さきほどの 10 点に を足してみます。

x3 = np.append(x, 30)
y3 = np.append(y, 20)

print(round(float(np.corrcoef(x3, y3)[0, 1]), 4))   # -0.2882

0.9802 が になりました。 が大きいのに が小さい点を 1 つ置いたので、全体の傾きが引きずられています。

同じ位置に を足すと、こんどは 0.9968 まで上がります。 の平均から遠い点ほど、傾きを決める力が強い。

相関が でも関係はある

反対に、関係があるのに相関係数が になる場合もあります。

curve = np.array([-3, -2, -1, 0, 1, 2, 3])

print(round(float(np.corrcoef(curve, curve ** 2)[0, 1]), 4))   # 0.0

なので、 から完全に決まります。それでも相関係数はちょうど

左半分の負の積と右半分の正の積が打ち消し合うためです。直線としてはどちらへも傾いていない、というのが相関係数の言い分になります。

散布図を描けば放物線が見えます。数字だけを見て「関係なし」と結論すると、この形を見のがす。

相関係数が測っているのは直線の当てはまり具合だけです。関係の有無ではありません。

に近い値が出たら、まず図を見る。放物線でも周期的な形でも、直線でなければ に近づきます。

描いてから数える

手順としては、図が先です。

散布図を描く

形と外れ値を目で確かめる

そのうえで相関係数を出す

外れ値が見つかったら、それが測定の誤りなのか、本当にそういう対象があるのかを調べます。落とすかどうかは、その判断のあとで決める。

図を描かずに数字だけを出すと、 という値をそのまま受けとることになります。1 点のせいだと分かるのは、図を見たときだけです。

見るべきところは決まっています。まず全体の形が直線に近いかどうか。次に、群れから外れた点があるかどうか。最後に、縦の散らばりが横の位置によって変わっていないか。

3 つ目は見のがしやすい。 が大きいところだけ縦に大きく散っている形は、回帰の前提が崩れている合図です。

この 3 つを目で確かめてから相関係数を出せば、その数字が何を要約しているかが分かった状態になります。

散布図を描いたら放物線の形をしていて、相関係数が 0.02 でした。どう読みますか。

  • には関係がない
  • 直線の関係は弱いが、曲線の関係はある
  • 計算をまちがえている
__RESULT__

相関係数が測るのは直線の当てはまり具合だけです。対称な放物線では正と負の寄与が打ち消し合い、 に近い値になります。関係がないという結論は出せません。

np.corrcoef で 1 行、matplotlib で数行。手間はほとんど同じなので、両方を出す習慣にしておくほうが安全です。

参考

numpy.corrcoef. NumPy Reference.
pandas.DataFrame.corr. pandas documentation.
F. J. Anscombe, *Graphs in Statistical Analysis*. The American Statistician 27(1), 17-21, 1973.
10 点で np.corrcoef が返した 0.980238 は、$(30, 20)$ を 1 つ足すだけで $-0.2882$ になります。$(30, 200)$ を足せば 0.9968。$x$ の平均から遠い点ほど直線を強く引っぱるためです。pandas の .corr() は列の総当たりを一度に返し、method='spearman' で順位相関に切りかえられます。$y = 2^x$ ではふつうの相関が 0.7988、順位相関が 1.0。matplotlib で散布図を出し、np.polyfit の傾き 5.0 と切片 30.0 を重ねるところ、2000 点を alpha=0.2 で描いて密度を見る書き方まで、実行して確かめた出力とともに並べます。