このページに対応するRmdファイル:GitHub
タイタニック号乗客データを読み込む.
titanic <- read.csv("https://raw.githubusercontent.com/kurodaecon/bs/main/data/titanic3_csv.csv")
性別変数 sex
を例に利用.
head(titanic$sex)
## [1] "female" "male" "female" "male" "female" "male"
table(ベクトル)
で1変数の度数分布表を作成できる.
table(titanic$sex)
##
## female male
## 466 843
female
と male
それぞれを数える場合.
head(titanic$sex == "female") # logical ... TRUE or FALSE
## [1] TRUE FALSE TRUE FALSE TRUE FALSE
sum(titanic$sex == "female") # the number of TRUE = the number of female
## [1] 466
sum(titanic$sex == "male") # the number of male
## [1] 843
この table
関数を利用してデータに欠損値 (NA)
があるかを確認するとよい. 欠損値である場合に TRUE を返す関数
is.na
を併用する.
is.na(NA)
## [1] TRUE
is.na(c(1, 10, NA, 1000))
## [1] FALSE FALSE TRUE FALSE
table(is.na(c(1, 10, NA, 1000)))
##
## FALSE TRUE
## 3 1
table(is.na(titanic$sex))
##
## FALSE
## 1309
barplot(度数分布表または度数ベクトル)
で作成.
barplot(table(titanic$sex))
棒グラフと同様に pie(度数分布表または度数ベクトル)
で作成.
pie(table(titanic$sex))
ラベルに「%」を追加する.
titanic_sex_table <- table(titanic$sex)
titanic_sex_label <- paste(names(titanic_sex_table), " ",
round(100 * titanic_sex_table / sum(titanic_sex_table), 1), "%", sep = "")
pie(titanic_sex_table, labels = titanic_sex_label)
このコードはどのように動いているのか?
paste("female", " ", 35.6, "%", sep = "")
## [1] "female 35.6%"
titanic_sex_table / sum(titanic_sex_table)
##
## female male
## 0.3559969 0.6440031
round(100 * titanic_sex_table / sum(titanic_sex_table), 1)
##
## female male
## 35.6 64.4
注:ちょっとしたグラフを作成する程度ならExcelの方が便利という場合もよくある.
2つの質的変数の分割表(クロス集計表)も table
関数で作成できる.
table(1つ目のベクトル, 2つ目のベクトル)
のように2つの変数を引数として指定する.
table(titanic$sex, titanic$survived)
##
## 0 1
## female 127 339
## male 682 161
table(titanic[, c("sex", "survived")]) # same as above
## survived
## sex 0 1
## female 127 339
## male 682 161
セルを1つずつカウントすることもできる.
sum(titanic$sex == "female" & titanic$survived == 0)
## [1] 127
sum(titanic$sex == "female" & titanic$survived == 1)
## [1] 339
sum(titanic$sex == "male" & titanic$survived == 0)
## [1] 682
sum(titanic$sex == "male" & titanic$survived == 1)
## [1] 161
出港地 embarked
を例として.
table(titanic$embarked)
##
## C Q S
## 2 270 123 914
table(titanic$embarked == "") # 中身のない空の観測値がある
##
## FALSE TRUE
## 1307 2
names(which.max(table(titanic$embarked)))
## [1] "S"
年齢変数 age
を例に利用. 欠損値もある.
head(titanic$age)
## [1] 29.00 0.92 2.00 30.00 25.00 48.00
table(is.na(titanic$age))
##
## FALSE TRUE
## 1046 263
hist(ベクトル)
で作成. breaks
引数でセルの数を調整できる.
hist(titanic$age)
hist(titanic$age, breaks = 30) # set the number of cells
度数ではなく相対度数(全体に占める割合)で表示する場合は
freq = FALSE
という引数を追加する.
(おまけ)滑らかな曲線をフィットさせるには density
関数でカーネル密度推定を行って lines
関数で重ね描きする.
hist(titanic$age, freq = FALSE)
lines(density(titanic$age, na.rm = TRUE))
[0, 20), [20, 40), [40, 60), [60, 100) の4区間で作成する.
そのために,cut
関数を利用して実数データを上の4区間に変換する.
breaks
引数で区間の区切り値のベクトルを指定right = FALSE
引数を追加titanic_age_interval <- cut(titanic$age, breaks = c(0, 20, 40, 60, 100), right = FALSE)
table(titanic_age_interval)
## titanic_age_interval
## [0,20) [20,40) [40,60) [60,100)
## 225 576 205 40
table(titanic_age_interval) / sum(table(titanic_age_interval)) # relative frequency
## titanic_age_interval
## [0,20) [20,40) [40,60) [60,100)
## 0.21510516 0.55066922 0.19598470 0.03824092
同様に,分割表は以下のように作成できる.
table(titanic_age_interval, titanic$survived)
##
## titanic_age_interval 0 1
## [0,20) 119 106
## [20,40) 351 225
## [40,60) 121 84
## [60,100) 28 12
標本平均
\[ \bar{x} = \frac{1}{n} \sum_i x_i \]
x <- c(1, 2, 6)
1 + 2 + 6 # sum (1+2+6=9)
## [1] 9
sum(x) # sum
## [1] 9
sum(x) / 3 # definition of mean
## [1] 3
mean(x)
## [1] 3
mean(c(1, 2, 6)) # same as above
## [1] 3
「平均」はデータの分布の重心である. データの平均からの偏差 \(x_i - \bar{x}\) およびその和を考えてみよう.
x - mean(x)
## [1] -2 -1 3
sum(x - mean(x))
## [1] 0
平均からの偏差(平均からの乖離)をすべて足すと 0 になる(そのような値が「平均」として定義されているともいえる).
\[ \sum_i (x_i - \bar{x}) = \sum_i x_i - n \bar{x} = \sum_i x_i - n \left( \frac{1}{n} \sum_i x_i \right) = 0 \]
欠損値 NA
があると計算結果も NA
になる.
その場合は NA
を除外して平均を計算するために
na.rm = TRUE
引数を追加する.
mean(titanic$age)
## [1] NA
mean(titanic$age, na.rm = TRUE)
## [1] 29.88114
quantile
関数は,デフォルトでは 0%(最小値),
25%(第1四分位数), 50%(中央値), 75%(第3四分位数), 100%(最大値)
を出力.
quantile(c(1, 2, 4, 7, 8, 11, 13, 13, 15, 16, 18)) # returns quartiles as default 四分位数
## 0% 25% 50% 75% 100%
## 1.0 5.5 11.0 14.0 18.0
quantile(titanic$age, na.rm = TRUE)
## 0% 25% 50% 75% 100%
## 0.17 21.00 28.00 39.00 80.00
summary(titanic$age)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 0.17 21.00 28.00 29.88 39.00 80.00 263
summary関数も四分位点を報告するが,quantile関数を使った場合と少し値が違う場合もある.
たとえば,25%tileは 21.0 と計算されており,以下のように確認できる.
table(titanic$age < 21.0) / length(na.omit(titanic$age))
##
## FALSE TRUE
## 0.7619503 0.2380497
table(titanic$age <= 21.0) / length(na.omit(titanic$age))
##
## FALSE TRUE
## 0.7227533 0.2772467
probs
引数で percentile を指定できる.
seq(0.1, 0.9, by = 0.1) # 0.1, 0.2, ..., 0.9
## [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
quantile(titanic$age, probs = seq(0.1, 0.9, by = 0.1), na.rm = TRUE) # deciles 十分位数
## 10% 20% 30% 40% 50% 60% 70% 80% 90%
## 14 19 22 25 28 31 36 42 50
quantile(titanic$age, probs = 0.35, na.rm = TRUE) # 35th percentile
## 35%
## 24
median(titanic$age, na.rm = TRUE) # median 中央値
## [1] 28
max(titanic$age, na.rm = TRUE)
## [1] 80
min(titanic$age, na.rm = TRUE)
## [1] 0.17
max(titanic$age, na.rm = TRUE) - min(titanic$age, na.rm = TRUE) # range
## [1] 79.83
母分散,母標準偏差 (\(\mu\) は母平均)
\[ \sigma^2 = \frac{1}{N} \sum_i (x_i - \mu)^2, \quad \sigma = \sqrt{\sigma^2} \]
標本分散,標本標準偏差
\[ s^2 = \frac{1}{n-1} \sum_i (x_i - \bar{x})^2, \quad s = \sqrt{s^2} \]
x <- c(1, 2, 6)
x - 3
## [1] -2 -1 3
x - mean(x) # deviation from the mean
## [1] -2 -1 3
(x - mean(x))^2
## [1] 4 1 9
mean((x - mean(x))^2) # definition of population variance
## [1] 4.666667
sum((x - mean(x))^2) / 3 # same as above
## [1] 4.666667
sum((x - mean(x))^2) / (3-1) # definition of sample variance
## [1] 7
var(x) # defined as sample variance
## [1] 7
sqrt(var(x)) # standard deviation
## [1] 2.645751
sd(x)
## [1] 2.645751
欠損値 NA
があると計算結果も NA
になる.
その場合は NA
を除外して平均を計算するために
na.rm = TRUE
引数を追加する.
var(titanic$age)
## [1] NA
var(titanic$age, na.rm = TRUE)
## [1] 207.7488
sd(titanic$age, na.rm = TRUE)
## [1] 14.41349
なぜ標本分散の分母は \(n-1\) なのか?
平均0,分散1の乱数を生成する rnorm
関数を使ってシミュレーションを行って確認してみる.
var(rnorm(n = 5, mean = 0, sd = 1))
## [1] 0.7700556
シミュレーション
rnorm(n = サンプルサイズ, mean = 平均, sd = 標準偏差)
関数で正規分布と呼ばれる確率分布に従う乱数を生成
sd = 1
と設定し,分散の平均値が 1
に近いかどうかを確認するset.seed
関数を使って乱数を固定するfor
文を利用して「乱数の生成,分散を計算,記録」を1000回繰り返すrnorm_pop_var, rnorm_sample_var
それぞれのベクトルに記録rnorm_pop_var <- rnorm_sample_var <- NULL
for (i in 1:1000) {
# Step 1. 乱数の生成
set.seed(i) # 再現性のため
rnorm_i <- rnorm(n = 5, mean = 0, sd = 1)
# Step 2. 分散を計算
pop_var_i <- sum((rnorm_i - mean(rnorm_i))^2) / length(rnorm_i)
sample_var_i <- sum((rnorm_i - mean(rnorm_i))^2) / (length(rnorm_i)-1)
# Step 3. 記録
rnorm_pop_var <- c(rnorm_pop_var, pop_var_i)
rnorm_sample_var <- c(rnorm_sample_var, sample_var_i)
}
summary(rnorm_pop_var)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.02162 0.40059 0.71008 0.82542 1.11389 3.88203
summary(rnorm_sample_var)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.02703 0.50074 0.88761 1.03178 1.39237 4.85254
中級者向け:以下のように sapply
関数を使うことで
for
文を使わずに計算できる.
sapply(X = ベクトルやリスト, FUN = 関数)
:X
の各要素に対して関数を適用し,実行結果をベクトルで返すfor
文よりも計算速度が速い可能性が高いsummary(sapply(X = 1:1000, FUN = function (x) {
rnorm_i <- rnorm(n = 5, mean = 0, sd = 1)
sum((rnorm_i - mean(rnorm_i))^2) / length(rnorm_i) # population variance
}))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.02154 0.37973 0.67805 0.78518 1.06479 4.61459
本来の導出は以下の通り.
\(X_1, X_2, \ldots, X_n\) を平均 \(\mu\) 分散 \(\sigma^2\) の同一分布に独立に従う確率変数とする. このとき,標本分散が母分散 \(\sigma^2\) の不偏推定量(不偏性 \(E[\hat{\theta}] = \theta\) を満たすような推定量 \(\hat{\theta}\))となることは以下のように示される.
\[ E \left[ \sum_i (X_i - \bar{X})^2 \right] = E \left[ \sum_i (X_i - \mu)^2 \right] - n E \left[(\bar{X} - \mu)^2 \right] = n \sigma^2 - n \cdot \frac{\sigma^2}{n} = (n-1) \sigma^2 \] \[ \mbox{where} \quad E \left[(\bar{X} - \mu)^2 \right] = V(\bar{X}) = V \left( \frac{1}{n} \sum_i X_i \right) = \frac{1}{n^2} \sum_i V(X_i) = \frac{1}{n^2} \cdot n \sigma^2 = \frac{\sigma^2}{n} \] \[ \therefore E \left[ \frac{1}{n-1} \sum_i (X_i - \bar{X})^2 \right] = \sigma^2 \]
上の式より \(V(\bar{X}) = E \left[(\bar{X} - \mu)^2 \right]\) すなわち標本平均の真の平均からのばらつきがあるために標本分散の分母が \(n\) ではなく \(n-1\) になることが分かる.
なお,\(V(\bar{X})\) は \(n \to \infty\) で 0 になることから,サンプルサイズが十分に大きければ標本平均は真の平均になる(より正確に言えば確率収束する.「大数の法則」としても知られる.)ことも復習できる.
boxplot(ベクトル)
で作成.
boxplot(titanic$age)
text(1.35, quantile(titanic$age, .75, na.rm = TRUE) + 1.5 * IQR(titanic$age, na.rm = T), labels = "“max” (= Q3+1.5*IQR)")
text(1.35, quantile(titanic$age, .75, na.rm = TRUE), labels = "75% (Q3)")
text(1.35, quantile(titanic$age, .5, na.rm = TRUE), labels = "50% (median)")
text(1.35, quantile(titanic$age, .25, na.rm = TRUE), labels = "25% (Q1)")
text(1.35, min(titanic$age, na.rm = TRUE), labels = "(actual) min")
注:箱の下の髭は実際の最小値まで伸ばす.実際の最小値 (age = 0.17) が下の計算式で与えられる “min” より大きいため.
quantile(titanic$age, .25, na.rm = T) - 1.5 * IQR(titanic$age, na.rm = T)
## 25%
## -6
男女別に箱ひげ図を描く場合は,boxplot(女性の年齢ベクトル, 男性の年齢ベクトル)
のように指定する.
titanic_age_female <- titanic$age[titanic$sex == "female"] # age of female
titanic_age_male <- titanic$age[titanic$sex == "male"] # age of male
boxplot(titanic_age_female, titanic_age_male, names = c("Female", "Male"), ylab = "Age")
boxplot(連続変数 ~ グループ変数, data = データフレーム名)
でもグループで分けた箱ひげ図を作成できる.
boxplot(age ~ sex, titanic)
plot(1つ目のベクトル, 2つ目のベクトル)
で作成.
plot(x = titanic$age, y = titanic$fare, xlab = "Age", ylab = "Fare", pch = 20)
同じデータだが縦軸(Y軸)のスケールが異なる例.
tempx <- 1:10
set.seed(1)
tempy <- tempx + rnorm(10, sd = 4)
par(mfrow = c(1, 2))
plot(tempx, tempy, xlab = "x", ylab = "y", pch = 20)
plot(tempx, tempy, xlab = "x", ylab = "y", pch = 20, ylim = c(-50, 50))
左の図は正の相関を示しているように見えるが,右の図は弱い正の相関(または無相関)に見えるだろう.
Y軸のみ対数変換する場合は
log = "y"
,X軸とY軸の両方を対数変換する場合は
log = "xy"
を引数に追加する.
plot(x = titanic$age, y = titanic$fare, xlab = "Age", ylab = "Fare", pch = 20, log = "y")
table(titanic$fare <= 0) # omitted from the plot
##
## FALSE TRUE
## 1291 17
col = "red"
のように引数を追加することでマーカーの色を指定できる.
col = rgb(red, green, blue)
のように引数を追加すれば,RGB形式で色を指定できる.
col = rgb(red, green, blue, alpha)
のように引数を追加すれば,RGB形式で色を指定したうえに,透過水準を alpha
値(0以上1以下)として指定できる.
plot(x = titanic$age, y = titanic$fare, xlab = "Age", ylab = "Fare", pch = 20, col = rgb(0, 0, 0, .3))
Without jitter
plot(x = titanic$pclass, y = titanic$parch, xlab = "Ticket class",
ylab = "# of parents and children", pch = 20)
With jitter
plot(x = jitter(titanic$pclass), y = jitter(titanic$parch), xlab = "Ticket class",
ylab = "# of parents and children", pch = 20, cex = .5)
Raw plot
plot(x = titanic$age, y = titanic$survived, xlab = "Age", ylab = "Survived", pch = 20)
Binned plot
titanic_with_age <- titanic[!is.na(titanic$age), ] # remove obs. with no age
titanic_age_6 <- cut(titanic_with_age$age, breaks = 6) # convert age into 6 intervals
levels(titanic_age_6)
## [1] "(0.0902,13.5]" "(13.5,26.8]" "(26.8,40.1]" "(40.1,53.4]"
## [5] "(53.4,66.7]" "(66.7,80.1]"
titanic_mean_age <- c((0.0902+13.5)/2, (13.5+26.8)/2, (26.8+40.1)/2,
(40.1+53.4)/2, (53.4+66.7)/2, (66.7+80.1)/2)
titanic_mean_survived <- c(
mean(titanic_with_age$survived[titanic_age_6 == levels(titanic_age_6)[1]]),
mean(titanic_with_age$survived[titanic_age_6 == levels(titanic_age_6)[2]]),
mean(titanic_with_age$survived[titanic_age_6 == levels(titanic_age_6)[3]]),
mean(titanic_with_age$survived[titanic_age_6 == levels(titanic_age_6)[4]]),
mean(titanic_with_age$survived[titanic_age_6 == levels(titanic_age_6)[5]]),
mean(titanic_with_age$survived[titanic_age_6 == levels(titanic_age_6)[6]]) )
plot(x = titanic_mean_age, y = titanic_mean_survived,
xlab = "Age (binned)", ylab = "Survival rate", pch = 20)
注:Binned plot を計算するための便利なパッケージが幾つかあるため,実際に描画する際にはそれを利用するとよい.
3つ以上の連続変数の散布図の組み合わせを行列形式で表示する. Draftman’s display や Pair plot とも呼ばれる.
pairs(swiss[, c("Fertility", "Examination", "Education")])
母共分散
\[ \sigma_{x, y} = \frac{1}{N} \sum_i (x_i - \mu_{x})(y_i - \mu_{y}) \]
標本共分散
\[ Cov(x, y) = \frac{1}{n-1} \sum_i (x_i - \bar{x})(y_i - \bar{y}) \]
x <- c(1, 2, 6)
y <- c(1, 3, 4)
plot(x, y, cex = 2, xlim = c(0, 7), ylim = c(0, 5)) # scatter plot
(x - mean(x)) * (y - mean(y))
## [1] 3.3333333 -0.3333333 4.0000000
平均からの偏差の積は何を意味しているかを考えよう.
下の図で平均値を表す赤線をx軸・y軸とみなそう. このとき,偏差の積は,第1象限・第3象限では正,第2象限(・第4象限)では負の値を取る. よって,片方の変数がその平均値より大きな値を取るとき,もう片方の変数もその平均値より大きな値を取る傾向にあるならば,第1象限と第3象限に多くのデータが集まり,結果として偏差の積は正の値をとるだろう. その逆に右下がりの傾向がある時,偏差の積は負の値を取るだろう.
plot(x, y, cex = 2, xlim = c(0, 7), ylim = c(0, 5))
text(x, y+0.5, labels = round((x - mean(x)) * (y - mean(y)), 2), cex = 1.5)
abline(v = mean(x), h = mean(y), col = "red")
text(3.5, 0.5, expression(bar(x) == 3), col = "red", cex = 1.5)
text(0.5, 2.4, expression(bar(y) == 2.7), col = "red", cex = 1.5)
下図からも分かるように,\((x,y)\) が \(\bar{x}, \bar{y}\) の両方から離れるほど偏差の積の絶対値が大きくなる.
以上のように計算される「偏差の積」の平均値(のようなもの)が共分散である.
# sum((x - mean(x)) * (y - mean(y))) / 3 # definition of population covariance
sum((x - mean(x)) * (y - mean(y))) / (3-1) # definition of sample covariance
## [1] 3.5
cov(x, y) # sample covariance
## [1] 3.5
相関係数は,共分散をそれぞれの変数の標準偏差で割ることでスケーリングしたもの.
\[ Cor(x, y) = \frac{Cov(x, y)}{\sqrt{s^2_x} \cdot \sqrt{s^2_y}} \]
cov(x, y) / (sd(x) * sd(y)) # definition of correlation coef.
## [1] 0.8660254
cor(x, y) # correlation coefficient
## [1] 0.8660254
相関係数の大きさは,データに最もよく当てはまる直線(下図では赤色の実線)に各データがどれだけ近いかによって決まる.
set.seed(0)
x2 <- rnorm(10)
y2a <- x2 + rnorm(10, sd = 1); cor(x2, y2a)
## [1] 0.8447137
y2b <- x2 + rnorm(10, sd = 2); cor(x2, y2b)
## [1] 0.5979751
par(mfrow = c(1, 2))
plot(x2, y2a, ylim = c(-3, 3), main = paste("r =", round(cor(x2, y2a), 2)))
abline(lm(y2a ~ x2), col = "red") # Add fitted (regression) line
plot(x2, y2b, ylim = c(-3, 3), main = paste("r =", round(cor(x2, y2b), 2)))
abline(lm(y2b ~ x2), col = "red")
相関係数の大きさは,直線の傾きの大きさ(どれだけsteepであるか)を表すわけではない.
set.seed(0)
x3 <- rnorm(10)
y3a <- x3 + rnorm(10, sd = 1); cor(x3, y3a)
## [1] 0.8447137
y3b <- y3a / 2; cor(x3, y3b)
## [1] 0.8447137
par(mfrow = c(1, 2))
plot(x3, y3a, ylim = c(-2, 2), main = paste("r =", round(cor(x3, y3a), 2)))
abline(lm(y3a ~ x3), col = "red")
plot(x3, y3b, ylim = c(-2, 2), main = paste("r =", round(cor(x3, y3b), 2)))
abline(lm(y3b ~ x3), col = "red")
lm(y3a ~ x3)$coef; lm(y3b ~ x3)$coef # slope of fitted line
## (Intercept) x3
## -0.3128390 0.8616914
## (Intercept) x3
## -0.1564195 0.4308457
相関係数が 1 や -1 になるのは,一方の変数がもう一方の変数の定数倍・定数加算によって得られるような場合.
x4a <- x * 2 + 3
cor(x, x4a)
## [1] 1
x4b <- x * (-0.5) + 3
cor(x, x4b)
## [1] -1
par(mfrow = c(1, 2))
plot(x, x4a, cex = 2); abline(lm(x4a ~ x), col = "red")
plot(x, x4b, cex = 2); abline(lm(x4b ~ x), col = "red")
一見して異なるものを表す変数間で相関係数が -1 になる場合がある. これは回帰分析における多重共線性の議論と関わるので留意しよう.
たとえば,「女性の場合に1をとる変数(ダミー変数)」と「男性の場合に1をとる変数」をそれぞれ作成したとき,もしデータセットに含まれる全ての個体が女性/男性のいずれかに割り当てられているなら,この2つの変数の相関係数は定義上 -1 になる.
titanic$female <- 1 * (titanic$sex == "female")
titanic$male <- 1 * (titanic$sex == "male")
head(titanic[, c("sex", "female", "male")])
## sex female male
## 1 female 1 0
## 2 male 0 1
## 3 female 1 0
## 4 male 0 1
## 5 female 1 0
## 6 male 0 1
cor(titanic$female, titanic$male)
## [1] -1
See https://en.wikipedia.org/wiki/Anscombe%27s_quartet
変数の関係が互いに異なるが平均・分散・相関係数が概ね同じ {x, y} という変数の組が4セット含まれる.
str(anscombe) # display structure of object
## 'data.frame': 11 obs. of 8 variables:
## $ x1: num 10 8 13 9 11 14 6 4 12 7 ...
## $ x2: num 10 8 13 9 11 14 6 4 12 7 ...
## $ x3: num 10 8 13 9 11 14 6 4 12 7 ...
## $ x4: num 8 8 8 8 8 8 8 19 8 8 ...
## $ y1: num 8.04 6.95 7.58 8.81 8.33 ...
## $ y2: num 9.14 8.14 8.74 8.77 9.26 8.1 6.13 3.1 9.13 7.26 ...
## $ y3: num 7.46 6.77 12.74 7.11 7.81 ...
## $ y4: num 6.58 5.76 7.71 8.84 8.47 7.04 5.25 12.5 5.56 7.91 ...
summary(anscombe)
## x1 x2 x3 x4 y1
## Min. : 4.0 Min. : 4.0 Min. : 4.0 Min. : 8 Min. : 4.260
## 1st Qu.: 6.5 1st Qu.: 6.5 1st Qu.: 6.5 1st Qu.: 8 1st Qu.: 6.315
## Median : 9.0 Median : 9.0 Median : 9.0 Median : 8 Median : 7.580
## Mean : 9.0 Mean : 9.0 Mean : 9.0 Mean : 9 Mean : 7.501
## 3rd Qu.:11.5 3rd Qu.:11.5 3rd Qu.:11.5 3rd Qu.: 8 3rd Qu.: 8.570
## Max. :14.0 Max. :14.0 Max. :14.0 Max. :19 Max. :10.840
## y2 y3 y4
## Min. :3.100 Min. : 5.39 Min. : 5.250
## 1st Qu.:6.695 1st Qu.: 6.25 1st Qu.: 6.170
## Median :8.140 Median : 7.11 Median : 7.040
## Mean :7.501 Mean : 7.50 Mean : 7.501
## 3rd Qu.:8.950 3rd Qu.: 7.98 3rd Qu.: 8.190
## Max. :9.260 Max. :12.74 Max. :12.500
# Standard deviation of x
c(sd(anscombe$x1), sd(anscombe$x2), sd(anscombe$x3), sd(anscombe$x4))
## [1] 3.316625 3.316625 3.316625 3.316625
# Standard deviation of y
c(sd(anscombe$y1), sd(anscombe$y2), sd(anscombe$y3), sd(anscombe$y4))
## [1] 2.031568 2.031657 2.030424 2.030579
# Correlation of x and y
c(cor(anscombe$x1, anscombe$y1), cor(anscombe$x2, anscombe$y2),
cor(anscombe$x3, anscombe$y3), cor(anscombe$x4, anscombe$y4))
## [1] 0.8164205 0.8162365 0.8162867 0.8165214
par(mfrow = c(2, 2))
plot(anscombe$x1, anscombe$y1)
plot(anscombe$x2, anscombe$y2)
plot(anscombe$x3, anscombe$y3)
plot(anscombe$x4, anscombe$y4)
この例は,生のデータを描画することの重要性を我々に教えてくれる.
See also: Same Stats, Different Graphs https://www.research.autodesk.com/publications/same-stats-different-graphs/
少なくとも一方の変数に欠損値 NA
がある場合は,欠損値がない観測値のみを使って相関係数を計算するために
use = "complete.obs"
引数を追加する.
cor(titanic$age, titanic$fare, use = "complete.obs")
## [1] 0.1787399
複数の変数に対して相関係数行列を計算することもできる.
cor(titanic[, c("age", "fare", "parch")], use = "complete.obs")
## age fare parch
## age 1.0000000 0.1787399 -0.1502409
## fare 0.1787399 1.0000000 0.2167232
## parch -0.1502409 0.2167232 1.0000000
客室等級ごとに年齢と運賃の相関係数を計算すると次のようになる. これは上で計算したサンプル全体に対して計算した相関係数と異なる.
c(cor(titanic$age[titanic$pclass == 1], titanic$fare[titanic$pclass == 1], use = "complete.obs"),
cor(titanic$age[titanic$pclass == 2], titanic$fare[titanic$pclass == 2], use = "complete.obs"),
cor(titanic$age[titanic$pclass == 3], titanic$fare[titanic$pclass == 3], use = "complete.obs"))
## [1] -0.1078528 -0.1855229 -0.2381369
各客室等級の年齢と運賃の平均値を計算すると次のようになる.
c(mean(titanic$age[titanic$pclass == 1], na.rm = TRUE),
mean(titanic$age[titanic$pclass == 2], na.rm = TRUE),
mean(titanic$age[titanic$pclass == 3], na.rm = TRUE))
## [1] 39.15993 29.50670 24.81637
c(mean(titanic$fare[titanic$pclass == 1], na.rm = TRUE),
mean(titanic$fare[titanic$pclass == 2], na.rm = TRUE),
mean(titanic$fare[titanic$pclass == 3], na.rm = TRUE))
## [1] 87.50899 21.17920 13.30289
直感的に説明すれば,客室等級ごとに計算した相関は客室等級「内」の相関を捉えるのに対して,サンプル全体の相関は客室等級「間」の相関も捉えるためである.
このように集団を分割したときに集団全体とは異なる傾向が観察される現象は「シンプソンのパラドックス」として知られる. 下の図を参照.
set.seed(0)
x1 <- rnorm(10, mean = 5); y1 <- - x1 + rnorm(10)
x2 <- rnorm(10, mean = 10); y2 <- - x2 + rnorm(10) + 10
x3 <- rnorm(10, mean = 15); y3 <- - x3 + rnorm(10) + 20
c(cor(x1, y1), cor(x2, y2), cor(x3, y3)) # by group
## [1] -0.9016505 -0.7137826 -0.7712845
x123 <- c(x1, x2, x3); y123 <- c(y1, y2, y3)
cor(x123, y123) # whole sample
## [1] 0.8573335
plot(x123, y123, col = rep(c("darkgreen", "blue", "darkorange"), each = 10),
pch = rep(c(15, 17, 19), each = 10))
abline(lm(y123 ~ x123), col = "red")
補足:このパラドックスは回帰分析においては交絡の問題として捉えることができる.
table(ベクトル)
hist(ベクトル)
mean(ベクトル)
plot(x = X軸のベクトル, y = Y軸のベクトル)
cor(1つ目のベクトル, 2つ目のベクトル)
.