# メモ

> Doing Math with Python: Use Programming to Explore Algebra, Statistics, Calculus, and More!
> Amit Saha

を Colab でなぞりながら読む。

本のまえがきに高校数学でプログラミングを学ぶ、と書いてあるので、あちら(アメリカ?)の高校数学の概要がわかり、復習になるかもしれない。

元の本の章立て

1. 数を扱う
1. データをグラフ化する
1. データを統計的に表現する
1. Sympy を使った代数と数式処理
1. 集合と確率で遊ぶ
1. 幾何図形とフラクタルの描画
1. 微積分を解く

この内、1章から5章までを https://colab.research.google.com/github/kalz2q/mycolabnotebooks/blob/master/doingmath01.ipynb、
残りを https://colab.research.google.com/github/kalz2q/mycolabnotebooks/blob/master/doingmath02.ipynb
でなぞっている。

元の本のプログラムは多くの場合、main を持ったプログラムの形にしてあるのに対し、この Colab での学習は コードセルで走るように書き直した。

とりあえず動くようにはしてあるつもりだが、改善の余地はたくさんあると思う。

ご意見をお寄せください。

# 数値の操作

四則演算はべき乗以外は普通なので実験するだけでいいだろう。

```
# 実験 数値計算
print (1 + 2)
print (3.5)
print ( -1 + 2.5)
print (100 - 45)
print (3 * 2)
print (3.5 * 1.5)
```

    3
    3.5
    1.5
    55
    6
    5.25

```
print (3 / 2)
print (4 / 2)
```

    1.5
    2.0

以上、加算、減算、乗算、除算を見た。

除算で引数が整数同士でも返される値は浮動小数点数になる。

整数除算を行いたい場合は、`//` を用いる。

```
print (3 // 2)
print (-3 // 2)
print (round (3 / 2))
print (round (-3 / 2))
print (int(3 / 2))
print (int(-3 / 2))
```

    1
    -2
    2
    -2
    1
    -1

`//` は床除算 `floor division` と呼ばれ、その数以下の整数を結果として返す。

余り計算は `%` `modulo` 演算子を用いる。

```
print (9 % 2)
```

    1

冪乗は `**` `exponential` 演算子を用いる。

```
print (2 ** 2)
print (2 ** 10)
print (1 ** 10)
```

    4
    1024
    1

冪乗の値 `exponential symbol` に `1` 以下の値が使える。平方根を求めたいときにには `1/2`、立方根の場合は `1/3`である。

```
print (8 ** (1 / 3))
```

    2.0

演算子の優先順序は `PEMDAS` に従う。

* 括弧 parntheses
* 指数 exponents
* 乗算 multiplication
* 除算 division
* 加算 addition
* 減算 subtraction

`PEMDAS`を覚える語呂合わせが欲しいが、どうでもいいか。 => Please Excuse My Dear Aunt Sally だって。

```
print (5 + 5 * 5)
print ((5 + 5) * 5)
```

    30
    50

# 変数

数字につけるラベルのことを数学やプログラミングでは変数、と呼ぶ。

中学とかだと $a$ が定数、$x$ が変数みたいな習い方するけど、それって無理あるよね。ラベルかぁ、ラベルというより箱がいいと思うのだが。"なにか"って言い方もあったかと思う。ある意味抽象化なのだから、そそ、"方程式"という言葉と一緒に習ったような気もする。なにかイコールなにか。なにか掛けるなにかイコールなにか。そのなにかに名前、ラベルをつけたところから数学が始まった。とかね。

```
a = 3
print (a + 1)
a = 5
print (a + 1)
```

    4
    6

# 型 type

整数と浮動小数点数は型がちがう。型を知るには `type()` を使う。

```
print (type (3))
print (type (3.5))
print (type (3.0))
```

    <class 'int'>
    <class 'float'>
    <class 'float'>

```
print (3 == 3.0)
print (type(3) == type (3.0))
```

    True
    False

`3 == 3.0` が `True` になるのは整数を浮動小数点に変換してから比較しているのだろう。

`3 === 3.0' というような厳密な比較をする演算子はないみたい。

```
print (int(3.8))
print (int(3.0))
print (float (3))
print (int (-3.8))
print ( -7 // 2)
```

    3
    3
    3.0
    -3
    -4

上の例でマイナスを `//` で整数割り算をして割り切れないと下側になるので、床除算なのだが、そういうこと。

# 分数 fraction

下の例では `from fractions import Fraction` としているが、一方で Rational というのもあったよね。

質問: 分数と有理数との関係。実数との関係。無理数も、無限に小数点が続く分数もコンピューターだと float なのだろうがそれでは数学ができないので、どうにかしているはず。最低限表示の話だが、numpy では Rational、python では  Fraction か？

とりあえずここは  Fraction で進む。

```
from fractions import Fraction
f = Fraction (3, 4)
f
```

    Fraction(3, 4)

```
print (f)
```

    3/4

`print()` 関数は `Fraction(3, 4)` を印刷するときに、見やすい形に変換している、と思われる。

```
Fraction (3, 4) * 1 + 1.5
```

    2.25

```
Fraction (3, 4) + 1 + Fraction (1, 3)
```

    Fraction(25, 12)

```
Fraction (3, 4) * 1 + 1.5 + Fraction (1, 3)
```

    2.5833333333333335

次の例でもあるように、float と分数をまぜると、float になってしまう。

```
from fractions import Fraction
display(1.5 + Fraction (1, 3))
print(1.5 + Fraction (1, 3))

```

    1.8333333333333333

    1.8333333333333333

```
print (type (Fraction(1,3)))
print (type (1.5 + Fraction (1,3)))
```

    <class 'fractions.Fraction'>
    <class 'float'>

式 expression の中に1つでも浮動小数点があれば結果は浮動小数点。浮動小数点がなければ、分数があれば分数が結果になる。

# 複素数 complex number

Pythonは文字 $j$ で識別される虚数部を持つ複素数をサポートする。
$j$ または $J$ は数学表記の  $i$ に相当する。
複素数 $2 + 3i$ はPythonでは `2 + 3j` として記述される。

```
a = 2 + 3j
print (a)
print (type(a))
```

    (2+3j)
    <class 'complex'>

```
a = complex (2, 3)
a
```

    (2+3j)

```
b = 3 + 3j
print (a + b)
print (a - b)
```

    (5+6j)
    (-1+0j)

```
print (a)
print (b)
print (a * b)
```

    (2+3j)
    (3+3j)
    (-3+15j)

```
z = 2 + 3j
print (z.real)
print (z.imag)
```

    2.0
    3.0

```
2 +3j - 3j
```

    (2+0j)

# 共役 conjugate

複素数の共役 (きょうやく) は、実部は同じで、虚部は符号が反対になる。

`conjugate()` メソッドで得ることができる。

```
z = 2 + 3j
print (z)
print (z.conjugate())
```

    (2+3j)
    (2-3j)

実数部と虚数部はどちらも浮動小数点数。

実数部と虚数部を使用して、次の式で複素数の大きさを計算できる。

```
(z.real ** 2 + z.imag ** 2) ** 0.5
```

    3.605551275463989

`abs()` 関数は実数の場合は絶対値を返すが、複素数の場合は大きさを返す。

上記の式と同じ結果になる。

```
abs(z)
```

    3.605551275463989

標準ライブラリの  cmath モジュールは、複素数を処理するために他の多くの特殊な関数へのアクセスを提供する。 cmath  は  complex math の意味。

# ユーザー入力

```
# a = input()
# print (a)
# print (type(a))
```

    3
    3
    <class 'str'>

Colabでも上記のようにするとユーザー・インプットを得ることができるが、プログラムが止まるのであまり使いみちがないような気がする。

`input()`関数で得られるのは文字列なので、数字の場合は `int()`関数などで変換する必要がある。

```
a = '1'
print (int(a) + 1)
print (float(a) + 1)
```

    2
    2.0

```
# int('2.0') とすると、エラーになるので
int(float('2.0'))
```

    2

'3/4' が入力されると `float()` でも `int()` でもエラーになる。

ユーザー入力をエラーなしにするためには、

`try ... except` ブロックで扱う必要がある。

# 例外処理 exception

基本的な考え方は次のとおり。

`try... except` ブロックで1つ以上の文 statement を実行し、実行中にエラーが発生しても、プログラムはクラッシュせず、代わりに、処理は except ブロックに転送される。ここで、適切な操作を実行できる。

```
# try:
#     a = float(input('Enter a number: '))
# except ValueError:
#     print ('You entered an invalid number')
#
# Enter a number: 3/4
# You entered an invalid number
```

`try ... except` ブロックで例外を扱うには、例外の種類を特定する必要がある。

上記の場合、ValueError を指定した。

```
print (1.0.is_integer())
print (1.1.is_integer())
```

    True
    False

```
from fractions import Fraction
Fraction ('3/4')
```

    Fraction(3, 4)

```
Fraction (3, 4)
```

    Fraction(3, 4)

```
print (Fraction (3, 4))
```

    3/4

```
complex ('2+3j') # '2 + 3j' は `ValueError` スペースがじゃまでエラーになる
```

    (2+3j)

# 因数 Factor

```
def is_factor (a, b):
    if b % a == 0:
        return True
    else:
        return False

print (is_factor(4, 1024))
print (1024 % 4 == 0)
```

    True
    True

### range

```
for i in range (1, 4):
    print (i)
```

    1
    2
    3

```
for i in range (1, 10, 2):
    print (i)
```

    1
    3
    5
    7
    9

```
def factors(b):
    ''' Find the factors of an integer '''
    for i in range (1, b+1):
        if b % i == 0:
            print (i)

factors (25)
```

    1
    5
    25

# フォーマット format

```
### format
item1 = 'apples'
item2 = 'bananas'
item3 = 'grapes'

print('At the grocery store, I bought some {2} and {2} and {1}'.format(item1, item2, item3))
```

    At the grocery store, I bought some grapes and grapes and bananas

```
print('Number 1: {0} Number 2: {1} '.format(1, 3.578))
```

    Number 1: 1 Number 2: 3.578

# 掛け算表 Multiplication table

```
# multiplication table printer
def multi_table(a):
    for i in range(1, 11):
        print('{0} x {1} = {2}'.format(a, i, a*i))

a = 5
multi_table(float(a))
```

    5.0 x 1 = 5.0
    5.0 x 2 = 10.0
    5.0 x 3 = 15.0
    5.0 x 4 = 20.0
    5.0 x 5 = 25.0
    5.0 x 6 = 30.0
    5.0 x 7 = 35.0
    5.0 x 8 = 40.0
    5.0 x 9 = 45.0
    5.0 x 10 = 50.0

```
print ('{0:.2f}'.format(1.25456))
print ('{0:.2f}'.format(1.2555))
print ('{0:.2f}'.format(1))
```

    1.25
    1.26
    1.00

# 測定単位変換 converting units of measurement

長さ、時間、質量、温度の国際的な測定単位は、メートル、秒、キログラム、およびケルビンと定められている。

しかし!!!!

例えば温度は 303.15 ケルビンと言わず、華氏 86 度とか、摂氏 30 度とか言う。比較のためには測定単位を同じにする変換を行わなければならない。

まず、長さのインチとマイルの変換のプログラムを作ろう。

1 インチは 2.54 センチメートル。100 で割ればメートルになる。

例えば 25.5 インチは

(25.5 * 2.54) / 100

```
(25.5 * 2.54) / 100
```

    0.6476999999999999

で、0.6476999999999999 メートルである。

1 マイルは 1.609 キロメートルなので、目的地が 650 マイル先ならば

650 * 1.609

```
650 * 1.609
```

    1045.85

で 1045.85 キロメートルであることがわかる。

さて、温度は、次の式で表される。

$$
C = (F - 32) \times \frac{5}{9}
$$

```latex
%%latex
\displaystyle

C = (F - 32) \times \frac{5}{9}
```

\displaystyle

C = (F - 32) \times \frac{5}{9}

ここで `F` は華氏、`C` は摂氏である。

華氏で98.6度はヒトの平均体温と言われるがこれを摂氏では何度か。

```
F = 98.6

(F - 32) * 5 / 9
```

    37.0

まず、変数 `F` を作り98.6度を代入する。

次に摂氏に変換する数式を評価する。

逆もやってみよう。摂氏から華氏への変換である。

```
C = 37
C * (9 / 5) + 32
```

    98.60000000000001

単位変換プログラムをつくる。

```
def km_miles(km):
    miles = km / 1.609
    return miles

def miles_km(miles):
    km = miles * 1.609
    return km

miles = 650
print (miles_km(miles))

km = 1000
print (km_miles(km))
```

    1045.85
    621.5040397762585

# 二次方程式の根をみつける quadratic equation

二次方程式は一般に次の形で表される。

```latex
%%latex

a x^2 + bx + c = 0
```

a x^2 + bx + c = 0

二次方程式の根の公式は次のようなものである。

```latex
%%latex
\displaystyle

x = \frac {- b \pm \sqrt{b^2 - 4ac}} {2a}
```

\displaystyle

x_1 = \frac {- b \pm \sqrt{b^2 - 4ac}} {2a}

二次方程式は一般に2個の根を持つ。どちらの解も元の二次方程式を満足させる。

2つの根が同一の場合もある。

定数部分、`a`、`b`、`c`を引数として解を計算するプログラムを作る。

```
def roots(a, b, c):
    '''Quadratic equation root calculator
    '''
    D = (b*b - 4*a*c)**0.5
    x_1 = (-b + D) / (2 * a)
    x_2 = (-b - D) / (2 * a)

    return (x_1, x_2)

a, b, c = 1, 2, 1

solvedroot = roots(a, b, c)

print ('x1: {}'.format(solvedroot[0]))
print ('x2: {}'.format(solvedroot[1]))

```

    x1: -1.0
    x2: -1.0

複素数 `complex number` が根となる場合がある。

$$
x^2 + x + 1 = 0
$$

の場合でやってみる。

```
a, b, c = 1, 1, 1

solvedroot = roots(a, b, c)

print ('x1: {}'.format(solvedroot[0]))
print ('x2: {}'.format(solvedroot[1]))
```

    x1: (-0.49999999999999994+0.8660254037844386j)
    x2: (-0.5-0.8660254037844386j)

### 問題 1. even_odd

与えられた数が偶数か奇数かと、それぞれの場合について、続く9つの偶数または奇数の数列を返す。

input: 2
output: even 2 4 6 8 10 12 14 16 18 20

input: 1
output: odd 1 3 5 7 9 11 13 15 17 19

浮動小数点数の場合、is_integer() メソッドでエラーメッセージを出すこと。

```
def even_odd_vending (num):
    if (num % 2) == 0:
        return ['even'] + [(x+num) for x in range(0,20,2)]
    else :
        return ['odd']  + [(x+num) for x in range(0,20,2)]

def even_odd(num):
    try:
        if float(num).is_integer():
            return (even_odd_vending(int(num)))
        else:
            return "eerrroor"
    except ValueError:
        return ('num is invalid')

print(even_odd_vending(2))
print(even_odd_vending(1))

print (even_odd(1))
print (even_odd(2))
print (even_odd(2.5))
print (even_odd(2.0))
print (even_odd("two"))

```

    ['even', 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
    ['odd', 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
    ['odd', 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
    ['even', 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
    eerrroor
    ['even', 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
    num is invalid

### 問題 2. 掛け算表の拡張

掛け算表を拡張して、2つの引数をとり、最初の数 * 0,1, ..., 次の引数までの表とする。

```
# enhanced multiplication table printer
def multi_table(a, b):
    for i in range(1, b+1):
        print('{0} x {1} = {2}'.format(a, i, a*i))

a = 5
b = 15
multi_table(a, b)
```

    5 x 1 = 5
    5 x 2 = 10
    5 x 3 = 15
    5 x 4 = 20
    5 x 5 = 25
    5 x 6 = 30
    5 x 7 = 35
    5 x 8 = 40
    5 x 9 = 45
    5 x 10 = 50
    5 x 11 = 55
    5 x 12 = 60
    5 x 13 = 65
    5 x 14 = 70
    5 x 15 = 75

### 問題 3. キログラムとポンドの重量単位変換プログラム

1 ポンドは 0.453592キログラム

```
def pound_kg(pound) :
    return pound * 0.453592

def kg_pound(kg):
    return kg / 0.453592

print (pound_kg(1))
print (f"{kg_pound(1):.7}")
```

    0.453592
    2.204624

### 問題 4. 分数計算機

```
from fractions import Fraction
Fraction (3, 4) + Fraction(2, 3)
```

    Fraction(17, 12)

```
print (Fraction(8,2))
print (Fraction (3, 4) + Fraction(2, 3))
print (Fraction (3, 4) - Fraction(2, 3))
print (Fraction (3, 4) * Fraction(2, 3))
print (Fraction (3, 4) / Fraction(2, 3))
```

    4
    17/12
    1/12
    1/2
    9/8

# グラフでのデータの視覚化

* 数直線とデカルト平面
* プロットライブラリmatplotlib
* グラフ
* ニュートンの重力法則と発射体軌跡

を学ぶ。

### 数直線

数直線をmatplotlibで描きたい。

```
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(12,2))
ax = fig.add_subplot(xlim=(-4,4), ylim=(0, 1.0))

# blue arrow
ax.arrow(-3.5, 0.5, 7, 0.0, head_width=0.1, head_length=0.15, linewidth=4, color='b', length_includes_head=True)
ax.arrow(3.5, 0.5, -7, 0, head_width=0.1, head_length=0.15, linewidth=4, color='b', length_includes_head=True)

x = [-3, -2, -1, 0, 1, 2, 3]
y = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
data_name = ["-3", "-2", "-1", "0", "1", "2", "3"]
ax.plot(x, y, 'r|', ms="40")

xy = zip (x, y)
xy_name = zip (xy, data_name)
for (i, name) in zip (xy, data_name) :
    ax.annotate(name,i, xycoords='data', xytext=(-7,-40), textcoords='offset points', fontsize=20)
# for (i, j, name) in zip (x, y, data_name) :
#     plt.text(i, j, name, fontsize=15, position=(i-0.05, j-0.2))

ax.set_axis_off()
plt.show()
```

# デカルト平面を理解する

数直線は直感的にいくつかの性質を表している。たとえば、ゼロの右側はすべて正で、左側は負であること。数字 $a$ が数字 $b$ の右側にあればかならず $a$ が $b$ より大きく、$b$ は $a$ より小さい。両端の矢印は数直線が永遠に続き、線上のすべての点はどこまで行っても実数を表している。数字は1つで線上の1点に対応する。

次の図では数直線がそれぞれの 0点で交差している。これをデカルト平面もしくはx-y平面と呼び、水平の数直線をx軸、垂直の数直線をy軸と呼ぶ。

デカルト平面では1つの数値ではなく、2つの数値で点を表す。
図の点Aを2つの数値x、yで表し、（x、y）と書き、点の座標 `coordinates`と呼ぶ。

```
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(6,6))
ax = fig.add_subplot(xlim=(-4,4), ylim=(-4, 4))

# arrows
ax.arrow(-3.5, 0.0, 7, 0.0, head_width=0.1, head_length=0.15, linewidth=4, color='b', length_includes_head=True)
ax.arrow(3.5, 0.0, -7, 0, head_width=0.1, head_length=0.15, linewidth=4, color='b', length_includes_head=True)
ax.arrow(0.0, -3.5, 0.0, 7.0, head_width=0.1, head_length=0.15, linewidth=4, color='b', length_includes_head=True)
ax.arrow(0.0, 3.5, 0.0, -7.0, head_width=0.1, head_length=0.15, linewidth=4, color='b', length_includes_head=True)

x1 = [-3, -2, -1, 1, 2, 3]
y1 = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
data_name = ["-3", "-2", "-1", "1", "2", "3"]
ax.plot(x1, y1, 'r|', ms="20")

x2 = [0,0,0,0,0,0]
y2 = [-3,-2,-1,1,2,3]
ax.plot(x2, y2, 'r_', ms="20")
ax.plot(2,2,"ro")
ax.plot(0,0,"ro")

for (i, j, name) in zip (x1, y1, data_name) :
    ax.text(i, j, name, fontsize=15, position=(i-0.1, j-0.6))
for (i, j, name) in zip (x2, y2, data_name) :
    ax.text(i, j, name, fontsize=15, position=(i-0.5, j - 0.1))
ax.annotate("Origin",xy=(-0.2,0.2), xytext=(-2,2), ha='center', fontsize=15, arrowprops={'arrowstyle':'->'})
ax.annotate("",xy=(2,0), xytext=(2,2), arrowprops={'arrowstyle':'<->', 'ls':'dashed'})
ax.annotate("",xy=(0,2), xytext=(2,2), arrowprops={'arrowstyle':'<->', 'ls':'dashed'})
ax.text(3.8,-0.2,"$x$",fontsize=15)
ax.text(0.3,3.5,"$y$",fontsize=15)
ax.text(2.2,2.0,"$A (x, y)$", fontsize=15)
ax.set_axis_off()
plt.show()

```

### リストとタプル

Pythonでリストとタプルはリストがイミュータブルでなく、変えられるのに対し、タプルはイミュータブルで変えられない、という違いがある。

このテキストではx座標、y座標を表すのにリストを使う。タプルはグラフの`range`をカスタマイズする際に登場する。

リストは鈎括弧`brackets`で作ることができる。要素はカンマで区切る。

要素はインデクスでアクセスする。インデクスは0ベースである。

```
simplelist = [1, 2, 3]
print (simplelist)
print (simplelist[0])
print (simplelist[1])
print (simplelist[2])
```

    [1, 2, 3]
    1
    2
    3

```
stringlist = ['a string','b string','c string']
emptylist = []
print (stringlist[1])
print (emptylist)
```

    b string
    []

```
emptylist = []
emptylist.append(1) # in-place
emptylist.append("two")
emptylist = emptylist + [3, 4]
print (emptylist)
```

    [1, 'two', 3, 4]

タプルはカッコ `()` を使って作る。

```
simpletuple = (1,2,3)
print(simpletuple[0])
print(simpletuple[1])
print(simpletuple[2])
```

    1
    2
    3

```
emptylist = []
simpletuple = (1,2,3)
print(simpletuple[-1]) # => 3
# print(empltylist[-1]) => error!!!!
# print (type(emptylist[-1])) => this is error too
print (bool(emptylist)) # => false

```

    3
    False

# 数え上げる iterating

```
l = [1,2,3]
for item in l :
    print(item)
```

    1
    2
    3

```
l = ["one", "two", "three"]
for index, item in enumerate(l) :
    print(index, item)
```

    0 one
    1 two
    2 three

```
import matplotlib.pyplot as plt
import numpy as np

x_numbers = [1,2,3]
y_numbers = [2,4,6]
fig = plt.figure()
ax = fig.add_subplot()

ax.plot(x_numbers, y_numbers, 'bo-')

plt.show()
```

```
import matplotlib.pyplot as plt
import numpy as np

nyc_temp = [53.9, 56.3, 56.4, 53.4, 54.5, 55.8, 56.8, 55.0, 55.3, 54.0, 56.7, 56.4, 57.3]
years = range(2000, 2013)

fig = plt.figure()
ax = fig.add_subplot()

ax.plot(years, nyc_temp, marker='o')

plt.show()
```

```
import matplotlib.pyplot as plt
import numpy as np

nyc_temp_2000 = [31.3, 37.3, 47.2, 51.0, 63.5, 71.3, 72.3, 72.7, 66.0, 57.0, 45.3, 31.1]
nyc_temp_2006 = [40.9, 35.7, 43.1, 55.7, 63.1, 71.0, 77.9, 75.8, 66.6, 56.2, 51.9, 43.6]
nyc_temp_2012 = [37.3, 40.9, 50.9, 54.8, 65.1, 71.0, 78.8, 76.7, 68.8, 58.0, 43.9, 41.5]

fig = plt.figure()
ax = fig.add_subplot()

months = range (1,13)
ax.plot(months, nyc_temp_2000, months, nyc_temp_2006, months, nyc_temp_2012)

plt.show()
```

上の例ではひとつの `ax.plot()` で全部書いているが、3回書いても同じ。

```
import matplotlib.pyplot as plt
import numpy as np

nyc_temp_2000 = [31.3, 37.3, 47.2, 51.0, 63.5, 71.3, 72.3, 72.7, 66.0, 57.0, 45.3, 31.1]
nyc_temp_2006 = [40.9, 35.7, 43.1, 55.7, 63.1, 71.0, 77.9, 75.8, 66.6, 56.2, 51.9, 43.6]
nyc_temp_2012 = [37.3, 40.9, 50.9, 54.8, 65.1, 71.0, 78.8, 76.7, 68.8, 58.0, 43.9, 41.5]

fig = plt.figure()
ax = fig.add_subplot()
# ax.axis(ymin=0,ymax=80)
ax.axis([0,13,0,100])

months = range (1,13)
ax.plot(months, nyc_temp_2000)
ax.plot(months, nyc_temp_2006)
ax.plot(months, nyc_temp_2012)
plt.title('Average monthly temperature in NYC')
plt.xlabel('Month')
plt.ylabel('Temperature')
plt.legend([2000,2006,2012])
plt.savefig('mygraph.svg')
plt.show()
```

`plt.savefig('mygraph.svg')` とすると、svg に書き出せる。

書き出したファイルはダウンロードできる。

```
from google.colab import files
files.download('mygraph.svg')
```

    <IPython.core.display.Javascript object>

    <IPython.core.display.Javascript object>

# 数式のグラフ化

## ニュートンの万有引力

```latex
%%latex
\displaystyle

F = \frac{Gm_1m_2}{r^2}
```

\displaystyle

F = \frac{Gm_1m_2}{r^2}

上の例はニュートンの万有引力の法則で、2つの物体の質量を $m_1$、$m_2$ その間の距離を $r$、としたときに働く引力の大きさ $F$ を求めるもので、$G$ は引力定数。

$m_1$ を 0.5kg、$m_2$ を 1.5kg とする。
引力定数は
$6.674 \times 10^{-11} \,\mathrm{N m^2 kg^{-2}} $
である。

距離を100m, 150m, 200m, 300m, ..., 1000m とした時の 19 の点について引力のグラフを描く。

```
# 2つの物体間の距離と引力

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot()

# 2つの物体の重さキログラム
m1 = 0.5
m2 = 1.5

# 距離のリストを作る
r = range(100, 1001, 50)

# 引力を入れる空リストを作る
F = []

# 万有引力定数
G = 6.674*(10**-11)

# 公式に当てはめて、引力を計算する
for dist in r:
    force = G*(m1*m2)/(dist**2)
    F.append(force)

plt.plot(r, F, marker='o')
plt.xlabel('Distance in meters')
plt.ylabel('Gravitational force in newtons')
plt.title('Gravitational force and distance')
plt.show()

```

### 放物線

ボールを投げると、初速度 $u$ と角度 $\theta$ がある。

初速度は、$u_x = u \cos \theta$ と $u_y = u \sin \theta$ に分解される。

速度 $v$ は変化するが、$v_x$は変化せず、$v_y$ は変化する。$v_y$ は次の式で表される。

$$
v_y = u \sin \theta - gt
$$

ここで $g$ は重力加速度である。

水平速度は一定なので、水平距離は $S_x = u (\cos \theta) t$ で表せる。

垂直距離は

$$
S_y = u (\sin \theta) t - \frac{1}{2}gt^2
$$

となる。

ボールが頂点に達した時、$v_y$ は $0$ になっていることからそこ到達するまでの時間が割り出せる。

$$
u \sin \theta - gt_{\mathrm{peak}} = 0  \\
t_{\mathrm{peak}} = \frac{u \sin \theta}{g}
$$

落ちてくるまでの時間はこの倍。
$$
t_{\mathrm{flight}} = 2t_{\mathrm{peak}} = 2 \frac{u \sin \theta}{g}
$$

初速度 $u$ を $5 \mathrm{m/s}$、角度 $\theta$ を $45$度とすると、下記のように計算できる。

$$
t_{\mathrm{flight}} = 2 \frac {5 \sin 45}{9.8}
$$

```
import math
2 * 5 * math.sin(45/180*math.pi) / 9.8
```

    0.7215375318230076

ここでは $t_{\mathrm{flight}}$ を 0.72154 とする。

この時間を0.001秒ごとに x 座標と y 座標を計算して、グラフを描くこととしよう。

```
def frange (start, final, increment):
    """
    float version of interval increment between 2 given numbers
    """
    numbers = []
    while start < final:
        numbers.append(start)
        start = start + increment

    return numbers

```

```
import matplotlib.pyplot as plt
import math
import numpy as np

fig = plt.figure()
ax = fig.add_subplot()

def frange (start, final, increment):
    """
    float version of interval increment between 2 given numbers
    """
    numbers = []
    while start < final:
        numbers.append(start)
        start = start + increment

    return numbers

u = 5.0
theta = 60
theta = math.radians(theta)
g = 9.8

# time of flight
t_flight = 2*u*math.sin(theta)/g

# find the intervals
intervals = frange(0, t_flight, 0.001)

# list of x and y coordinates
x = []
y = []
for t in intervals:
    x.append(u*math.cos(theta)*t)
    y.append(u*math.sin(theta)*t - 0.5*g*t*t)

plt.plot(x, y)
plt.xlabel('x-coordinate')
plt.ylabel('y-coordinate')
plt.title('Projectile motion of a ball')
plt.show()

```

```
# I want to draw 1. 45 degree, 2. 60 degree, 3. 5 velocity, 4. 10 velocity versions

import matplotlib.pyplot as plt
import math
import numpy as np

fig = plt.figure()
ax = fig.add_subplot()

def frange (start, final, increment):
    """
    float version of interval increment between 2 given numbers
    """
    numbers = []
    while start < final:
        numbers.append(start)
        start = start + increment

    return numbers

def draw_trajectory (u, theta) :
    theta = math.radians(theta)
    g = 9.8
    t_flight = 2*u*math.sin(theta)/g
    intervals = frange(0, t_flight, 0.001)

    x = []
    y = []
    for t in intervals:
        x.append(u*math.cos(theta)*t)
        y.append(u*math.sin(theta)*t - 0.5*g*t*t)

    plt.plot (x, y)

draw_trajectory (5, 45)
draw_trajectory (5, 60)
draw_trajectory (10, 45)
draw_trajectory (10, 60)

plt.xlabel('x-coordinate')
plt.ylabel('y-coordinate')
plt.title('Projectile motion of a ball')
plt.legend(["5,45","5,60","10,45","10,60"])
plt.show()

```

よく、45度の角度で投げると一番遠くへ行く、というがほんとうか。

```
# draw at various angles

import matplotlib.pyplot as plt
import math
import numpy as np

fig = plt.figure()
ax = fig.add_subplot()

def frange (start, final, increment):
    """
    float version of interval increment between 2 given numbers
    """
    numbers = []
    while start < final:
        numbers.append(start)
        start = start + increment

    return numbers

def draw_trajectory (u, theta) :
    theta = math.radians(theta)
    g = 9.8
    t_flight = 2*u*math.sin(theta)/g
    intervals = frange(0, t_flight, 0.001)

    x = []
    y = []
    for t in intervals:
        x.append(u*math.cos(theta)*t)
        y.append(u*math.sin(theta)*t - 0.5*g*t*t)

    plt.plot (x, y)

angles = [15,30,45,60,75]

for i in angles:
    draw_trajectory (5, i)

plt.xlabel('x-coordinate')
plt.ylabel('y-coordinate')
plt.title('Projectile motion of a ball')
plt.legend(angles)
plt.show()

```

# 棒グラフ バーチャート

```
import matplotlib.pyplot as plt
import math
import numpy as np

fig = plt.figure()
ax = fig.add_subplot()

def create_bar_chart(data, labels):
    num_bars = len(data)
    positions = range(1, num_bars+1)
    ax.barh(positions, data, align='center')
    plt.yticks(positions, labels)

steps = [6534, 7000, 8900, 10786, 3467, 11045, 5095]

labels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']

create_bar_chart(steps, labels)

# Set the label of each bar
# plt.yticks(positions, labels)
plt.xlabel('Steps')
plt.ylabel('Day')
plt.title('Number of steps walked')
plt.grid()
plt.show()

```

# フィボナッチ数

```
def fibo(n):
    if n == 1 :
        return [1]
    elif n == 2:
        return [1,1]
    else :
        a = 1
        b = 1
        series = [a,b]
        for i in range(n):
            c = a + b
            series.append(c)
            a = b
            b = c
        return series

print (fibo(10))
```

    [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

```
import matplotlib.pyplot as plt
import math
import numpy as np

fig = plt.figure()
ax = fig.add_subplot()

def fibo(n):
    if n == 1 :
        return [1]
    elif n == 2:
        return [1,1]
    else :
        a = 1
        b = 1
        series = [a,b]
        for i in range(n):
            c = a + b
            series.append(c)
            a = b
            b = c
        return series

def plot_ratio(series):
    ratios = []
    for i in range(len(series)-1):
        ratios.append(series[i+1]/series[i])
    ax.plot(ratios)

num = 10
series = fibo (num)
plot_ratio(series)
plt.title('Ratio of Fibonacci & Golden')
plt.ylabel('Ratio')
plt.xlabel('No.')
plt.grid()
plt.show()
```

黄金比 golden ratio

正方形を切り落とすと相似になる長方形の縦横比なので

$$
\begin{eqnarray}
1: a &=& (a - 1) : 1\\
\frac{1}{a} &=& \frac{a-1}{1}\\
a^2 -a -1 &=& 1\\
a &=& \frac{1 + \sqrt {2^2 + 1}}{2}\\
a &=& \frac{1+\sqrt{5}}{2}\\
a &\simeq& (1+2.2362)/2 = 1.6181
\end{eqnarray}
$$

# 統計処理

# 有意差について

この本 doing math with python では、有意差 stastitical significance については語っていないので、別途学ぶ必要がある。

有意差でないからと言って、データの結果が間違っているわけではないが、有意差が出ないような統計は客観性が乏しいのも事実なので、有意は大切。

例えばアビガンはとても効くのに有意差が証明できないので、保険薬としての承認は得られないのは税金を使う以上あたりまえだけれど、医者が実験として使ったり、患者の自費で使ったりして命を助けることは重要なこと。

また、兄弟が生まれた順序と身長の関係が先に生まれた方が高いことは小さいが相関係数がプラス positive correlation coefficient であり、これはたぶん有意差があるので、たとえ身の回りのほとんどの例がそれに当てはまらないとしても正しい結論である。

有意ということは、仮にその結論が間違っているとした場合の起こる確率がデータに戻してみると10%以下 (5%以下) である、ということなので、[1,1,1,1,1,0]というデータで 1 という結論を出したところ、1 でない確率は、1 / 6 => 0.16666 なので、有意な差はない。つまり多くの場合、有意差が出ないのはデータ設計が悪いか、データの数が圧倒的に少ないことによる。

# 平均値 mean

```
# 平均 mean
donations = [100,60,70,900,100,200,500,500,503,600,1000,1200]
print(sum(donations))
mean = sum(donations) / len(donations)
print (mean)
```

    5733
    477.75

```
def calculate_mean(numbers):
    s = sum(numbers)
    N = len(numbers)
    mean = s/N
    return mean

donations = [100,60,70,900,100,200,500,500,503,600,1000,1200]
mean = calculate_mean(donations)
N = len(donations)

print('Mean donation over the last {0} days is {1}'.format(N, mean))
```

    Mean donation over the last 12 days is 477.75

### メディアン 中央値

```
def calculate_median(numbers):
    N = len(numbers)
    numbers.sort()
    if N % 2 == 0:
        m1 = int(N/2 - 1)
        m2 = int(N/2 - 1)
        median = (numbers[m1] + numbers[m2]) / 2
    else:
        m = int((N-1)/2)
        median = numbers[m]
    return median

donations = [100, 60, 70, 900, 100, 200, 500, 500, 503, 600, 1000, 1200]

median = calculate_median(donations)
N = len(donations)

print ('Median donation over the last {0} days is {1}'.format(N, median))

```

    Median donation over the last 12 days is 500.0

### mode 最頻値

```
simplelist = [4,2,1,4,2,2,3,1,4,2,2]
from collections import Counter
c =Counter(simplelist)
print(c.most_common())
print(c)
print(c.most_common(2))
```

    [(2, 5), (4, 3), (1, 2), (3, 1)]
    Counter({2: 5, 4: 3, 1: 2, 3: 1})
    [(2, 5), (4, 3)]

上の、Counter は実装したいね。 これだけのために from collections import Counter はしたくないだろう。 というか実装したほうがわかりやすくないか。

こんなんでどうだ。

```
simplelist = [4,2,1,4,2,2,3,1,4]

def mode_counter(l):
    l.sort()
    items = list(set(l))
    counts = []
    for i in items:
        counts.append(l.count(i))
    item_count = zip(items, counts)
    return (list(item_count))

count_sorted = sorted(dict(mode_counter(simplelist)).items(), key=lambda x:x[1], reverse=True)
print (count_sorted)
```

    [(2, 3), (4, 3), (1, 2), (3, 1)]

```

```

```
from collections import Counter

def calculate_mode(numbers):
    c = Counter(numbers)
    mode = c.most_common(1)
    return mode[0][0]

scores = [7, 8, 9, 2, 10, 9, 9, 9, 9, 4, 5, 6, 1, 5, 6, 7, 8, 6, 1, 10]
mode = calculate_mode(scores)
print("The mode of the list of numbers is: {0}".format(mode))
```

    The mode of the list of numbers is: 9

```
scores = [7, 8, 9, 2, 10, 9, 9, 9, 9, 4, 5, 6, 1, 5, 6, 7, 8, 6, 1, 10]

def mode_counter(l):
    l.sort()
    items = list(set(l))
    counts = []
    for i in items:
        counts.append(l.count(i))
    item_count = zip(items, counts)
    return (list(item_count))

count_sorted = sorted(dict(mode_counter(scores)).items(), key=lambda x:x[1], reverse=True)
print (count_sorted)

# mode = calculate_mode(scores)
print("The mode of the list of numbers is: {0}".format(count_sorted[0][0]))
```

    [(9, 5), (6, 3), (1, 2), (5, 2), (7, 2), (8, 2), (10, 2), (2, 1), (4, 1)]
    The mode of the list of numbers is: 9

最頻値が複数あるときのためのバージョン

```
from collections import Counter

def calculate_mode(numbers):
    c = Counter(numbers)
    numbers_freq = c.most_common()
    max_count = numbers_freq[0][1]

    modes = []
    for num in numbers_freq:
        if num[1] == max_count:
            modes.append(num[0])
    return modes

scores = [5, 5, 5, 4, 4, 4, 9, 1, 3, 3 ,3]
modes = calculate_mode(scores)
print("The mode(s) of the list of numbers are: ")
for mode in modes:
    print(mode)
```

    The mode(s) of the list of numbers are:
    5
    4
    3

```
def mode_counter(l):
    l.sort()
    items = list(set(l))
    counts = []
    for i in items:
        counts.append(l.count(i))
    item_count = zip(items, counts)
    return (list(item_count))

scores = [5, 5, 5, 4, 4, 4, 9, 1, 3, 3 ,3]
modes = calculate_mode(scores)
print("The mode(s) of the list of numbers are: ")
for mode in modes:
    print(mode)

count_sorted = sorted(dict(mode_counter(scores)).items(), key=lambda x:x[1], reverse=True)
print (count_sorted)

```

### 頻度表(度数分布表, frequency table)

```
from collections import Counter

def frequency_table(numbers):
    table = Counter(numbers)
    print("Number\tFrequency")
    for number in table.most_common():
        print('{0}\t{1}'.format(number[0], number[1]))

scores = [7, 8, 9, 2, 10, 9, 9, 9, 9, 4, 5, 6, 1, 5, 6, 7, 8, 6, 1, 10]
frequency_table(scores)
```

    Numbe	Frequency
    9	5
    6	3
    7	2
    8	2
    10	2
    5	2
    1	2
    2	1
    4	1

番号順にソートする

```
from collections import Counter

def frequency_table(numbers):
    table = Counter(numbers)
    print("Number\tFrequency")
    numbers_freq = table.most_common()
    numbers_freq.sort()
    for number in numbers_freq:
        print('{0}\t{1}'.format(number[0], number[1]))

scores = [7, 8, 9, 2, 10, 9, 9, 9, 9, 4, 5, 6, 1, 5, 6, 7, 8, 6, 1, 10]
frequency_table(scores)

```

    Number	Frequency
    1	2
    2	1
    4	1
    5	2
    6	3
    7	2
    8	2
    9	5
    10	2

# 散布 dispersion
範囲 range
variation 分散
deviation 偏差

```
def find_range(numbers):
    lowest = min(numbers)
    highest = max(numbers)
    r = highest-lowest
    return lowest, highest, r

donations = [100, 60, 70, 900, 100, 200, 500, 500, 503, 600, 1000, 1200]
lowest, highest, r = find_range(donations)
print('Lowest: {0} Highest: {1} Range: {2}'.format(lowest, highest, r))
print(find_range(donations))
```

    Lowest: 60 Highest: 1200 Range: 1140
    (60, 1200, 1140)

```latex
%%latex
\displaystyle

\mathrm{variance} = \frac{\Sigma (x_i - x_\mathrm{mean})^2}{n}
```

\displaystyle

\mathrm{variance} = \frac{\Sigma (x_i - x_\mathrm{mean})^2}{n}

```
def calculate_mean(numbers):
    s = sum(numbers)
    N = len(numbers)
    mean = s/N
    return mean

def find_differences(numbers):
    mean = calculate_mean(numbers)
    diff = []
    for num in numbers:
        diff.append(num-mean)
    return diff

def calculate_variance(numbers):
    diff = find_differences(numbers)
    squared_diff = []
    for d in diff:
        squared_diff.append(d**2)
    sum_squared_diff = sum(squared_diff)
    variance = sum_squared_diff/len(numbers)
    return variance

donations = [100, 60, 70, 900, 100, 200, 500, 500, 503, 600, 1000, 1200]
variance = calculate_variance(donations)
print('The variance of the list of numbers is {0}'.format(variance))
std = variance**0.5
print('The standard deviation of the list of numbers is {0}'.format(std))

```

    The variance of the list of numbers is 141047.35416666666
    The standard deviation of the list of numbers is 375.5627166887931

```
donations= [382, 389, 377, 397, 396, 368, 369, 392, 398, 367, 393, 396]
variance = calculate_variance(donations)
print('The variance of the list of numbers is {0}'.format(variance))
std = variance**0.5
print('The standard deviation of the list of numbers is {0}'.format(std))
```

    The variance of the list of numbers is 135.38888888888889
    The standard deviation of the list of numbers is 11.63567311713804

```
import matplotlib.pyplot as plt
import numpy as np

donations1 = [100, 60, 70, 900, 100, 200, 500, 500, 503, 600, 1000, 1200]
donations2 = [382, 389, 377, 397, 396, 368, 369, 392, 398, 367, 393, 396]
mean = [400,400,400,400,400,400,400,400,400,400,400,400,]

fig = plt.figure()
ax = fig.add_subplot()

months = range(1, 13)
ax.plot(donations1, marker='o')
ax.plot(donations2, marker='o')
ax.plot(mean)
plt.legend(["Donations 1", "Donations 2", "Mean"])

plt.show()

```

# 相関 correlation

相関係数 correlation coefficient

相関係数は正と負があり、1 が最大で -1 が最小である。 0 の場合は少なくとも線形の相関はなく、非線形の相関がある可能性はある。

相関関係があることは因果関係を意味しない。 有名な例は、アイスクリームの売上と犯罪率である。

相関係数は次の公式で計算される。

```latex
%%latex
\displaystyle

\mathrm{correlation} = \frac{n \Sigma {xy} - \Sigma x \Sigma y}{\sqrt {
    (n \Sigma x^2 - (\Sigma x)^2)
    (n \Sigma y^2 - (\Sigma y)^2)
    }}
```

\displaystyle

\mathrm{correlation} = \frac{n \Sigma {xy} - \Sigma x \Sigma y}{\sqrt {
    (n \Sigma x^2 - (\Sigma x)^2)
    (n \Sigma y^2 - (\Sigma y)^2)
    }}

```
def find_corr_x_y(x, y):
    n = len(x)

    prod = []
    for xi, yi in zip(x, y):
        prod.append(xi * yi)

    sum_prod_x_y = sum(prod)
    sum_x = sum(x)
    sum_y = sum(y)
    squared_sum_x = sum_x ** 2
    squared_sum_y = sum_y ** 2

    x_square = []
    for xi in x:
        x_square.append(xi**2)

    x_square_sum = sum(x_square)

    y_square = []
    for yi in y:
        y_square.append(yi ** 2)
    y_square_sum = sum(y_square)

    numerator = n * sum_prod_x_y - sum_x * sum_y
    denominator_term1 = n * x_square_sum - squared_sum_x
    denominator_term2 = n * y_square_sum - squared_sum_y
    denominator = (denominator_term1 * denominator_term2) ** 0.5
    correlation = numerator/denominator

    return correlation

```

次の2つの数列の相関関係を調べる。

相関関係を見るには、相関係数を算出する前にプロットしてみるのが大切である。

```
high_school_grades = [90, 92, 95, 96, 87, 87, 90, 95, 98, 96]
college_admission_test = [85, 87, 86, 97, 96, 88, 89, 98, 98, 87]
```

```
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()

high_school_grades = [90, 92, 95, 96, 87, 87, 90, 95, 98, 96]
college_admission_test = [85, 87, 86, 97, 96, 88, 89, 98, 98, 87]

ax.set_xlabel('High School Grades')
ax.set_ylabel('College Admission Test Scores')
ax.scatter(high_school_grades, college_admission_test)
plt.show()
```

若干の正の相関関係が見られるが、弱い相関係数である。

```
print (find_corr_x_y(high_school_grades, college_admission_test))
```

    0.3183785775683751

数学のグレードとの相関を見よう。

high_school_math_grades = [83, 85, 84, 96, 94, 86, 87, 97, 97, 85]

```
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()

# high_school_grades = [90, 92, 95, 96, 87, 87, 90, 95, 98, 96]
high_school_math_grades = [83, 85, 84, 96, 94, 86, 87, 97, 97, 85]
college_admission_test = [85, 87, 86, 97, 96, 88, 89, 98, 98, 87]

ax.set_xlabel('High School Math Grades')
ax.set_ylabel('College Admission Test Scores')
ax.scatter(high_school_math_grades, college_admission_test)
plt.show()
```

```
print (find_corr_x_y(high_school_math_grades, college_admission_test))
```

    0.9989633063220916

相関係数が 1 に近いので、強い正の相関関係であることがわかる。

# 散布図 scatter plot の重要性

統計的な数値、つまり平均、分散、相関係数、が同じでまったく違う性質のデータがある。Francis Anscombe の “Graphs in Statistical Analysis” に書かれている有名な例を見てみよう。

次のA, B, C, Dのそれぞれについて2つの数列は同じ平均、分散、相関係数であるが、プロットするとまったく違う性質のデータである。

```
a_x1 = [10.0, 8.0, 13.0, 9.0, 11.0, 14.0, 6.0, 4.0, 12.0, 7.0, 5.0]
a_y1 = [8.04, 6.95, 7.58, 8.81, 8.33, 9.96, 7.24, 4.26, 10.84, 4.82, 5.68]
b_x2 = [10.0, 8.0, 13.0, 9.0, 11.0, 14.0, 6.0, 4.0, 12.0, 7.0, 5.0]
b_y2 = [9.14, 8.14, 8.74, 8.77, 9.26, 8.10, 6.13, 3.10, 9.13, 7.26, 4.74]
c_x3 = [10.0, 8.0, 13.0, 9.0, 11.0, 14.0, 6.0, 4.0, 12.0, 7.0, 5.0]
c_y3 = [7.46, 6.77, 12.74, 7.11, 7.81, 8.84, 6.08, 5.39, 8.15, 6.42, 5.73]
d_x4 = [8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 19.0, 8.0, 8.0, 8.0]
d_y4 = [6.58, 5.76, 7.71, 8.84, 8.47, 7.04, 5.25, 12.50, 5.56, 7.91, 6.89]
```

```
a_x1 = [10.0, 8.0, 13.0, 9.0, 11.0, 14.0, 6.0, 4.0, 12.0, 7.0, 5.0]
a_y1 = [8.04, 6.95, 7.58, 8.81, 8.33, 9.96, 7.24, 4.26, 10.84, 4.82, 5.68]
b_x2 = [10.0, 8.0, 13.0, 9.0, 11.0, 14.0, 6.0, 4.0, 12.0, 7.0, 5.0]
b_y2 = [9.14, 8.14, 8.74, 8.77, 9.26, 8.10, 6.13, 3.10, 9.13, 7.26, 4.74]
c_x3 = [10.0, 8.0, 13.0, 9.0, 11.0, 14.0, 6.0, 4.0, 12.0, 7.0, 5.0]
c_y3 = [7.46, 6.77, 12.74, 7.11, 7.81, 8.84, 6.08, 5.39, 8.15, 6.42, 5.73]
d_x4 = [8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 19.0, 8.0, 8.0, 8.0]
d_y4 = [6.58, 5.76, 7.71, 8.84, 8.47, 7.04, 5.25, 12.50, 5.56, 7.91, 6.89]

def mean(numbers):
    s = sum(numbers)
    N = len(numbers)
    mean = s/N
    return mean

def find_differences(numbers):
    mean_num = mean(numbers)
    diff = []
    for num in numbers:
        diff.append(num-mean_num)
    return diff

def stddev(numbers):
    diff = find_differences(numbers)
    squared_diff = []
    for d in diff:
        squared_diff.append(d**2)
    sum_squared_diff = sum(squared_diff)
    variance = sum_squared_diff/len(numbers)
    return variance**0.5

def find_corr_x_y(x, y):
    n = len(x)

    prod = []
    for xi, yi in zip(x, y):
        prod.append(xi * yi)

    sum_prod_x_y = sum(prod)
    sum_x = sum(x)
    sum_y = sum(y)
    squared_sum_x = sum_x ** 2
    squared_sum_y = sum_y ** 2

    x_square = []
    for xi in x:
        x_square.append(xi**2)

    x_square_sum = sum(x_square)

    y_square = []
    for yi in y:
        y_square.append(yi ** 2)
    y_square_sum = sum(y_square)

    numerator = n * sum_prod_x_y - sum_x * sum_y
    denominator_term1 = n * x_square_sum - squared_sum_x
    denominator_term2 = n * y_square_sum - squared_sum_y
    denominator = (denominator_term1 * denominator_term2) ** 0.5
    correlation = numerator/denominator

    return correlation

print("Followings are mean, deviation of X, mean, deviation of Y, and correlation of A, B, C, D")
print(mean(a_x1), stddev(a_x1), mean(a_y1), stddev(a_y1), find_corr_x_y(a_x1, a_y1))
print(mean(b_x2), stddev(b_x2), mean(b_y2), stddev(b_y2), find_corr_x_y(b_x2, b_y2))
print(mean(c_x3), stddev(c_x3), mean(c_y3), stddev(c_y3), find_corr_x_y(c_x3, c_y3))
print(mean(d_x4), stddev(d_x4), mean(d_y4), stddev(d_y4), find_corr_x_y(d_x4, d_y4))

```

    Followings are mean, deviation of X, mean, deviation of Y, and correlation of A, B, C, D
    9.0 3.1622776601683795 7.500909090909093 1.937024215108669 0.816420516344843
    9.0 3.1622776601683795 7.500909090909091 1.93710869148962 0.8162365060002422
    9.0 3.1622776601683795 7.500000000000001 1.9359329439927313 0.8162867394895953
    9.0 3.1622776601683795 7.50090909090909 1.9360806451340837 0.8165214368885068

しかし!!!! 散布図は次のようになる。

```
import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
ax4 = fig.add_subplot(2, 2, 4)

ax1.scatter(a_x1, a_y1)
ax1.set_xlabel("X1")
ax1.set_ylabel("Y1")
ax2.scatter(b_x2, b_y2)
ax2.set_xlabel("X2")
ax2.set_ylabel("Y2")
ax3.scatter(c_x3, c_y3)
ax3.set_xlabel("X3")
ax3.set_ylabel("Y3")
ax4.scatter(d_x4, d_y4)
ax4.set_xlabel("X4")
ax4.set_ylabel("Y4")
plt.show()
```

# ファイルの読み書き (省略)

テキストファイル

CSVファイル

# パーセンタイル(分布)

[5, 1, 9, 3, 14, 9, 7] において、50番目のパーセンタイルは 7 であり、25番目のパーセンタイルは 3.5 である。

パーセンタイルは次のような手順で算出する。 これをプログラム化する。

1. パーセンタイル $p$ に対応する値を算出したいとする。
2. データを昇順 ascending order でソートする。 これを $\mathrm{data}$ とする。
3. 次に、
$$
i = \frac{np}{100} + 0.5
$$
を算出する。 ここで $n$ はデータの個数である。
4. この結果 $i$ が整数ならば $\mathrm{data[i]}$ がパーセンタイル $p$ に対応する値である。
5. もし $i$ が整数でないならば、$i$ の整数部分の値を $k$ とし、小数点以下を $f$ として、
$\mathrm{(1 - f)*data[k] + f * data[k + 1]}$ がパーセンタイル $p$ の値である。

```
data = [5, 1, 9, 3, 14, 9, 7]

def calc_percentile(x, p):
    x.sort()
    i = len(x)*p / 100 + 0.5
    if i == i // 1 :
        return (x[int(i-1)])
    else:
        k = i // 1
        f = i % 1
        return ((1-f)*x[int(k-1)]+f*x[int(k)])

print (calc_percentile(data, 50))
print (calc_percentile(data, 25))
```

    7
    3.5

### 頻度表のグループ化 grouped frequency table

以前

scores = [7, 8, 9, 2, 10, 9, 9, 9, 9, 4, 5, 6, 1, 5, 6, 7, 8, 6, 1, 10]

について頻度表を作成したが、これをグループ化して、次のような表を作成したい。

Grade | Frequency
--- | ---
1 - 6 | 6
6 - 11 | 14

ここで、範囲の 1 - 6 は 1 を含み 6 を含まない。 6 - 11 は 6 を含み 11 を含まない。

範囲の作成については次の関数を用いる。

```
scores = [7, 8, 9, 2, 10, 9, 9, 9, 9, 4, 5, 6, 1, 5, 6, 7, 8, 6, 1, 10]

def create_classes(numbers, n):
    low = min(numbers)
    high = max(numbers)

    width = (high - low) / n
    classes = []
    a = low
    b = low + width
    while a < (high - width):
        classes.append((a, b))
        a = b
        b = a + width
    classes.append((a, high + 1))
    return classes

print(create_classes(scores, 2))

```

    [(1, 5.5), (5.5, 11)]

```
# create grouped frequency table

def create_classes(numbers, n):
    low = min(numbers)
    high = max(numbers)

    width = (high - low) / n
    classes = []
    a = low
    b = low + width
    while a < (high - width):
        classes.append((a, b))
        a = b
        b = a + width
    classes.append((a, high + 1))
    return classes

def frequency_counter(l, num_classes):
    l.sort()
    items = list(set(l))
    counts = []
    for i in items:
        counts.append(l.count(i))
    item_count = list(zip(items, counts))

    classes = create_classes(l, num_classes)
    frequency = []
    for class_i in classes:
        i = 0
        for item in item_count:
            if (item[0] >= class_i[0] and item[0] < class_i[1]):
                i = i + item[1]
        frequency.append(i)

    grouped_frequency = list(zip(classes, frequency))

    return (grouped_frequency)

scores = [7, 8, 9, 2, 10, 9, 9, 9, 9, 4, 5, 6, 1, 5, 6, 7, 8, 6, 1, 10]
grouped_frequency = frequency_counter(scores, 2)
print(grouped_frequency)
```

    [((1, 5.5), 6), ((5.5, 11), 14)]

# 代数と記号数学 Algebra and Symbolic Math with SymPy

$x^3 + 3 x^2 + 3 x + 1$ を因数分解せよ。
みたいのが簡単に解けるようになるよ!!!!

```
from sympy import *
init_printing()
x = symbols('x')
factor(x**3 + 3*x**2 + 3*x + 1)
```

```
x.name
```

    'x'

```
from sympy import *
init_printing()
x, y = symbols('x, y')
factor(x**2 - y**2)
```

```
from sympy import *
init_printing()
x, y = symbols('x, y')

pprint(expand ((x+y)**3))
# expand ((x+y)**3)
display(expand ((x+y)**3))

```

```
from sympy import *
init_printing()

x = symbols ('x')
b = (x + 2) * (x - 2)
c = (x**2 - 4) / (x - 2)
display(b, c)
pprint(c)
print(latex(c))
```

```latex
%%latex
\displaystyle

\frac{x^{2} - 4}{x - 2}
```

\displaystyle

\frac{x^{2} - 4}{x - 2}

```
init_printing(order='rev-lex')
expr = 1 + 2*x + 2*x**2

expr
```

# 数列 sequence, 級数 series

次のような級数を考えてみる。

$$
x + \frac{x^2}{2} + \frac{x^3}{3} + \frac{x^4}{4} + \dots + \frac{x^n}{n}
$$

```latex
%%latex
\displaystyle

x + \frac{x^2}{2} + \frac{x^3}{3} + \frac{x^4}{4} + \dots + \frac{x^n}{n}
```

\displaystyle

x + \frac{x^2}{2} + \frac{x^3}{3} + \frac{x^4}{4} + \dots + \frac{x^n}{n}

```
from sympy import *
init_printing()

x = symbols('x')

display(x)
```

```
from sympy import *
init_printing()

def print_series(n):
    init_printing(order='rev-lex')

    x = symbols('x')
    series = x
    for i in range(2, n + 1):
        series = series + (x ** i) / i

    return series

display(print_series(5))

```

```
from sympy import *
help(series)
```

    Help on function series in module sympy.series.series:

    series(expr, x=None, x0=0, n=6, dir='+')
        Series expansion of expr around point `x = x0`.

        See the doctring of Expr.series() for complete details of this wrapper.

# 値の代入

```
from sympy import *
init_printing()

x, y = symbols('x, y')
expr = x * x + x * y + x * y + y * y
display(expr)

res = expr.subs({x: 1, y: 2})
display(res)
```

```
from sympy import *
init_printing()

x, y = symbols('x, y')
expr = x * x + x * y + x * y + y * y
display(expr)

res = expr.subs({x: 1, y: 2})
display(res)

res = expr.subs({x:1-y})
display(res)

display(expand(res))

display (simplify(res))
```

```
from sympy import *
init_printing()

def print_series(n):
    init_printing(order='rev-lex')

    x = symbols('x')
    series = x
    for i in range(2, n + 1):
        series = series + (x ** i) / i

    return series

# The number of terms in the series:
n = 5
series = print_series(n)

# the Value of x to evalute the series:
x_value = 1.2

series_value = series.subs({x: x_value})
text = "Value of the series at {0}: {1}".format(x_value, series_value)

display(series)

print(text)

```

# 文字列を数式に変換する

```
from sympy import *
init_printing(order='lex')

text = "x**2 + 3*x + x**3 + 2*x"

expr = sympify(text)

display (expr)

display(2*expr)

```

# 例外処理 catch SympifyError exception

```
from sympy import *
init_printing()

text = "x**2 + 3*x + x**3 + 2x"

try:
    expr = sympify(text)
    display(expr)
except SympifyError:
    print ('Invalid text')

```

    Invalid text

```
from sympy import *
init_printing()

x,y = symbols('x, y')

def product(expr1, expr2):
    prod = expand(expr1 * expr2)
    return prod

expr1 = "2*x - 3"
expr2 = "x + y + 1"

expr1 = sympify(expr1)
expr2 = sympify(expr2)

display(product(expr1, expr2))
display(factor(product(expr1, expr2)))
```

```
from sympy import *
init_printing()

x, y = symbols("x, y")

expr1 = x ** 2 + x * 2 + x
expr2 = x ** 3 + x * 3 + x

display(expr1 * expr2)
display(expand(expr1 * expr2))

expr3 = x * y + x
expr4 = x * x + y

display(expr3 * expr4)
display(expand(expr3*expr4))
```

# 方程式を解く

```
from sympy import *
init_printing()

x, y = symbols("x, y")

expr = x - 5 - 7
display(expr)
solve(expr)
```

```
from sympy import *
init_printing()

x, y = symbols("x, y")

expr = x**2 + 5*x + 4
display(expr)
display(solve(expr))
solve(expr, dict=True)
```

```
from sympy import *
init_printing()

x, y = symbols("x, y")

expr = x**2 + x + 1
display(expr)
display(solve(expr))
solve(expr, dict=True)
```

```
from sympy import *
init_printing()

a, b, c, x, y = symbols("a, b, c, x, y")

expr = a*x**2 + b*x + c
display(expr)
display(solve(expr, x))
solve(expr, x, dict=True)

```

```
from sympy import *
init_printing()

a, b, c, x, y = symbols("a, b, c, x, y")

expr = (x - 1) * (y - 2)
display(expand(expr))
display(solve(expr, x, y))
solve(expr, x, y, dict=True)

```

### 運動方程式

次に物理学の運動方程式の1つを考える。

加速度が $a$ で一定で、初期速度 $u$ の物体が $t$ 時間の間に移動する距離は次の公式で与えられる。

$$
s = ut + \frac12 a t^2
$$

```latex
%%latex
\displaystyle

s = ut + \frac12 at^2
```

\displaystyle

s = ut + \frac12 at^2

距離 $s$ を移動するのに必要な時間 $t$ を solve() を使って解いてみよう。

```
from sympy import *
init_printing()

s, u, t, a = symbols("s,u,t,a")

expr = u * t + (1 / 2) * a * t * t - s
t_expr = solve(expr, t, dict=True)
display(t_expr)
print()
latex(t_expr)
```

$$
\left [ \left \{
    t : \frac{- u + \sqrt{2.0 a s + u^2}}{a}
\right \}, \quad \left \{
    t : - \frac{u + \sqrt{2.0 a s + u^2}}{a}
\right \}\right ]
$$

$t$ の式を得たので、$s, u, a$ を subs() で代入すれば $t$ の2つの値を得ることができる。

# 線形方程式 linear equation

次の2つの方程式を考える。

$$
\begin{array}{ll}
2x + 3y &=& 6 \\
3x + 2y &=& 12
\end{array}
$$

```latex
%%latex
\displaystyle

\begin{array}{ll}
2x + 3y &=& 6  \\
3x + 2y &=& 12
\end{array}
```

\displaystyle

\begin{array}{ll}
2x + 3y &=& 6  \\
3x + 2y &=& 12
\end{array}

```
from sympy import *
init_printing()

x, y = symbols("x, y")

expr1 = 2 * x + 3 * y - 6
expr2 = 3 * x + 2 * y - 12

solve((expr1, expr2))

```

```
solve((expr1, expr2), dict=True)
```

```
soln = solve((expr1, expr2))
display(expr1.subs({x:soln[x], y:soln[y]}))
display(expr2.subs({x:soln[x], y:soln[y]}))

```

# 数式でグラフを描く

テキストでは sympy.plotting.plot を使っているがうまく行かないのと、sympy.plotting.plot でも裏で matplotlib.pyplot を使っているので、以下、matplotlib.pyplot で描いてみる。

```
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot()

x = np.linspace(-10, 10, 400)
y = 2 * x + 3
ax.plot(x, y)

fig.show()
```

matplotlibのグラフでは普通 x=0 , y = 0 の軸を描かないが、描くとすると次のようになる。

```
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot()

x = np.linspace(-10, 10, 400)
y = 2 * x + 3
ax.plot(x, y)

ax.axhline(y=0)
ax.axvline(x=0)
ax.grid(true)
fig.show()
```

タイトルなどをつけてみよう。

```
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot()

x = np.linspace(-10, 10, 400)
y = 2 * x + 3
ax.plot(x, y)
ax.set_title('A line')
ax.set_xlabel('x')
ax.set_ylabel('2x + 3')

ax.grid(true)
fig.show()

```

文字列で表された方程式を sympify して、y で solve すればグラフが描ける。

```
import matplotlib.pyplot as plt
import numpy as np
from sympy import *
init_printing()

x,y = symbols('x, y')

expr_text = "2*x + 3*y - 6"
expr = sympify(expr_text)
solutions = solve(expr, y)
display(solutions[0])

fig = plt.figure()
ax = fig.add_subplot()

x_values = np.linspace(-10, 10, 40)
y = []
for i in x_values :
    res = solutions[0].subs({x: i})
    y.append(res)

ax.plot(x_values, y)
ax.set_title(expr_text)
ax.set_xlabel('x')
ax.set_ylabel(solutions[0])

ax.grid(true)
fig.show()

```

### グラフを重ねる

```
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-10,10,40)
expr1 = 2 * x + 3
expr2 = 3 * x + 1

fig = plt.figure()
ax = fig.add_subplot()

ax.plot(expr1)
ax.plot(expr2)
ax.legend(["2 * x + 3","3 * x + 1"])
ax.grid(True)
fig.show()

from sympy import *
x, y = symbols('x,y')
solve(((2 * x + 3 - y), (3 * x + 1 - y)))
```

上の例では、試行錯誤の結果、同じ $x$ という変数を使って、matplotlibでグラフを描くのと、グラフの交点を solve を使って解くのは、matplotlib が python で、solve が sympy なのでそのままでは難しい。なので、解を求める前までは python で進め、解を求めるのを sympy でやった。

今の考え: このやり方でやるのならば、

1. 変数をダブらないようにする。
2. 変数を初期化する方法を探す。
3. 無理なので全く別にやる。

とか方法を決めるのがよいと思う。 だれかやっているだろうから、これはこのままにして先へ進む。いまのところ、無理なので全く別にやる、ということにしておこう。

```
from sympy import *
init_printing(order="rev-lex")

x, n, s = symbols("x, n, s")

s = summation(x**n/n, (n, 1, 5))

display(s)

display(s.subs({x:1.2}))
```

各項 term が $a + (n - 1) * d$ で表される級数の $n$ 個の項を求める。

例) $n = 3$ ならば  $3a + 3d$

```
from sympy import *
init_printing(order="rev-lex")

a, d, m, n, s = symbols("a, d, m, n, s")

s = summation(a+(n-1)*d, (n, 1, m))

display(s.subs({m:3}))

```

# 不等式 inequality equation

```
from sympy import *
init_printing()

x = symbols("x")

ineq_obj = -x ** 2 + 4 < 0
display(ineq_obj)

lhs = ineq_obj.lhs
p = Poly(lhs, x)
rel = ineq_obj.rel_op

solve_poly_inequality(p, rel)

```

# 有理式 rational expression

有理式とは分数の分子 numerator 分母 denominator の両方が多項式 polynomial であるもののことで、有理不等式は次のようなものである。

$$
\frac{x - 1}{x + 2} > 0
$$

```latex
%%latex
\displaystyle
\frac{x - 1}{x + 2} > 0
```

\displaystyle
\frac{x - 1}{x + 2} > 0

```
from sympy import *
init_printing()

x = symbols("x")

ineq_obj = ((x-1)/(x+2)) > 0
display(ineq_obj)

lhs = ineq_obj.lhs
numer, denom = lhs.as_numer_denom()
p1 = Poly(numer)
p2 = Poly(denom)
rel = ineq_obj.rel_op

solve_rational_inequalities([[((p1, p2), rel)]])

```

次に多項式でも有理式でもない式の不等式を取り上げる。

$$
\sin x - 0.6 > 0
$$

```latex
%%latex
\displaystyle

\sin x - 0.6 > 0

```

\displaystyle

\sin x - 0.6 > 0

```
from sympy import *
init_printing()

x = symbols("x")

ineq_obj = sin(x) - 0.6 > 0
display(ineq_obj)

display(solve_univariate_inequality(ineq_obj, x, relational=False))

```

```
from sympy import *
init_printing()

display(pi)

display(float(pi))

s = solve_univariate_inequality(ineq_obj, x, relational=False)

display(s.end)
display(float(s.end))
```

```
from sympy import *
init_printing()

x = symbols('x')

expr = x ** 2 - 4
print('\"{0}\" is polynomial => {1}'.format(expr, expr.is_polynomial()))
print()
expr = 2 * sin(x) + 3
print('\"{0}\" is polynomial => {1}'.format(expr, expr.is_polynomial()))
print()
expr = (2+x)/(3+x)
print('\"{0}\" is rational => {1}'.format(expr, expr.is_rational_function()))
print()
expr = 2+x
print('\"{0}\" is rational => {1}'.format(expr, expr.is_rational_function()))
print()
expr = 2+sin(x)
print('\"{0}\" is rational => {1}'.format(expr, expr.is_rational_function()))
print()

```

    "x**2 - 4" is polynomial => True

    "2*sin(x) + 3" is polynomial => False

    "(x + 2)/(x + 3)" is rational => True

    "x + 2" is rational => True

    "sin(x) + 2" is rational => False

# 集合 set と確率 probability

集合の要素には重複がないという点でリストとは違う。

```
from sympy import *
init_printing()

s = FiniteSet(2,4,6)
print(s)
print(type(s))
```

    {2, 4, 6}
    <class 'sympy.sets.sets.FiniteSet'>

sympy を入れなくても、python に set という型があり、手軽に使えるが、本格的に集合を扱う場合にはいまのところ sympy の FiniteSet が適している。

```
s = set([5,1,2,1,2,3,4,5,5])
print(s)
print(type(s))
```

    {1, 2, 3, 4, 5}
    <class 'set'>

```
members = {1,2,3,4,1,2}
s = FiniteSet(*members)
print(s)
print(type(s))
```

    {1, 2, 3, 4}
    <class 'sympy.sets.sets.FiniteSet'>

```
members = {1,2,3,4,1,2}
s = list(FiniteSet(*members))
print(s)
print(type(s))
```

    [1, 2, 3, 4]
    <class 'list'>

```
set([3,2,1,1]) == FiniteSet(1,2,3)
```

    True

### 濃度 cardinality

有限集合における「元の個数」を一般の集合に拡張したもの。

```
cardinality = len(FiniteSet(1,2,2,3))
print (cardinality)
```

    3

```
from sympy import *
s = FiniteSet()
s
```

```
set([])
```

```
set([]) == FiniteSet()
```

    True

```
EmptySet()
```

```
members = [1,2,2,3]
s = FiniteSet(*members)
s
```

```
2 in s
```

    True

```
for s in s:
    print(s**2)
```

    1
    4
    9

```
{3,2,1} == FiniteSet(1,2,3)
```

    True

```
from sympy import *

s = FiniteSet(1,2,3)
t = FiniteSet(1,2)
print(t.is_subset(s))
print(s.is_superset(t))
```

    True
    True

```
from sympy import *

s = FiniteSet(1,2,3)
t = s.powerset()
print(t)
```

    {EmptySet(), {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}

```
from sympy import *

s = FiniteSet(1, 2, 3)
t = FiniteSet(1, 2, 3)
print(s.is_proper_subset(t))
print(t.is_proper_superset(s))

t = FiniteSet(1, 2, 3, 4)
print(s.is_proper_subset(t))
print(t.is_proper_superset(s))
```

    False
    False
    True
    True

```
from sympy import *

s = FiniteSet(1, 2, 3)
t = FiniteSet(2, 4, 6)
print(s.union(t))

```

    {1, 2, 3, 4, 6}

```
from sympy import *

s = FiniteSet(1, 2)
t = FiniteSet(2, 3)
print(s.intersect(t))

```

    {2}

```
from sympy import *

s = FiniteSet(1, 2, 3)
t = FiniteSet(2, 4, 6)
u = FiniteSet(3, 5, 7)

print(s.union(t).union(u))
print()
print(s.intersect(t).intersect(u))
```

    {1, 2, 3, 4, 5, 6, 7}

    EmptySet()

# デカルト積 cartesian product

```
from sympy import *

s = FiniteSet(1, 2)
t = FiniteSet(3, 4)
p = s*t
print(p)
print(list(p))
```

    {1, 2} x {3, 4}
    [(1, 3), (1, 4), (2, 3), (2, 4)]

```
s = FiniteSet(0,1,2)
print(list(s**2))
```

    [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

```
from sympy import *

s = FiniteSet(1, 2, 3, 4)
t = FiniteSet(3, 4)
p = s*t
len(p) == len(s)*len(t)
```

    True

# 振り子 pendulum

振り子の紐の長さを $L$、一回振れて戻ってくるまでの周期を $T$、とすると次の式が成り立つ。

$$
T = 2 \pi \sqrt{\frac{L}{g}}
$$

ここで $\pi$ 数学的定数で約 3.14、$g$ は重力加速度で約 9.8 $\mathrm{m/s^2}$である。

```latex
%%latex
\displaystyle

T = 2 \pi \sqrt{\frac{L}{g}}

```

\displaystyle

T = 2 \pi \sqrt{\frac{L}{g}}

振り子の長さを cm で、15, 18, 21, 22.5, 25 の 5 とおりで考える。

```
from sympy import *

def time_period(length):
    g = 9.8
    T = 2 * pi * (length / g)** 0.5
    return T

L = FiniteSet(15, 18, 21, 22.5, 25)
for l in L:
    t = time_period(l / 100)
    print('Length: {0} cm Time Period: {1:.3f} s'.format(float(l), float(t)))

```

    Length: 15.0 cm Time Period: 0.777 s
    Length: 18.0 cm Time Period: 0.852 s
    Length: 21.0 cm Time Period: 0.920 s
    Length: 22.5 cm Time Period: 0.952 s
    Length: 25.0 cm Time Period: 1.004 s

次にこれを重力加速度が 9.8, 9.78, 9.83 の場合で考える。

```
from sympy import *

def time_period(length, g):
    T = 2 * pi * (length / g) ** 0.5
    return T

L = FiniteSet(15, 18, 21, 22.5, 25)
g_values = FiniteSet(9.8, 9.78, 9.83)
print('{0:^15}{1:^15}{2:^15}'.format(
    'Length(cm)', 'Gravity(m/s^2)', 'Time  Period(s)'))
for elem in L*g_values:
    l = elem[0]
    g = elem[1]
    t = time_period(l / 100, g)
    print('{0:^15}{1:^15}{2:^15.3f}'.format(float(l), float(g), float(t)))

```

      Length(cm)   Gravity(m/s^2) Time  Period(s)
         15.0           9.78           0.778
         15.0            9.8           0.777
         15.0           9.83           0.776
         18.0           9.78           0.852
         18.0            9.8           0.852
         18.0           9.83           0.850
         21.0           9.78           0.921
         21.0            9.8           0.920
         21.0           9.83           0.918
         22.5           9.78           0.953
         22.5            9.8           0.952
         22.5           9.83           0.951
         25.0           9.78           1.005
         25.0            9.8           1.004
         25.0           9.83           1.002

# 確率 probability

$S$ Sample space
$E$ Event

$$
P(E) = \frac{n(E)}{n(S)}
$$

```latex
%%latex
\displaystyle

P(E) = \frac{n(E)}{n(S)}
```

\displaystyle

P(E) = \frac{n(E)}{n(S)}

ここで $n(E)$ と $n(S)$ は事象 $E$ と サンプルスペース $S$ の数 cardinality である。 $P(E)$ は 0 と 1 の間の値で、大きい数字の方が確率が高いことを表す。

例えばサイコロで 3 の出る確率は次のようになる。

$$
\begin{array}{ll}
S &=& \{1,2,3,4,5,6\}\\
E &=& \{3\}\\
n(S) &=& 6 \\
n(E) &=& 1 \\
P(E) &=& \Large{\frac{1}{6}}
\end{array}
$$

```latex
%%latex
\displaystyle

\begin{array}{lll}
S &=& \{1,2,3,4,5,6\}\\
E &=& \{3\}\\
n(S) &=& 6 \\
n(E) &=& 1 \\
P(E) &=& \Large{\frac{1}{6}}
\end{array}
```

\displaystyle

\begin{array}{lll}
S &=& \{1,2,3,4,5,6\}\\
E &=& \{3\}\\
n(S) &=& 6 \\
n(E) &=& 1 \\
P(E) &=& \Large{\frac{1}{6}}
\end{array}

```
from sympy import *

def probability(space, event):
    return len(event) / len(space)

def check_prime(number):
    if number != 1:
        for factor in range(2, number):
            if number % factor == 0:
                return False
    else:
        return False
    return True

space = FiniteSet(*range(1, 21))
primes = []
for num in space:
    if check_prime(num):
        primes.append(num)
event = FiniteSet(*primes)
p = probability(space, event)

print('Sample space: {0}'.format(space))
print('Event: {0}'.format(event))
print('Probability of rolling a prime: {0:0.5f}'.format(p))

```

    Sample space: {1, 2, 3, ..., 18, 19, 20}
    Event: {2, 3, 5, 7, 11, 13, 17, 19}
    Probability of rolling a prime: 0.40000

事象 $A$ または $B$ の確率。 どちらかが起きる確率。

例として、次の例を考えよう。

> A: 素数である場合
> B: 奇数である場合

$S$ は {1,2,3,4,5,6} 、 $A$ は {2,3,5} 、$B$ は {1,3,5} になる。よって、

$$
E = \{2,3,5\} \cup \{1,3,5\} = \{1,2,3,5\} \\
P(E) = \frac{n(E)}{n(S)} = \frac{4}{6} = \frac{2}{3}
$$

```latex
%%latex
\displaystyle

E = \{2,3,5\} \cup \{1,3,5\} = \{1,2,3,5\} \\
P(E) = \frac{n(E)}{n(S)} = \frac{4}{6} = \frac{2}{3}

```

\displaystyle

E = \{2,3,5\} \cup \{1,3,5\} = \{1,2,3,5\} \\
P(E) = \frac{n(E)}{n(S)} = \frac{4}{6} = \frac{2}{3}

```
from sympy import *

s = FiniteSet(1, 2, 3, 4, 5, 6)
a = FiniteSet(2, 3, 5)
b = FiniteSet(1, 3, 5)
e = a.union(b)
display(e)
print(len(e)/len(s))

```

    {1, 2, 3, 5}

    0.6666666666666666

# ランダム

```
import random
print(random.randint(1, 6))
print(random.randint(1, 6))
print(random.randint(1, 6))
print(random.randint(1, 6))
print(random.randint(1, 6))
print(random.randint(1, 6))
print(random.randint(1, 6))
print(random.randint(1, 6))
print(random.randint(1, 6))

```

    1
    5
    6
    6
    2
    3
    6
    6
    4

```
import matplotlib.pyplot as plt
import random

target_score = 20

def roll():
    return random.randint(1, 6)

score = 0
num_rolls = 0
while score < target_score:
    die_roll = roll()
    num_rolls += 1
    print('Rolled: {0}'.format(die_roll))
    score += die_roll
    print('Score of {0} reached in {1} rolls'.format(score, num_rolls))

```

    Rolled: 1
    Score of 1 reached in 1 rolls
    Rolled: 2
    Score of 3 reached in 2 rolls
    Rolled: 3
    Score of 6 reached in 3 rolls
    Rolled: 6
    Score of 12 reached in 4 rolls
    Rolled: 5
    Score of 17 reached in 5 rolls
    Rolled: 4
    Score of 21 reached in 6 rolls

```
from sympy import *
import random

def find_prob(target_score, max_rolls):
    die_sides = FiniteSet(1, 2, 3, 4, 5, 6)
    s = die_sides ** max_rolls
    if max_rolls > 1:
        success_rolls = []
        for elem in s:
            if sum(elem) >= target_score:
                success_rolls.append(elem)
    else:
        if target_score > 6:
            success_rolls = []
        else:
            success_rolls = []
            for roll in die_sides:
                if roll >= target_score:
                    success_rolls.append(roll)
    e = FiniteSet(*success_rolls)
    return len(e) / len(s)

target_score = 25
max_rolls = 4
p = find_prob(target_score, max_rolls)
print('Probability:  {0:.5f}'.format(p))

target_score = 25
max_rolls = 5
p = find_prob(target_score, max_rolls)
print('Probability:  {0:.5f}'.format(p))

```

    Probability:  0.00000
    Probability:  0.03241

### 偏ったランダム

テキストでは nonuniform random numbers とあるのだが、適当な翻訳がない、というかランダムが一様でない、というのはランダムの定義に反しているような気がするが、あとでフラクタルで使うというので、それなりの考え方なのだろう。

例えば、ということで、表 head の出る確率が裏 tail の出る確率の倍である偏ったコインを考える。 これをシミュレートする。

```
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(12,2))
ax = fig.add_subplot(xlim=(-4,4), ylim=(0, 1.0))

ax.arrow(-3.5, 0.5, 7, 0.0, head_width=0.0, head_length=0.0, linewidth=4, color='b')

x = [-3.5, 0.0, 3.5]
y = [0.5, 0.5, 0.5]
data_name = ["0", "1/2", "1"]
ax.plot(x, y, 'r|', ms="40")

ax.annotate("0",(-3.55,0.1), fontsize=20)
ax.annotate("1/2",(-0.16,0.1), fontsize=20)
ax.annotate("1",(3.4,0.1), fontsize=20)
ax.annotate("Heads", (-2.2,0.7), fontsize=20)
ax.annotate("Tails", (1.4,0.7), fontsize=20)

ax.set_axis_off()
plt.show()
```

```
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(12,2))
ax = fig.add_subplot(xlim=(-4,4), ylim=(0, 1.0))

ax.arrow(-3.5, 0.5, 7, 0.0, head_width=0.0, head_length=0.0, linewidth=4, color='b')

x = [-3.5, 1.11, 3.5]
y = [0.5, 0.5, 0.5]
ax.plot(x, y, 'r|', ms="40")

ax.annotate("0",(-3.55,0.1), fontsize=20)
ax.annotate("2/3",(0.95,0.1), fontsize=20)
ax.annotate("1",(3.4,0.1), fontsize=20)
ax.annotate("Heads", (-1.7,0.7), fontsize=20)
ax.annotate("Tails", (1.8,0.7), fontsize=20)

ax.set_axis_off()
plt.show()
```

```
import random

def toss():
    # 0 -> Heads, 1-> Tails
        if random.random() < 2/3:
            return 0
        else:
            return 1

```

次に架空の ATM を考え、次のような確率で紙幣 $5, $10, $20, $50 のドル札が発行されるとする。

```
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(12,2))
ax = fig.add_subplot(xlim=(-4,4), ylim=(0, 1.0))

ax.arrow(-3.5, 0.5, 7, 0.0, head_width=0.0, head_length=0.0, linewidth=4, color='b')

x = [-3.5,-2.3, -1.11, 1.11, 3.5]
y = [0.5, 0.5, 0.5,0.5,0.5]
ax.plot(x, y, 'r|', ms="40")

ax.annotate("0",(-3.55,0.1), fontsize=20)
ax.annotate("1/6",(-2.44,0.1), fontsize=20)
ax.annotate("1/3",(-1.33,0.1), fontsize=20)
ax.annotate("2/3",(0.95,0.1), fontsize=20)
ax.annotate("1",(3.4,0.1), fontsize=20)

ax.annotate("$5", (-3.0,0.7), fontsize=20)
ax.annotate("$10", (-2.0,0.7), fontsize=20)
ax.annotate("$20", (-0.3,0.7), fontsize=20)
ax.annotate("$50", (1.85,0.7), fontsize=20)

ax.set_axis_off()
plt.show()
```

$5ドル札と$10ドル札の確率は 1/6、$20ドル札と$50ドル札の確率は 1/3 になる。

```
from sympy import *
import random

def get_index(probability):
    c_probability = 0
    sum_probability = []
    for p in probability:
        c_probability += p
        sum_probability.append(c_probability)
    r = random.random()
    for index, sp in enumerate(sum_probability):
        if r <= sp:
            return index
    return len(probability) - 1

def dispense():
    dollar_bills = [5, 10, 20, 50]
    probability = [1/6, 1/6, 1/3, 2/3]
    bill_index = get_index(probability)
    return dollar_bills[bill_index]

print (dispense())
print (dispense())
print (dispense())
print (dispense())
print (dispense())
print (dispense())
print (dispense())
print (dispense())

```

    50
    5
    20
    20
    10
    50
    20
    20

# ベン図 Venn diageram

課題 5-1

```
from matplotlib_venn import venn2
import matplotlib.pyplot as plt
from sympy import *

def draw_venn(sets):
    venn2(subsets=sets)
    plt.show()

s1 = FiniteSet(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)
s2 = FiniteSet(2, 3, 5, 7, 11, 13, 17, 19)

draw_venn([s1,s2])
```

```
from matplotlib_venn import venn2
import matplotlib.pyplot as plt
from sympy import *

A = FiniteSet(1, 2)
B = FiniteSet(2, 3, 4)

venn2(subsets=(A,B))
plt.show()
print()
venn2(subsets=(15,10,5), set_labels=('X','Y'))
plt.show()
```

```
venn2(subsets=(s1,s2), set_labels=('s1', 's2'))
plt.show()
```

ある高校でフットボールをやるかどうかのアンケートを取った結果、次のようなデータになった。これをベン図で表す。

StudentID,Football,Others
1,1,0
2,1,1
3,0,1
4,1,1
5,1,0
6,1,0
7,1,1
8,0,1
9,1,1
10,0,1
11,1,1
12,1,0

```
from matplotlib_venn import venn2
import matplotlib.pyplot as plt
from sympy import *

def draw_venn(sets):
    venn2(subsets=sets,set_labels=('Football', 'Others'))
    plt.show()

def read_data(data):
    football = []
    others = []
    for row in data.split('\n'):
        if row.split(',')[1] == '1':
            football.append(row[0])
        if row.split(',')[2] == '1':
            others.append(row[0])
    return football, others

data = '''1,1,0
2,1,1
3,0,1
4,1,1
5,1,0
6,1,0
7,1,1
8,0,1
9,1,1
10,0,1
11,1,1
12, 1, 0 '''

l1, l2 = read_data(data)
s1 = FiniteSet(*l1)
s2 = FiniteSet(*l2)

draw_venn([s1, s2])

```

### 大数の法則 law of large numbers
課題 5-2

確率論において、$X = 1$ は事象 $1$ を表し、 $P(X=1)$ は $1$ が出る確率を表す。 ランダム変数には2種類あり、離散変数 discrete と連続変数 continuous があり、このテキストでいままであつかって来たのは離散の方である。

離散変数における期待値 $E$ は平均 (average または mean) と同じであり、以下の式で計算できる。

$$
E = x_1P(x_1)+x_2P(x_2) + x_3P(x_3) + \dots + x_nP(x_n)
$$

```latex
%%latex
\displaystyle

E = x_1P(x_1)+x_2P(x_2) + x_3P(x_3) + \dots + x_nP(x_n)

```

\displaystyle

E = x_1P(x_1)+x_2P(x_2) + x_3P(x_3) + \dots + x_nP(x_n)

したがってサイコロの期待値は次のようになる。

```
e = 1*(1/6) + 2*(1/6) + 3*(1/6) + 4*(1/6) + 5*(1/6) + 6*(1/6)
e
```

    3.5

大数の法則 law of large numbers により、試行を繰り返すと平均は期待値に収束する。

```
import random

def roll(num_trials):
    rolls = []
    for t in range(num_trials):
        rolls.append(random.randint(1, 6))
    return sum(rolls)/num_trials

expected_value = 3.5
print('Expected value: {0}'.format(expected_value))

for trial in [100, 1000, 10000, 100000, 500000]:
    avg = roll(trial)
    print('Trials: {0} Trial average {1}'.format(trial, avg))
```

    Expected value: 3.5
    Trials: 100 Trial average 3.17
    Trials: 1000 Trial average 3.538
    Trials: 10000 Trial average 3.5157
    Trials: 100000 Trial average 3.4929
    Trials: 500000 Trial average 3.498646

### 何回で破産するか
課題 5-3

コイントスで表が出れば、$1 ドルをもらい、裏が出れば $1.5 ドル失うゲームとする。 金額を指定して破産するまでトスを繰り返すプログラムを作る。

```
import random
def roll(num_trials):
    rolls = []
    for t in range(num_trials):
        rolls.append(random.randint(1, 6))
    return sum(rolls)/num_trials

expected_value = 3.5

print('Expected value: {0}'.format(expected_value))

for trial in [100, 1000, 10000, 100000, 500000]:
    avg = roll(trial)
    print('Trials: {0} Trial average {1}'.format(trial, avg))
```

    Expected value: 3.5
    Trials: 100 Trial average 3.49
    Trials: 1000 Trial average 3.517
    Trials: 10000 Trial average 3.5014
    Trials: 100000 Trial average 3.50256
    Trials: 500000 Trial average 3.497212

### トランプのカードをシャフルする
課題 5-4

トランプのカードを 1 から 52 までの数字で表し、シャフルした結果を次のような数字のリストで返すプログラムを作る。

[3, 9, 21, 50, 32, 4, 20, 52, 7, 13, 41, 25, 49, 36, 23, 45, 1, 22, 40, 19, 2, 35, 28, 30, 39, 44, 29, 38, 48, 16, 15, 18, 46, 31, 14, 33, 10, 6, 24, 5, 43, 47, 11, 34, 37, 27, 8, 17, 51, 12, 42, 26]

```
import random
x = [1,2,3,4]
random.shuffle(x)
x
```

    [2, 4, 3, 1]

数字ではわかりにくいので、Card クラスを作成して、スペードの10とかで表示する。

```
import random

class Card:
    def __init__ (self, suit, rank):
        self.suit = suit
        self.rank = rank

card1 = Card('clubs', 'ace')
card2 = Card('spades', '10')
card3 = Card('clubs', '6')
card4 = Card('spades', 'jack')
card5 = Card('spades', '9')

cards = [card1, card2, card3, card4, card5]
random.shuffle(cards)

for card in cards:
    print('{0} of {1}'.format(card.rank, card.suit))
```

    10 of spades
    ace of clubs
    jack of spades
    9 of spades
    6 of clubs

### 円の面積 モンテカルロ法
課題 5-5

辺の長さが $2r$ の正方形に内接する半径 $r$ の円がある。ダーツを投げて円の中に入ったものを $N$、円の外に当たったものを $M$として次の分数を計算する。

$$
f = \frac{N}{N+M}
$$

正方形の面積を $A$ とすると、$f \times A$ はほぼ円の面積になる。

ダーツを投げる回数を $10^3, 10^5, 10^6$ としたときの値と理論値 $\pi r^2$ とを比較する。

```
import math
import random

def estimate(radius, total_points):
    center = (radius, radius)
    in_circle = 0
    for i in range(total_points):
        x = random.uniform(0, 2*radius)
        y = random.uniform(0, 2*radius)
        p = (x, y)
        # distance of the point created from circle's center
        d = math.sqrt((p[0]-center[0])**2 + (p[1]-center[1])**2)
        if d <= radius:
            in_circle += 1
    area_of_square = (2*radius)**2
    return (in_circle/total_points)*area_of_square

radius = float('2')
print ('Radius: {}'.format(radius))
area_of_circle = math.pi*radius**2
for points in [10**3, 10**5, 10**6]:
    print('Area: {0}, Estimated ({1}): {2}'.format(area_of_circle, points, estimate(radius, points)))
```

    Radius: 2.0
    Area: 12.566370614359172, Estimated (1000): 12.784
    Area: 12.566370614359172, Estimated (100000): 12.53536
    Area: 12.566370614359172, Estimated (1000000): 12.5688

このプログラムには random.uniform(a, b) が使える。この関数は $a$ と $b$ の間のランダムな値を返す。 今回の場合、$a = 0, \, b = 2r$ である。

以上から逆に$pi$ の値を概算できる。正方形の面積は $4 r^2$ で、内接円の面積は $\pi r^2$ だから、その比率 $f$ は

$$
f = \frac{\pi r^2}{4 r^2} = \frac{N}{N + M}
$$
よって
$$
r \approx 4 \frac{N}{N+M}
$$

ダーツを投げる回数を十分大きく取って、$\pi$ が 3.14 に近い数字であることを確認する。

```
import math
import random

def estimate(total_points):
    radius = 1
    center = (radius, radius)
    in_circle = 0
    for i in range(total_points):
        x = random.uniform(0, 2*radius)
        y = random.uniform(0, 2*radius)
        p = (x, y)
        # distance from circle's center
        d = math.sqrt((p[0]-center[0])**2 + (p[1]-center[1])**2)
        if d <= radius:
            in_circle += 1
    return (in_circle/total_points)*4

for points in [10**3, 10**5, 10**6]:
    print('Known value: {0}, Estimated ({1}): {2}'.format(math.pi, points, estimate(points)))
```

    Known value: 3.141592653589793, Estimated (1000): 3.076
    Known value: 3.141592653589793, Estimated (100000): 3.13692
    Known value: 3.141592653589793, Estimated (1000000): 3.143868

# p. 148

以上で 4章まで終わった。

5章 図形とフラクタル Drawing Geometric Shapes and Fractals
6章 微積分 Solving Calculus Problems

は doingmath02.ipynb にする。


# Multiple Regression Analysis: OLS Asymptotics

So other than the finite sample properties in the previous chapters, we also need to know the ***asymptotic  properties*** or ***large sample properties*** of estimators and test statistics. And fortunately, under the assumptions we have made, OLS has satisfactory large sample  properties.

$Review\DeclareMathOperator*{\argmin}{argmin}
\DeclareMathOperator*{\argmax}{argmax}
\DeclareMathOperator*{\plim}{plim}
\newcommand{\using}[1]{\stackrel{\mathrm{#1}}{=}}
\newcommand{\ffrac}{\displaystyle \frac}
\newcommand{\space}{\text{ }}
\newcommand{\bspace}{\;\;\;\;}
\newcommand{\QQQ}{\boxed{?\:}}
\newcommand{\void}{\left.\right.}
\newcommand{\CB}[1]{\left\{ #1 \right\}}
\newcommand{\SB}[1]{\left[ #1 \right]}
\newcommand{\P}[1]{\left( #1 \right)}
\newcommand{\abs}[1]{\left| #1 \right|}
\newcommand{\norm}[1]{\left\| #1 \right\|}
\newcommand{\dd}{\mathrm{d}}
\newcommand{\Tran}[1]{{#1}^{\mathrm{T}}}
\newcommand{\d}[1]{\displaystyle{#1}}
\newcommand{\RR}{\mathbb{R}}
\newcommand{\EE}{\mathbb{E}}
\newcommand{\NN}{\mathbb{N}}
\newcommand{\ZZ}{\mathbb{Z}}
\newcommand{\QQ}{\mathbb{Q}}
\newcommand{\AcA}{\mathscr{A}}
\newcommand{\FcF}{\mathscr{F}}
\newcommand{\Exp}{\mathrm{E}}
\newcommand{\Var}[2][\,\!]{\mathrm{Var}_{#1}\left[#2\right]}
\newcommand{\Cov}[2][\,\!]{\mathrm{Cov}_{#1}\left(#2\right)}
\newcommand{\Corr}[2][\,\!]{\mathrm{Corr}_{#1}\left(#2\right)}
\newcommand{\I}[1]{\mathrm{I}\left( #1 \right)}
\newcommand{\N}[1]{\mathrm{N} \left( #1 \right)}
\newcommand{\ow}{\text{otherwise}}$

1. Expected values unbiasedness: $\text{MLR}.1 \sim \text{MLR}.4$
2. Variance formulas: $\text{MLR}.1 \sim \text{MLR}.5$
3. Gauss-Markov Theorem: $\text{MLR}.1 \sim \text{MLR}.5$
4. Exact sampling distributions/tests: $\text{MLR}.1 \sim \text{MLR}.6$

## Consistency

In practise, time series data regressions will fail the unbiasedness, only **consistency** remains.

$Def$

>Let $W_n$ be an estimator of $\theta$ based on a sample $Y_1,Y_2,\dots,Y_n$ of size $n$. Then, $W_n$ is a consistent estimator of $u$ if for every $\varepsilon > 0$,
>
>$$P\CB{\abs{W_n - \theta} > \varepsilon} \to 0 \text{ as } n \to \infty  $$
>
>Or alternatively, for arbitrary $\epsilon > 0$ and $n \to \infty$, we have $P\CB{\abs{W_n - \theta}< \epsilon} \to 1$

We can also write this as $\text{plim}\P{W_n} = \theta$

$Remark$

>In our real life we don't have infinite samples thus this property involves a thought experiment about what would happen as the sample size gets *large*.

$Theorem.1$

Under assumptions $MLR.1$ through $MLR.4$, the OLS estimator $\hat\beta_j$ is consistent for $\beta_j$, for all $j = 0,1,\dots,k$ meaning that $\plim\P{\hat\beta_j} = \beta_j$.

$Proof$

>$$
\hat\beta_1 = \ffrac{\d{\sum_{i=1}^{n} \P{x_{i1} - \bar{x}_1} y_i}} {\d{\sum_{i=1}^{n} \P{x_{i1} - \bar{x}_1}^2}}
\\[0.6em]$$
>
>since $y_i = \beta_0 + \beta_1 x_1 + u_i$

>$$\begin{align}
\hat\beta_1&= \beta_1 + \ffrac{\d{\sum_{i=1}^{n} \P{x_{i1} - \bar{x}_1} u_i}} {\d{\sum_{i=1}^{n} \P{x_{i1} - \bar{x}_1}^2}}\\
&= \beta_1 + \ffrac{\d{\ffrac{1} {n}\sum_{i=1}^{n} \P{x_{i1} - \bar{x}_1} u_i}} {\d{\ffrac{1} {n}\sum_{i=1}^{n} \P{x_{i1} - \bar{x}_1}^2}} \\[0.5em]
\end{align}\\[0.6em]$$
>
> by **law of large number**
>
>$$\begin{align}
\plim\P{\hat\beta_1}&= \beta_1 + \ffrac{\Cov{x_1,u}} {\Var{x_1}}\\
&= \beta_1 + \ffrac{0} {\Var{x_1}} = \beta_1
\end{align}$$
***

$Assumption.4'$ $MLR.4'$ **Zero Mean and Zero Correlation**

$\Exp\SB{u} = 0$ and $\Cov{x_j, u} = 0$, for $j = 1,2,\dots,k$

$Remark$

>The original one is the assumption of **Zero conditional mean** that is $\Exp\SB{u \mid x_1,x_2,\dots,x_k} = 0$. $MLR.4$ is stronger than $MLR.4'$.
>
>Also $MLR.4'$ cannot guarantee the unbiasdness but consistency only.

### Deriving the inconsistency in OLS

> If the error $u$ is correlated with any of the independent variables $x_j$, then OLS is biased and inconsistent.

In the simple regression case, the ***inconsistency*** in $\hat\beta_1$ (or loosely called the ***asymptotic bias***) is $\plim\P{\hat\beta_1} - \hat\beta_1 = \ffrac{\Cov{x_1,u}} {\Var{x_1}}$. And it's positive if $x_1$ and $u$ are positively correlated, negative otherwise.

And this formula will help us find the asymptotic analog of the omitted variable bias (ref **Chap_03.3**). Suppose the true model is $y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + v$ and the OLS estimators with **first four Gauss-Markov assumptions** is $\hat\beta_0$, $\hat\beta_1$, and $\hat\beta_2$, and obviously these three are **consistent**. Then omit $x_2$ and do the simple regression of $y$ on $x_1$ with model $y = \beta_0 + \beta_1 x_1 + u$, then we have $u = \beta_2 x_2 + v$. Let $\tilde\beta_1$ denote the simple regression slope estimator. Then

$$\plim \tilde\beta_1 = \beta_1 + \beta_2 \ffrac{\Cov{x_1,x_2}} {\Var{x_1}} = \beta_1 + \beta_2 \delta_1$$

If $x_1$ and $x_2$ are *uncorrelated* (in the population), then $\delta_1 = 0$, and $\tilde\beta_1$ is a consistent estimator of $\beta_1$ (although not necessarily unbiased). However, if $x_2$ has a positive partial effect on $y$, so that $\beta_2 > 0$ and $\Cov{x_1,x_2}>0$, $\delta_1> 0$. Then the inconsistency in $\tilde\beta_1$ is positive.

## Asymptotic Normality and Large Sample Inference

>$\text{MLR}.6 \iff $ the distribution of $y$ given $x_1,x_2,\dots,x_k$, which is just $u$ then, is normal. Normality has nothing to do with the unbiasedness however to do statistical inference, we need that. And fortunately, by **central limit theorem**, even though the $y_i$ are not from a normal distribution, the OLS estimator still satisfy ***asymptotic normality***, which means they are approximately normally distributed in
large enough sample sizes.

$Theorem.2$ Asymptotic Normality of OLS

Under the Gauss-Markov Assumptions, $\text{MLR}.1$ through $\text{MLR}.5$,

- $\sqrt{n}\P{\hat\beta_j - \beta_j} \newcommand{\asim}{\overset{\text{a}}{\sim}}\asim \N{0, \ffrac{\sigma^2} {a_j^2}}$, where $\ffrac{\sigma^2} {a_j^2}$ is the ***asymptotic variance*** of $\sqrt{n}\P{\hat\beta_j - \beta_j} $; and for the slope coefficients, $a_j^2 = \plim \P{\ffrac{1} {n} \sum_{i=1}^{n} \hat r_{ij}^{2}}$ where the $r_{ij}$ are the residuals from regressing $x_j$ on the other independent variables. We say that $\hat\beta_j$ is *asymptotically normally distributed*;
- $\hat\sigma^2$ is a consistent estimator of $\sigma^2 = \Var{u}$;
- For each $j$, $\ffrac{\hat\beta_j - \beta_j} {\text{sd}\P{\hat\beta_j}}\asim \N{0,1}$; $\ffrac{\hat\beta_j - \beta_j} {\text{se}\P{\hat\beta_j}}\asim \N{0,1}$ where $\text{se}\P{\hat\beta_j} = \sqrt{\widehat{\Var{\hat\beta_j}}} = \sqrt{\ffrac{\hat\sigma^2} {\text{SST}_j \P{1-R^2_j}}}$ is the usual OLS standard error.

$Remark$

>Here we dropped the assumption $\text{MLR}.6$ and the only one restriction remained is that the error has finite variance.
>
>Also note that the population distribution of the error term, $u$, is immutable and has nothing to do with the sample size. Thie theorem only says that regardless of the population distribution of $u$, the OLS estimators, when properly standardized, have approximate standard normal distributions.
>
>$\text{sd}\P{\hat\beta_j}$ depends on $\sigma$ and is not observable, while $\text{se}\P{\hat\beta_j}$ depends on $\hat\sigma$ and can be computed. In the previous chapter we've already seen that: under **CLM**, $\text{MLR}.1$ through $\text{MLR}.6$, we have $\ffrac{\hat\beta_j - \beta_j} {\text{sd}\P{\hat\beta_j}}\sim \N{0,1}$ and $\ffrac{\hat\beta_j - \beta_j} {\text{se}\P{\hat\beta_j}}\sim t_{n-k-1} = t_{df}$.
>
>In large samples, the $t$-distribution is close to the $\N{0,1}$ distribution and thus $t$ test are valid in large samples *without* $\text{MLR}.6$. But still we need $\text{MLR}.1$ to $\text{MLR}.5$.

Now from $\hat\sigma^2$ is a consistent estimator of $\sigma^2$, let's have a closer look of ${\widehat{\Var{\hat\beta_j}}} = {\ffrac{\hat\sigma^2} {\text{SST}_j \P{1-R^2_j}}}$, where $\text{SST}_j$ is the total sum of squares of $x_j$ in the sample, $R^2_j$ is the $R$-squared from regressing $x_j$ on all of the other independent variables. As the **sample size** *grows*, $\hat\sigma^2$ converges in probability to the constant $\sigma^2$. Further, $R^2_j$ approaches a number strictly between $0$ and $1$. Then about the rate, the sample variance of $x_j$ is $\ffrac{\text{SST}_j} {n}$, so that it converges to $\Var{x_j}$ as the sample size grows, meaning that we have: $\text{SST}_j \approx n\sigma_j^2$, where $\sigma_j^2$ is the population variance of $x_j$. Combining all these facts:

$\bspace \widehat{\Var{\hat\beta_j}}$ shrinks to zero at the rate of $1/n$, $\text{se}\P{\hat\beta_j}$ also shrinks to zero at the rate of $\sqrt{1/n}$ . And the larger sample, the better.

When $u$ is not normally distributed, $\sqrt{\widehat{\Var{\hat\beta_j}}} = \sqrt{\ffrac{\hat\sigma^2} {\text{SST}_j \P{1-R^2_j}}}$ is called the **asymptotic standard error** and $t$ statistics are called **asymptotic *$\textbf{t}$* statistics**. We also have **asymptotic confidence interval**.

### Other Large Sample Tests: The Lagrange Multiplier Statistic

The ***Lagrange multiplier (LM) statistic***. We first consider the model: $y = \beta_0 + \beta_1 x_1 + \cdots + \beta_k x_k + u$. The null hypothesis is $H_0:\beta_{k-q+1} = \beta_{k-q+2} = \cdots = \beta_k = 0$, the last $q$ parameters, putting $q$ exclusion restrictions on the model. The $LM$ statistic requires estimation of the restricted model only. Thus, assume that we have run the regression: $y = \tilde\beta_0 + \tilde\beta_1 x_1 + \cdots + \tilde\beta_{k-q} x_{k-q} + \tilde u$, where $\tilde\void$ indicates that the estimates are from the restricted model.

However it turns out that to get a usable test statistic, we must include *all* of the independent variables in the regression so that we run the regression of $\tilde u$ on $x_1, x_2,\dots,x_k$, that we call an ***auxiliary regression***, a regression that is used to compute a test statistic but whose coefficients are not of direct interest.

Then under the null hypothesis, the sample size $n$, multiplied by the usual $R$-squared from the auxiliary regression is distributed asymptotically as a $\chi^2$ $r.v.$ with $q$ degrees of freedom. Here's the overall procedure for testing the joint significance of a set of $q$ independent variables using this method.

***

Lagrange Multiplier Statistic for $q$ exclusion restrictions

1. Regress $y$ on the *restricted set* of independent variables, $x_1,\dots, x_{k-q}$, and save the residuals, $\tilde u$
2. Regress $\tilde u$ on *all* of the independent variables and obtain the $R$-squared, $R^2_u$. Just to distinguich from regress $y$ on them
3.  Compute **Lagrange multiplier statistic**: $LM = nR_u^2$
4.  Compare $LM$ to the appropriate critical value $c$, in a $\chi_q^2$ distribution; if $LM > c$ then the null hypothesis is *rejected*. Even better, obtain the $p$-value as the probability that a $\chi_q^2$ $r.v.$ exceeds the value of the test statistic. If the $p$-value is less than the desired significance level, then $H_0$ is rejected. If not, we fail to reject $H_0$. The rejection rule is essentially the same as for $F$ testing.

## Asymptotic Efficiency of OLS

In general, the $k$ regressor case, the class of consistent estimators is obtained by generalizing the OLS first order conditions:

$$\sum_{i=1}^n g_j\P{\mathbf{x}_i} \P{y_i - \tilde\beta_0 - \tilde\beta_1 x_{i1} - \cdots - \tilde\beta_k x_{ik}} = 0, \bspace j = 0,1,\dots,k$$

where $g_j\P{\mathbf{x}_i}$ denotes any function of all explanatory variables for observation $i$. And obviously $g_0\P{\mathbf{x}_i} = 1$ and $g_j\P{\mathbf{x}_j} = x_{ij}$ for $j=1,2,\dots,k$ are the conditions to obtain the OLS estimators.

Here's the theorem:

$Theorem.3$ Asymptotic Efficiency of OLS

Under the Gauss-Markov assumptions, let $\tilde\beta_j$ denote estimators that solve equations of the equation:

$$\sum_{i=1}^n g_j\P{\mathbf{x}_i} \P{y_i - \tilde\beta_0 - \tilde\beta_1 x_{i1} - \cdots - \tilde\beta_k x_{ik}} = 0, \bspace j = 0,1,\dots,k$$

and let $\hat\beta_j\newcommand{\Avar}[2][\,\!]{\mathrm{Avar}_{#1}\left[#2\right]}$ denote the OLS estimators. Then for $j=0,1,\dots,k$, the OLS estimators have the smallest asymptotic variances: $\Avar{\sqrt{n} \P{\hat\beta_j - \beta_j}} \leq \Avar{\sqrt{n} \P{\tilde\beta_j - \beta_j}}$

***