とりあえずの統計学〜相関係数〜

**相関係数**というものを聞いたのでそれをまとめてみようかなと
（そして、相関係数を計算するクラスを`Swift`で作ってしまおうとw

自分なりの解釈なので間違ってましたらご指摘いただけるとありがたいです。

# 相関係数とは
事柄Aと事柄Bの関係（相関）の強さを表した数値です

- A型の人は、几帳面が多い
- 商品Aを買った人は、商品Bも買う人が多い
- 英語のテストの点数が高い人は、国語のテストの点数も高い人が多い

などの関係を数値化したものです

# 相関係数の計算
いきなり求めるのは大変なので、相関係数の計算に必要なものから求めていきます

クラスを作っておきます

```swift
class CorrelationCoefficient {
}
```

## 例題
わかりやすくするため、ある学校のテスト（英語と国語）の点数から相関係数を求める。という問題をやっていきましょう。
以下の表がある学校の英語と国語のテストの点数を表しています。

||英語|国語|
|:--|:--|:--|
|Aくん|40|38|
|Bさん|50|65|
|Cさん|44|40|
|Dくん|74|87|
|Eさん|92|90|

英語も国語もやること（計算方法）は同じなので、英語の場合のみ求めていきます

### Swift
計算しやすいように配列に入れておきます

```swift
let English: [Double] = [40, 50, 44, 74, 92]
let Japanese: [Double] = [38, 65, 40, 87, 90]
```

## 平均
まずはテストの平均を求めてみます
テストの点数の合計を人数で割れば良いですね

```
(40 + 50 + 44 + 74 + 92) ÷ 5 = 60
```

### Swift
計算しやすいように配列にしておいたので、`reduce`を使っていきましょう

```swift
func average(_ array:[Double]) -> Double {
	return array.reduce(0, +) / Double(array.count)
}
```

## 偏差
偏差という言葉はあまり聞きなれないかとおもいます
平均から各値がどのくらい離れているかのことです
計算は簡単で、各値と平均の差を求めるだけです


```
40 - 60 = -20
50 - 60 = -10
44 - 60 = -16
74 - 60 = 14
92 - 60 = 32
```

### Swift
今回も配列なのを利用し、`map`メソッドで偏差の配列を返すようにします

```swift
func deviation(_ array:[Double]) -> [Double] {
	let average = self.average(array)
	return array.map({ (value) -> Double in
		value - average
	})
}
```

## 分散
分散はなんとなくわかるかと思いますが、データのばらつきを表します
先ほど求めた偏差の平均を取るのですが、平均は必ず`0`になってしまいますw
そこで、偏差の2乗の平均を求めます（平均ではなく合計を`個数 - 1`で割ることもあるそうです）

```
( (-20)^2 + (-10)^2 + (-16)^2 + 14^2 + 32^2 ) ÷ 5 = 395.2
```

### Swift

先ほどの偏差の返り値が配列なのを利用し、`reduce`で足していきます

```swift
func dispersion(_ array:[Double]) -> Double {
	let deviations = deviation(array)
	return deviations.reduce(0, { (result, value) -> Double in
		result + (value * value)
	}) / Double(deviations.count)
}
```

## 標準偏差
また聞きなれない言葉が出てきましたねw
分散は各値のばらつきを表していましたね。しかし、都合上各偏差を2乗していました。
そこで、元のデータを単位（次元）を合わせた方が感覚的にわかりやすくなるということで標準偏差というのが用いられます
計算は、分散の正の平方根を求めるだけです

```
√395.2 = 19.87
```

**[余談]**ちなみに、国語のテストの点数の標準偏差は`22.17`なので、国語のテストの点数の方がばらつきがあると言えます

### Swift
平方根は、`sqrt()`というメソッドが用意されてるのでそれを使います

```swift
func standardDeviation(_ array:[Double]) -> Double {
	return sqrt(dispersion(array))	
}
```

## 一旦休憩
知らない言葉が出てきて疲れたかと思うので、一旦余談で休憩でもはさみましょうw
みなさんご存知、**偏差値**ですが、ここまで求めた値から出すことができます

頭の良さそうなEさんの英語のテストの偏差値を求めてみましょう

```
// ((Eさんの点数 - 平均) / 標準偏差) × 10 + 50
((92 - 60) / 19.87) × 10 + 50 = 66.10
```

偏差値はご存知の通り、真ん中が50なので頭が良いですね:blush:
一応、簡単に解説すると、

- `+ 50` -> 値の中心を50にします
- `× 10` -> 幅を10までとります

幅を10にするというのは、`偏差値40`で`平均 - 標準偏差`、`偏差値60`で`平均 + 標準偏差`の点数になるように調整してます

### Swift
偏差値を知りたい時用につくりました

```swift
func deviationValue(_ array:[Double],_ value:Double) -> Double {
	return ((value - average(array)) / standardDeviation(array)) * 10 + 50
}
```

## 共分散
またしても聞きなれない言葉がw
各値の分布を数値化してくれてると考えて大丈夫かと思います....
各テストの偏差の積の平均で求められます（平均ではなく合計を`個数 - 1`で割ることもあるそうです）

```
// (英語のテストの偏差) × (国語のテストの偏差)
(40 - 60) × (38 - 64) = 520
(50 - 60) × (65 - 64) = -10
(44 - 60) × (40 - 64) = 384
(74 - 60) × (87 - 64) = 322
(92 - 60) × (90 - 64) = 832

(520 + (-10) + 384 + 322 + 832) ÷ 5 = 409.6
```

### Swift
2つのデータ配列を受け取れるように引数を2つとります
また、2つの配列の要素の個数が違う場合は、`0`を返すようにしてあります

```swift
func covariance(_ array1:[Double],_ array2:[Double]) -> Double {
	let deviation1 = deviation(array1)
	let deviation2 = deviation(array2)
	if deviation1.count != deviation2.count {
		return 0
	} 
	return deviation1.enumerated().reduce(0) { (result, value) -> Double in
		result + value.element * deviation2[value.offset]
	} / Double(deviation1.count)
}
```

## 相関係数
やっと**相関係数**を求めます
おまたせしました
**共分散**と**各標準偏差**を使用します

```
// 英語のテストの標準偏差：19.87
// 国語のテストの標準偏差：22.17
// 共分散：409.6
// 共分散 ÷ (英語のテストの標準偏差 × 国語のテストの標準偏差)
409.6 ÷ (19.87 × 22.17) = 0.92
```

**相関関数は、-1以上1以下になります**

### Swift
今まで作ったメソッドを使えば簡単ですねw

```swift
func correlationCoefficient(_ array1:[Double],_ array2:[Double]) -> Double {
	return covariance(array1, array2) / (standardDeviation(array1) * standardDeviation(array2))
}
```

# 相関係数の意味
相関係数を求めることまではできましたね
しかし、ただ相関係数が0.92だよと言われてもぽかんですよねw
そこで相関係数の持つ意味を解説していきたいと思います（簡単にですが）

相関係数を`r`として、下の表に表します

|相関係数の値|2つの事柄の関係|
|:--|:--|
|r = 1|完全な正の関係がある|
|0.7 <= r < 1|強い正の関係がある|
|0.4 <= r < 0.7|やや強い正の関係がある|
|0.2 <= r < 0.4|やや正の関係がある|

|相関係数の値|2つの事柄の関係|
|:--|:--|
|-0.2 < r < 0.2|ほとんど関係がない|
|r = 0|完全に関係ない|

|相関係数の値|2つの事柄の関係|
|:--|:--|
|-0.4 < r <= -0.2|やや負の関係がある|
|-0.7 < r <= 0.4|やや強い負の関係がある|
|-1 < r <= 0.7|強い負の関係がある|
|r = -1|完全な負の関係がある|

今回の例題でいうと、

- 正の関係というのは、英語の点数が高い人は国語の点数も高い人が多い
- 負の関係というのは、英語の点数が高い人は国語の点数は低い人が多い

という関係になります。
`r=1`で完全な正の関係があるという場合は、英語の点数が高い人は確実に国語の点数も高いとなります

今回は、正の関係になるように例題を作ったのですが、`0.92`と予想以上に相関係数が高くなってしまいましたねw

# Swift
最終的な相関係数求めるクラス

```swift
import Foundation

let English: [Double] = [40, 50, 44, 74, 92]
let Japanese: [Double] = [38, 65, 40, 87, 90]

class CorrelationCoefficient {
	
	func average(_ array:[Double]) -> Double {
		return array.reduce(0, +) / Double(array.count)
	}
	
	func deviation(_ array:[Double]) -> [Double] {
		let average = self.average(array)
		return array.map({ (value) -> Double in
			value - average
		})
	}
	
	func dispersion(_ array:[Double]) -> Double {
		let deviations = deviation(array)
		return deviations.reduce(0, { (result, value) -> Double in
			result + (value * value)
		}) / Double(deviations.count)
	}
	
	func standardDeviation(_ array:[Double]) -> Double {
		return sqrt(dispersion(array))
	}
	
	func deviationValue(_ array:[Double], value:Double) -> Double {
		return ((value - average(array)) / standardDeviation(array)) * 10 + 50
	}
	
	func deviationValue(_ array:[Double],_ value:Double) -> Double {
		return ((value - average(array)) / standardDeviation(array)) * 10 + 50
	}

	func covariance(_ array1:[Double],_ array2:[Double]) -> Double {
		let deviation1 = deviation(array1)
		let deviation2 = deviation(array2)
		return deviation1.enumerated().reduce(0) { (result, value) -> Double in
			result + value.element * deviation2[value.offset]
		} / Double(deviation1.count)
	}
	
	func correlationCoefficient(_ array1:[Double],_ array2:[Double]) -> Double {
		return covariance(array1, array2) / (standardDeviation(array1) * standardDeviation(array2))
	}
}

// Usage
let correlationCoefficient = CorrelationCoefficient()
correlationCoefficient.correlationCoefficient(English, Japanese) // 0.92
```

# 参考
- [５分で分かる！相関係数の求め方](https://blog.apar.jp/data-analysis/2822/)
- [マンガでわかる統計学入門-滝川好夫](https://www.amazon.co.jp/マンガでわかる統計学入門-滝川好夫/dp/4405102511/ref=pd_lpo_sbs_14_t_2?_encoding=UTF8&psc=1&refRID=KKVGNAEX7R7G31Z9ABF2)