![見出し画像](https://assets.st-note.com/production/uploads/images/141423647/rectangle_large_type_2_39f50a9f74cac3f762b0c6a2f5f28de5.png?width=1200)
【統計】相関が強い=傾きが大きい?
論文を読んでいると、2つの数字の関係性を表す際に「相関」が使われていることがあります。
よく聞く説明は「一方が変われば他方もそれに連れて変わるような関係」などかと思います。
例えば「国語の点数が高い人は、数学の点数が高い。つまり国語と数学の点数は相関している」などです。相関の強さは「相関係数(r)」で表すことが多いです。
もう一つ、2つの数字の関係性を表すものに「傾き」があります。「一方が1変化した時に、他方がどれくらいの変化するか」を表します。
中学で習う一次関数でいう「y = ax + b」の「a」のことですね。
相関と傾きは別のものと説明されることが多い印象があります。相関が強いからと言って、傾きが大きいわけではない、みたいなことです。
ふと、これって本当なのかと疑問に思い、統計ソフトを使いながら考えてみました。
※今回使用したRコードのみ有料で、記事は全部無料で読めます
コードをR上にコピペすれば今回の内容を再現できます
相関と傾きのおさらい
普段論文や統計に馴染みのある方は読み飛ばしてください。
相関とは
前述したように、相関とは2つの変数(3つ以上の場合もありますが)について「一方が変われば他方もそれに連れて変わるような関係」のことです。
※変数とは「異なる値を取ることができる記号や要素」のことです。例えば長方形の面積の公式「縦の長さ × 横の高さ」の「縦の高さ」「横の高さ」や一次関数「y = 2x」の「y」や「x」がそれにあたります
関係性の強弱を「相関係数(r)」というもので、-1から1の範囲の値で表します。例えば、AとBの2つの変数の相関係数を見るときには
r = 1: 正の相関→Aが増えるとBも増える
r = 0: 相関がない→AとBに関係がない
r = -1: 負の相関→Aが増えるとBは減る
といった風に解釈します。1または-1に近づくほど「相関が強い」と言えます。
例えば、ある学校の生徒の国語と数学の点数の関係に関する相関係数は以下の手順で求めます
1.国語と算数それぞれの平均値を求める
2.偏差(それぞれのデータにおける平均値との差)を求める
各データの値から平均値を引いた値(偏差)を算出します。
例えば国語の平均点が60点で、Aさんの点数が70点なら、Aさんの国語の点数の偏差は70 - 60 = 10となります。
3.共分散を求める
各生徒の国語と数学の偏差を掛け合わした値を合計し、生徒数(サンプルサイズ)で割ります。2変量がどのように一緒に変動するかを表します。
4.標準偏差を求める
各生徒の偏差の2乗の平均を求めて、その平方根を取ります。そのデータのばらつき具合が分かります。
例えば国語の標準偏差は以下のように求めます。
![](https://assets.st-note.com/img/1716290890078-EVN26s2Cht.png)
5.相関係数を求める
共分散を標準偏差の積で割ると相関係数が算出されます。
傾きとは
こちらも前述のように「一方が1変化した時に、他方がどれくらいの変化するか」を表します。一次関数でいうと「y = ax + b」の「a」のことです。
例えば「y = 2x」なら「xが1増えるとyが2増える」
「y = -3x」なら「xが1増えるとyが-3減る」となります。
傾きが大きいということは「一方が変化したときに、他方が大きく変化する」といったイメージです。
Rで実験
統計ソフトのRを使って、相関係数と傾きの関係がどんな感じなのか実験してみようと思います(私は統計の専門家ではないので、もしかするともっといい方法があるかもしれません)。
Rのダウンロードはこちらから。無料です。
サンプルデータの作成
まずは、一つサンプルデータを作ってみます。
適当に傾きを0.8、相関係数を0.7と指定して、散布図を作成してみました。データは「とある患者集団1,000人の血圧と体重の関係」というケースを想定してみました。一応、体重の変化が血圧に影響するんじゃないかという仮定です。
これまた適当に、平均血圧を120 mmHg、平均体重を70 kgと設定し、Rにランダムなデータを作成してもらいました。
※現実世界のデータではありません
![](https://assets.st-note.com/img/1716255283641-Is9m2ZugQy.png?width=1200)
散布図というのは、図1のように縦軸と横軸にそれぞれの尺度を置き、各サンプル(患者)がどこに位置されるかを表したものです。青い線は回帰直線と呼ばれるもので、ざっくりいうと、2変量間の関係性を線で示しています(最小2乗法による)。この坂の角度で傾きがわかります。
作成されたデータの母数(母集団、つまりそのグループや集合の特性を表す平均値などの値)はこんな感じです。
相関係数:0.73
傾き:0.87
共分散:192.3
体重の平均(標準偏差):70.2 (14.9) kg
血圧の平均(標準偏差):120.7 (17.9) mmHg
ランダムに作成したデータなので指定した数値から少し誤差がありますが、大体指定通りですかね。
傾きを変えるとどうなるか
次に、相関係数と体重・血圧の平均値の指定はそのままに傾きを0.2に小さくしてみます。
![](https://assets.st-note.com/img/1716255353517-2zQj37srq1.png?width=1200)
坂の角度が小さくなりましたね(図2)。
ただ、同時に点が回帰直線の周りに密集していますね。
出力されたデータの母数はこんな感じです。
相関係数:0.73
傾き:0.22
共分散:48.2
体重の平均(標準偏差):70.2 (14.9) kg
血圧の平均(標準偏差):120.2 (4.5) mmHg
血圧の標準偏差が、先ほどの17.9から4.5に小さくなりましたね。
相関係数を変えるとどうなるか
次に、図1の傾きと体重・血圧の平均値の指定はそのままに相関係数を0.6に小さくしてみます。
![](https://assets.st-note.com/img/1716257174303-txZd3NuPGS.png?width=1200)
傾きは最初の散布図と変わりませんが、点が少し散らばった感じがしますね(図3)。
このデータの母数はこんな感じです。
相関係数:0.64
傾き:0.89
共分散:197.4
体重の平均(標準偏差):70.2 (14.9) kg
血圧の平均(標準偏差):120.2 (20.8) mmHg
今度は血圧の標準偏差が17.9から20.8に大きくなりました。しかし、共分散はあまり変わりませんでした。
相関係数と傾きの関係とは
相関係数と傾きをそれぞれ変えてみても、データを作成することができました。やはり相関が強いからといって、変数間の変化への影響が強いというわけではなさそうですね。
ただ、相関係数だけ変えたり、傾きだけ変えたりすると標準偏差が変動しました。例えば相関係数だけ小さくすると標準偏差が大きくなり、傾きだけ小さくすると標準偏差が小さくなりました。
ここでふと、「傾きが小さいと、標準偏差が小さくないと相関係数が大きくならない?」もしくは「傾きが大きいと、標準偏差が大きくても相関係数が大きくなる?」という疑問が浮かびました。
そこで、こんなことを試してみました。
体重を㎏からt(トン)に変えてみる
最初のデータ(図1)と傾きや相関係数の設定はそのままに、体重の単位をkgからtに変えてみました。1単位あたりの数値が1/1000になります。
![](https://assets.st-note.com/img/1716335338201-ZgN6jvX02L.png?width=1200)
横軸の縮尺的に、視覚的にはあまり変わらないようにも見えますが、 母数はこんな感じでした(図5)。
相関係数:0.73
傾き:871.9
共分散:0.2
体重の平均(標準偏差):0.07 (0.01) t
血圧の平均(標準偏差):120.7 (17.9) mmHg
傾きが約1,000倍くらいになりましたね。標準偏差も(単位を無視すると)0.01になって、かなり小さくなったように見えます。しかし、相関係数はそのままです。
つまり、傾きや標準偏差って単位や尺度に影響される側面があるということでしょう。測り方を変えてしまえば、ある程度は意図的に変えてしまえるということです。
しかし、例えば図4のような結果から単純に「傾きが大きいので、体重と血圧に大きな影響がありそう」と言ってしまっていいかというとそうでもないかと思います。「1トン体重が増えたら血圧が871.9 mmHg上がる」という結果にどういう意味があるのか?ということを考えないといけないですね。
図1を見れば「1kg体重が増えたら血圧が0.87mmHg上がる」ということなので、随分印象が変わってしまいます。このあたりが、効果量(どれだけ違いを生み出したり影響したりしたか)をみて判断することが重要と言われる理由でしょう(1, 2)
※繰り返しますが、これは仮想のデータなので本当にそういう関係性があるわけではありません。
そもそも相関係数も線形関係を前提としているので、一次関数的な関連じゃなかったまた違ったりしますよね(その話はまた別の機会に……)。
まとめ
相関係数と傾きには関係がなさそう。傾きが小さくて相関係数が高い、傾きが高くて相関係数が低いといった状況も当然ある
相関係数は変量の変化が他方にどれくらい関連しているかを示しているだけで、動きの大きさは関係ない
傾きは単位や尺度によって変化する。その傾きの大きさにどれくらい意味があるかを考える必要がある
文献
1)Wasserstein, R. L., & Lazar, N. A. (2016). The ASA Statement on p-Values: Context, Process, and Purpose. The American Statistician, 70(2), 129–133. https://doi.org/10.1080/00031305.2016.1154108
2) Cohen, J. (1988). Statistical Power Analysis for the Behavioral Sciences (2nd ed.). Routledge. https://doi.org/10.4324/9780203771587
今回使用したRコード
以下に今回使用したRコードを置いておきます。
黒い部分の右上のアイコンをクリックするとコピーできるので、R上に貼りつけて実行してみてください。
パッケージの準備
はじめに使用するパッケージを用意しておく必要があります。
以下コードを実行しておきます。
# 必要なパッケージの読み込み
if(!require(MASS)) install.packages("MASS")
library(MASS)
if(!require(ggplot2)) install.packages("ggplot2")
library(ggplot2)
相関係数0.7 傾き0.8の散布図の作成
# サンプルサイズ
n <- 1000
# 相関係数と標準偏差の設定
desired_r <- 0.7
desired_slope <- 0.8
mean_weight <- 70 # 体重の平均
mean_bp <- 120 # 血圧の平均
sd_weight <- 15 # 体重の標準偏差
# 体重データ生成
set.seed(123) # 再現性のためのシード設定
weight <- rnorm(n, mean = mean_weight, sd = sd_weight)
# 誤差の標準偏差を計算
sd_bp <- sqrt((desired_slope^2 * sd_weight^2) / (desired_r^2)) # 血圧の標準偏差を相関係数から計算
error_sd <- sqrt(sd_bp^2 * (1 - desired_r^2))
# 血圧データ生成
blood_pressure <- desired_slope * weight + rnorm(n, mean = mean_bp - desired_slope * mean_weight, sd = error_sd)
# データフレームの作成
df <- data.frame(weight = weight, blood_pressure = blood_pressure)
# 共分散を計算する関数
calculate_covariance <- function(x, y) {
n <- length(x)
mean_x <- mean(x)
mean_y <- mean(y)
covariance <- sum((x - mean_x) * (y - mean_y)) / n
return(covariance)
}
# 共分散の計算
covariance <- calculate_covariance(df$weight, df$blood_pressure)
cat("共分散:", covariance, "\n")
# 相関係数の計算
correlation_coefficient <- cor(df$weight, df$blood_pressure)
# 線形回帰モデルの適用
model <- lm(blood_pressure ~ weight, data = df)
slope <- coef(model)[2]
# 平均値の計算
mean_weight <- mean(df$weight)
mean_bp <- mean(df$blood_pressure)
# 標準偏差の計算
sd_weight <- sd(df$weight)
sd_bp <- sd(df$blood_pressure)
# 結果の表示
cat("相関係数:", correlation_coefficient, "\n")
cat("回帰直線の傾き:", slope, "\n")
cat("体重の平均値:", mean_weight, "\n")
cat("血圧の平均値:", mean_bp, "\n")
cat("体重の標準偏差:", sd_weight, "\n")
cat("血圧の標準偏差:", sd_bp, "\n")
# 軸の範囲を決定
x_range <- range(df$weight)
y_range <- range(df$blood_pressure)
# 散布図と回帰直線の描画
ggplot(df, aes(x = weight, y = blood_pressure)) +
geom_point() +
geom_smooth(method = "lm", col = "blue") +
labs(title = "Scatter Plot with Regression Line (Slope = 0.8)", x = "Weight (kg)", y = "Blood Pressure (mmHg)") +
theme_minimal() +
xlim(x_range) +
ylim(y_range)
相関係数0.7 傾き0.2の散布図の作成
# サンプルサイズ
n <- 1000
# 相関係数と標準偏差の設定
desired_r <- 0.7
desired_slope <- 0.2
mean_weight <- 70 # 体重の平均
mean_bp <- 120 # 血圧の平均
sd_weight <- 15 # 体重の標準偏差
# 体重データ生成
set.seed(123) # 再現性のためのシード設定
weight <- rnorm(n, mean = mean_weight, sd = sd_weight)
# 誤差の標準偏差を計算
sd_bp <- sqrt((desired_slope^2 * sd_weight^2) / (desired_r^2)) # 血圧の標準偏差を相関係数から計算
error_sd <- sqrt(sd_bp^2 * (1 - desired_r^2))
# 血圧データ生成
blood_pressure <- desired_slope * weight + rnorm(n, mean = mean_bp - desired_slope * mean_weight, sd = error_sd)
# データフレームの作成
df <- data.frame(weight = weight, blood_pressure = blood_pressure)
# 共分散を計算する関数
calculate_covariance <- function(x, y) {
n <- length(x)
mean_x <- mean(x)
mean_y <- mean(y)
covariance <- sum((x - mean_x) * (y - mean_y)) / n
return(covariance)
}
# 共分散の計算
covariance <- calculate_covariance(df$weight, df$blood_pressure)
cat("共分散:", covariance, "\n")
# 相関係数の計算
correlation_coefficient <- cor(df$weight, df$blood_pressure)
# 線形回帰モデルの適用
model <- lm(blood_pressure ~ weight, data = df)
slope <- coef(model)[2]
# 平均値の計算
mean_weight <- mean(df$weight)
mean_bp <- mean(df$blood_pressure)
# 標準偏差の計算
sd_weight <- sd(df$weight)
sd_bp <- sd(df$blood_pressure)
# 結果の表示
cat("相関係数:", correlation_coefficient, "\n")
cat("回帰直線の傾き:", slope, "\n")
cat("体重の平均値:", mean_weight, "\n")
cat("血圧の平均値:", mean_bp, "\n")
cat("体重の標準偏差:", sd_weight, "\n")
cat("血圧の標準偏差:", sd_bp, "\n")
# 軸の範囲を決定
x_range <- range(df$weight)
y_range <- range(df$blood_pressure)
# 散布図と回帰直線の描画(縦軸の範囲を固定)
ggplot(df, aes(x = weight, y = blood_pressure)) +
geom_point() +
geom_smooth(method = "lm", col = "blue") +
labs(title = "Scatter Plot with Regression Line (Slope = 0.2)", x = "Weight (kg)", y = "Blood Pressure (mmHg)") +
theme_minimal() +
xlim(x_range) +
ylim(y_range)
相関係数0.6 傾き0.8の相関図の作成
# サンプルサイズ
n <- 1000
# 相関係数と傾きの設定
desired_r <- 0.6
desired_slope <- 0.8
mean_weight <- 70 # 体重の平均
mean_bp <- 120 # 血圧の平均
sd_weight <- 15 # 体重の標準偏差
# 体重データ生成
set.seed(123) # 再現性のためのシード設定
weight <- rnorm(n, mean = mean_weight, sd = sd_weight)
# 誤差の標準偏差を計算
error_sd <- sqrt((1 - desired_r^2) * (desired_slope^2 * var(weight) / desired_r^2))
# 血圧データ生成
blood_pressure <- desired_slope * weight + rnorm(n, mean = 0, sd = error_sd) + mean_bp
# データフレームの作成
df <- data.frame(weight = weight, blood_pressure = blood_pressure)
# 共分散を計算する関数
calculate_covariance <- function(x, y) {
n <- length(x)
mean_x <- mean(x)
mean_y <- mean(y)
covariance <- sum((x - mean_x) * (y - mean_y)) / n
return(covariance)
}
# 共分散の計算
covariance <- calculate_covariance(df$weight, df$blood_pressure)
cat("共分散:", covariance, "\n")
# 実際の相関係数を計算
correlation_coefficient <- cor(df$weight, df$blood_pressure)
# 線形回帰モデルの適用
model <- lm(blood_pressure ~ weight, data = df)
slope <- coef(model)[2]
# 平均値の計算
mean_weight <- mean(df$weight)
mean_bp <- mean(df$blood_pressure)
# 標準偏差の計算
sd_weight <- sd(df$weight)
sd_bp <- sd(df$blood_pressure)
# 結果の表示
cat("相関係数:", correlation_coefficient, "\n")
cat("回帰直線の傾き:", slope, "\n")
cat("体重の平均値 (kg):", mean_weight, "\n")
cat("血圧の平均値:", mean_bp, "\n")
cat("体重の標準偏差 (kg):", sd_weight, "\n")
cat("血圧の標準偏差:", sd_bp, "\n")
# 軸の範囲を決定
x_range <- range(df$weight)
y_range <- range(df$blood_pressure)
# 散布図と回帰直線の描画
ggplot(df, aes(x = weight, y = blood_pressure)) +
geom_point() +
geom_smooth(method = "lm", col = "blue") +
labs(title = "Scatter Plot with Regression Line (Slope = 0.8, Correlation = 0.6)", x = "Weight (kg)", y = "Blood Pressure (mmHg)") +
theme_minimal() +
xlim(x_range) +
ylim(y_range)
体重の単位をkgからtに
# サンプルサイズ
n <- 1000
# 相関係数と標準偏差の設定
desired_r <- 0.7
desired_slope <- 0.8
mean_weight <- 70 # 体重の平均 (kg)
mean_bp <- 120 # 血圧の平均
sd_weight <- 15 # 体重の標準偏差 (kg)
# 体重データ生成 (kg)
set.seed(123) # 再現性のためのシード設定
weight_kg <- rnorm(n, mean = mean_weight, sd = sd_weight)
# 体重をトン (t) に変換
weight_ton <- weight_kg / 1000
# 誤差の標準偏差を計算
sd_bp <- sqrt((desired_slope^2 * sd_weight^2) / (desired_r^2)) # 血圧の標準偏差を相関係数から計算
error_sd <- sqrt(sd_bp^2 * (1 - desired_r^2))
# 血圧データ生成
blood_pressure <- desired_slope * weight_kg + rnorm(n, mean = mean_bp - desired_slope * mean_weight, sd = error_sd)
# データフレームの作成 (トン)
df_ton <- data.frame(weight = weight_ton, blood_pressure = blood_pressure)
# 共分散を計算する関数
calculate_covariance <- function(x, y) {
n <- length(x)
mean_x <- mean(x)
mean_y <- mean(y)
covariance <- sum((x - mean_x) * (y - mean_y)) / n
return(covariance)
}
# 共分散の計算
covariance_ton <- calculate_covariance(df_ton$weight, df_ton$blood_pressure)
cat("共分散 (トン):", covariance_ton, "\n")
# 相関係数の計算
correlation_coefficient_ton <- cor(df_ton$weight, df_ton$blood_pressure)
# 線形回帰モデルの適用
model_ton <- lm(blood_pressure ~ weight, data = df_ton)
slope_ton <- coef(model_ton)[2]
# 平均値の計算
mean_weight_ton <- mean(df_ton$weight)
mean_bp_ton <- mean(df_ton$blood_pressure)
# 標準偏差の計算
sd_weight_ton <- sd(df_ton$weight)
sd_bp_ton <- sd(df_ton$blood_pressure)
# 結果の表示
cat("相関係数 (トン):", correlation_coefficient_ton, "\n")
cat("回帰直線の傾き (トン):", slope_ton, "\n")
cat("体重の平均値 (トン):", mean_weight_ton, "\n")
cat("血圧の平均値:", mean_bp_ton, "\n")
cat("体重の標準偏差 (トン):", sd_weight_ton, "\n")
cat("血圧の標準偏差:", sd_bp_ton, "\n")
# 軸の範囲を決定
x_range_ton <- range(df_ton$weight)
y_range_ton <- range(df_ton$blood_pressure)
# 散布図と回帰直線の描画
ggplot(df_ton, aes(x = weight, y = blood_pressure)) +
geom_point() +
geom_smooth(method = "lm", col = "blue") +
labs(title = "Scatter Plot with Regression Line (Slope = 0.8, Weight in Tons)", x = "Weight (t)", y = "Blood Pressure (mmHg)") +
theme_minimal() +
xlim(x_range_ton) +
ylim(y_range_ton)
この記事が気に入ったらサポートをしてみませんか?