Python3エンジニア認定データ分析試験 対策

Python3エンジニア認定データ分析試験の学習内容をまとめてみた。

# Numpy
数値計算に特化したライブラリ。Python標準のリストに比べて多次元配列のデータを効率よく扱える。

### 1次元配列

入力
```
a = np.array([1,2,3])
print(a)
```

出力
```
[1 2 3]
```

入力
```
type(a)
```

出力
```
numpy.ndarray
```

※ type →オブジェクトの型を返す。変数aはndarray型であることが分かる。ndarrayは多次元配列を扱うデータ構造。

入力
```
a.shape
```

出力
```
(3,)
```

※ shape → 形状を表す。(行、列)の形で表示される。

### 2次元配列

```
b = np.array([[1,2,3],[4,5,6]])
b.shape
```

出力
```
(2,3)
```

### 変形(reshape)
次元の変換を行える。

入力
```
c1 = np.array([0,1,2,3,4,5,6])
c2 = c1.reshape((2,3))
print(c2)
```
出力
```
[[0 1 2]
 [3 4 5]]
```

要素の数が合わない場合エラーとなる。

入力
```
c1 = np.array([0,1,2,3,4,5,6])
c2 = c1.reshape((3,4))
print(c2)
```
出力
```
ValueError: cannot reshape array of size 7 into shape (3,4)
```

多次元配列を1次元配列に変換するrevel、flattenを実行
revelは参照、flattenはコピーを返す。

入力
```
c3 = c2.ravel()
print(c3)
```

出力
```
[ 0  1  2  3  4  5]
```



入力
```
c4 = c2.flatten()
print(c4)
```

出力
```
[ 0  1  2  3  4  5]
```

### データ型(dtype)
データ型を返す。

入力
```
print(a.dtype)
```

出力
```
int64
```

・明示的な型宣言

入力
```
d = np.array([1,2],dtype=np.int16)
print(d.dtype)
```

出力
```
int16
```


・型変換

入力

```
d =d.astype(np.float16)
print(d.dtype)
```

出力
```
float16
```

### インデックスとスライス

・インデックス

入力
```
print(a[0])
```
出力
```
1
```

・スライス

入力
```
print(a[1:])
```
出力
```
2,3
```

・負のインデックス
配列の末尾から数える

入力
```
print(a[-1])
```
出力
```
3
```

・2次元配列(インデックス)

入力
```
print(b[1,0])
```
出力
```
4
```

・2次元配列(スライス)

入力
```
print(b[:,2])
```
出力
```
[3 6]
```

入力
```
print(b[1,:])
```
出力
```
[4 5 6]
```

・値が飛んでいる場合

入力
```
print(b[:,[0,2]])
```
出力
```
[[1 3]
 [4 6]]
```

### 参照とコピー

#### 参照
1. 変数aをa1に代入

入力
```
a1 = a
print(a)
```
出力
```
[1 2 3]
```

2. a1の値を変更

入力
```
a1[1] = 5
print(a1)
```
出力
```
[1 5 3]
```

3. aの値を確認

入力
```
print(a)
```
出力
```
[1 5 3]
```

a1 = a という操作では、aを参照するオブジェクトとしてa1が生成される。よって、a1を変更するとaも変更される。

#### コピー

1. 変数aをa2にコピー

入力
```
a2 = a.copy()
print(a2)
```
出力
```
[1 5 3]
```

2. a2の値を変更

入力
```
a2[0] = 6
print(a2)
```
出力
```
[6 5 3]
```

3. aの値を確認

入力
```
print(a)
```
出力
```
[1 5 3]
```

a2を変更してもaはそのままの値。

### 数列を返す(arange)

・引数1つ
入力
```
print(np.arange(10))
```
出力
```
[0 1 2 3 4 5 6 7 8 9]
```

・引数2つ(1から11の手前までの数列を返す)
入力
```
print(np.arange(1,11))
```
出力
```
[1 2 3 4 5 6 7 8 9 10]
```

・引数3つ(1から11の手前まで2ずつ増加する数列を返す)

入力
```
print(np.arange(1,11,2))
```
出力
```
[1 3 5 7 9]
```

### 乱数
疑似乱数を発生させる。



#### 0〜1間のランダムの要素を持つ行列を作る

入力
```
rng = np.random.default_rng()
f = rng.random(3,2)
print(f)
```

出力
```
[[0.37454012 0.95071431]
 [0.73199394 0.59865848]
 [0.15601864 0.15599452]]
```

#### 整数をランダムで出力する

入力
```
rng = np.random.default_rng()
print(rng.integers(1,10))
```

出力
```
7
```

・第三引数にsizeを指定

入力
```
rng = np.random.default_rng()
print(rng.integers(1,10,size=(3,3)))
```

出力
```
[[4 7 2]
 [8 1 5]
 [3 9 6]]
```

#### 小数値をランダムで出力する

入力
```
rng = np.random.default_rng()
print(rng.uniform(0.0,5.0,size=(2,3)))
```

出力
```
[[2.37454012 4.95071431 1.73199394]
 [3.59865848 0.15601864 0.75599452]]
```

・第一引数と第二引数を省略した場合、0.0〜1.0の範囲となる

入力
```
rng = np.random.default_rng()
print(rng.uniform(size=(4,3)))
```

出力
```
[[0.37454012 0.95071431 0.73199394]
 [0.59865848 0.15601864 0.15599452]
 [0.05808361 0.86617615 0.60111501]
 [0.70807258 0.02058449 0.96990985]]
```

#### 正規分布に従った乱数を出力する

・平均0、分散1の分布で出力(standard_normal)

入力
```
rng = np.random.default_rng()
print(rng.standard_normal(size=(4,2))
```

出力
```
[[ 0.49671415 -0.1382643 ]
 [ 0.64768854  1.52302986]
 [-0.23415337 -0.23413696]
 [ 1.57921282  0.76743473]]
```

・平均、標準偏差、形状を指定し乱数を出力する

入力
```
rng = np.random.default_rng()
print(rng.normal(50,10,3))
```

出力
```
[48.67323456 52.14789234 45.98765432]
```

平均50、標準偏差10で3要素を出力。


### 同じ要素の数列を作る

入力
```
print(np.zeros(3))
```

出力
```
[0. 0. 0.]
```

・2次元配列

入力
```
print(np.ones(3,4))
```

出力
```
[[1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]]
```

### 単位行列
体格成分が全て1、それ以外の成分が0になる行列を作る。

入力
```
print(np.eye(3))
```

出力
```
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
```

### 指定値で埋める

入力
```
print(np.full(3,3.14))
```

出力
```
[3.14 3.14 3.14]
```

・2次元配列

入力
```
print(np.full((2,4),np.pi))
```

出力
```
[[3.14159265 3.14159265 3.14159265 3.14159265]
 [3.14159265 3.14159265 3.14159265 3.14159265]]
```

※ pi → 円周率を表す。


### 範囲指定で均等割りデータを作る

・0から1までを5等分する

入力
```
print(np.linspace(0,1,5))
```

出力
```
[0.   0.25 0.5  0.75 1.  ]
```

### 要素間の差分

入力
```
l = np.array([2,2,6,1,3])
print(np.diff(l))
```

出力
```
[0 4 -5 2]
```

### 連結

入力
```
print(np.concatenate([a,a1]))
```

出力
```
[1 5 3 1 5 3]
```

#### ２次元配列

入力
```
b1 = np.array([[10],[20]])
print(np.concatenate([b,b1],axis=1))
```

出力
```
[[ 1  2  3 10]
 [ 4  5  6 20]]
```

※ axis → 増やす列数を指定

・hstackで同様の結果

入力
```
b1 = np.array([[10],[20]])
print(np.hstack([b,b1]))
```

出力
```
[[ 1  2  3 10]
 [ 4  5  6 20]]
```

・行を増やす

入力
```
b2 = np.array([30,60,45])
b3 = np.vstack([b,b2])
print(b3)
```

出力
```
[[ 1  2  3]
 [ 4  5  6]
 [30 60 45]]
```

### 分割

入力
```
first, second = np.hsplit(b3, [2])
print(first)
print(second)
```

出力
```
[[ 1  2]
 [ 4  5]
 [30 60]]
[[ 3]
 [ 6]
 [45]]
```

・行方向に分割

入力
```
first1, second1 = np.vsplit(b3, [2])
print(first)
print(second)
```

出力
```
[[1 2 3]
 [4 5 6]]
[[30 60 45]]
```

### 転置
2次元配列の行と列を入れ替えること。

入力
```
print(b.T)
```

出力
```
[[1 4]
 [2 5]
 [3 6]]
```

### 次元追加

入力
```
print(a[np.newaxis,:])
```

出力
```
[[1 2 3]]
```

・列を追加

入力
```
print(a[:,np.newaxis])
```

出力
```
[[1]
 [2]
 [3]]
```

### グリッドデータの生成

入力
```
m = np.arange(0,4)
n = np.arange(4,7)
xx,yy = np.meshgrid(m,n)
print(xx)
print(yy)
```

出力
```
[[0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]]
[[4 4 4 4]
 [5 5 5 5]
 [6 6 6 6]]
```

## Numpyの各機能

以下、事前に定義しておく。

```
a = np.arange(3)
b = np.arange(-3,3).reshape((2,3))
c = np.arange(1,7).reshape((2,3))
d = np.arange(6).reshape((3,2))
e = np.linspace(-1,1,10)
print("a:",a)
print("b:",b)
print("c:",c)
print("d:",d)
print("e:",e)
```

出力
```
a: [0 1 2]
b: [[-3 -2 -1]
    [ 0  1  2]]
c: [[1 2 3]
    [4 5 6]]
d: [[0 1]
    [2 3]
    [4 5]]
e: [-1.         -0.77777778 -0.55555556 -0.33333333 -0.11111111  0.11111111
     0.33333333  0.55555556  0.77777778  1.        ]
```


### ユニバーサルファンクション

・各要素の絶対値を返す
入力
```
print(np.abs(b))
```

出力
```
[[3 2 1]
 [0 1 2]]
```

・各要素の正弦を返す
入力
```
print(np.sin(e))
```

出力
```
[-0.84147098 -0.70169788 -0.52741539 -0.3271947  -0.11088263  0.11088263
  0.3271947   0.52741539  0.70169788  0.84147098]
```

・各要素の余弦を返す
入力
```
print(np.cos(e))
```

出力
```
[0.54030231 0.71247462 0.84960756 0.94511052 0.99383351 0.99383351
 0.94511052 0.84960756 0.71247462 0.54030231]
```

・各要素のlogを返す
入力
```
print(np.log(a))
```

出力
```
[-inf  0.          0.69314718]
```

※ -inf →マイナス無限大を表す。

・ネイビア数の冪乗を表す
入力
```
print(np.exp(a))
```

出力
```
[1.         2.71828183 7.3890561 ]
```

### ブロードキャスト

入力
```
print(a+10)
```

出力
```
[10 11 12]
```

・配列同士の和

入力
```
print(a+b)
```

出力
```
[[-3 -1  1]
 [ 0  2  4]]
```

・各要素を自身の要素の平均値から引いた配列

入力
```
print(c - np.mean(c))
```

出力
```
[[-2.5 -1.5 -0.5]
 [ 0.5  1.5  2.5]]
```

・掛け算

入力
```
print(b*2)
```

出力
```
[[-6 -4 -2]
 [ 0  2  4]]
```

### 配列の掛け算

入力
```
print(np.dot(b,a))
```

出力
```
[-4  5]
```

・ 掛ける順番を逆にするとエラー

入力
```
print(np.dot(a,b))
```

出力
```
ValueError: shapes (3,) and (2,3) not aligned: 3 (dim 0) != 2 (dim 0)
```

・ 2次元配列同士の積

入力
```
print(np.dot(b,d))
```

出力
```
[[ -8 -14]
 [ 10  13]]
```

・順序を逆にした場合

入力
```
print(np.dot(d,b))
```

出力
```
[[  0   1   2]
 [ -6  -1   4]
 [-12  -3   6]]
```

### 判定・真偽値

入力
```
print(a>1)
```

出力
```
[False False  True]
```

・Trueの数をカウント

入力
```
print(np.count_nonzero(b>0))
```

出力
```
2
```

※ count_nonzero → 0でない要素数を出力。Falseは0として扱われるため、Trueの数である2が出力される。

・ 要素の中にTrueが含まれているかを確認

入力
```
print(np.any(b>0))
```

出力
```
True
```

・全てがTrueかどうかを確認

入力
```
print(np.all(b>0))
```

出力
```
False
```

・条件に合致したものだけ出力

入力
```
print(b[b>0])
```

出力
```
[1 2]
```

・ 配列同士が同じ要素で構成されているかを確認

入力
```
print(np.allclose(b,c))
```

出力
```
False
```

・誤差を指定し、誤差の範囲内であればTrueを出力

入力
```
print(np.allclose(b,c,atol=10.0))
```

出力
```
True
```

# pandas
データ解析のためのライブラリ。
Numpyを基盤にシリーズとデータフレームというデータ型を提供。

### Series
一次元データ。

入力
```
import pandas as pd
ser = pd.series([10,20,30,40])
print(ser)
```

出力
```
0    10
1    20
2    30
3    40
dtype: int64
```

### DataFrame
2次元のデータ。

入力
```
df = pd.DataFrame([
[10,"a",True],
[20,"b",False],
[30,"c",False],
[40,"d",True]])
print(df)
```

出力
```
    0  1      2
0  10  a   True
1  20  b  False
2  30  c  False
3  40  d   True
```

・arangeを活用

入力
```
df = pd.DataFrame(np.arange(100).reshape((25,4)))
print(df.head())
print(df.tail())
```

出力
```
   0  1   2   3
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11
3 12 13  14  15
4 16 17  18  19
    0   1   2   3
20 80 81 82 83
21 84 85 86 87
22 88 89 90 91
23 92 93 94 95
24 96 97 98 99
```

※ head() → 先頭五行を出力
　 tail() → 末尾五行を出力。

### インデックス名、カラム名
行名、列名を指定できる。


入力
```
df = pd.DataFrame(np.arange(6).reshape((3,2)))
df.index = ["01","02","03"]
df.columns = ["A","B"]
print(df)
```

出力
```
    A  B
01  0  1
02  2  3
03  4  5
```
  
### データ抽出

入力
```
df = pd.DataFrame(np.arange(12).reshape((4,3)),
            columns = ["A","B","C"],
            index = ["1行目","2行目","3行目","4行目"])
print(df["A"])
```

出力
```
1行目    0
2行目    3
3行目    6
4行目    9
Name: A, dtype: int64
```

・ インデクサを使った抽出(loc)
loc(行名、列名)の形で指定する。

入力
```
print(df.loc[:,"A"])
```

出力
```
1行目    0
2行目    3
3行目    6
4行目    9
Name: A, dtype: int64
```

・ インデクサを使った抽出(iloc)
iloc(行番号、列番号)の形で指定。

入力
```
print(df.iloc[:,0])
```

出力
```
1行目    0
2行目    3
3行目    6
4行目    9
Name: A, dtype: int64
```


## 時系列データ

### 1ヶ月分のデータを作る

入力
```
dates = pd.date_range(start="2025-04-01",
                      end="2025-04-30")
print(dates)
```

出力
```
DatetimeIndex(['2025-04-01', '2025-04-02', '2025-04-03', '2025-04-04',
               '2025-04-05', '2025-04-06', '2025-04-07', '2025-04-08',
               '2025-04-09', '2025-04-10', '2025-04-11', '2025-04-12',
               '2025-04-13', '2025-04-14', '2025-04-15', '2025-04-16',
               '2025-04-17', '2025-04-18', '2025-04-19', '2025-04-20',
               '2025-04-21', '2025-04-22', '2025-04-23', '2025-04-24',
               '2025-04-25', '2025-04-26', '2025-04-27', '2025-04-28',
               '2025-04-29', '2025-04-30'],
              dtype='datetime64[ns]', freq='D')
```

・日付をインデックスにする

入力
```
rng = np.random.default_rng(123)
df = pd.DataFrame(rng.integers(1,31,size=30),
                  index=dates,
                  columns=["乱数値"])
print(df.head())
```

出力
```
            乱数値
2025-04-01     6
2025-04-02     3
2025-04-03     7
2025-04-04     4
2025-04-05     6
```
    

# Matplotlib

2次元のグラフを描画するためのライブラリ。


### pyplotインタフェース

入力
```
import matplotlib.pyplot as plt

x = [1,2,3]
y = [2,4,9]

plt.plot(x,y)
plt.title('pyplot interface')

plt.show()

```

出力

![スクリーンショット 2025-05-18 15.24.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/60824325-282e-4854-8017-e4e9d52d8847.png)


### オブジェクト指向インタフェース
描画オブジェクトにサブプロットを追加し、サブプロットに対しグラフを描画する。


入力
```

x = [1,2,3]
y = [2,4,9]

fig,ax = plt.subplots()

ax.plot(x,y)
ax.set_title('object-oriented interface')

plt.show()

```

出力

![スクリーンショット 2025-05-18 15.28.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/0fc6eb8c-b1f1-406a-8fa2-636a844bf54b.png)


・2つのサブプロットを配置

入力
```
flg,axes = plt.subplots(2)
plt.show()
```

出力

![スクリーンショット 2025-05-18 15.35.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/7c92eabf-a33e-4636-b97e-5aad54fff8e3.png)

### 軸ラベル
グラフの軸にラベルを指定できる。

入力
```
flg,ax = plt.subplots()

ax.set_xlabel('x label')
ax.set_ylabel('y label')
plt.show()
```

出力

![スクリーンショット 2025-05-18 15.37.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/3f2aa17e-f917-4faa-bad4-2b92e259bbb5.png)


### 反例

入力
```
flg,ax = plt.subplots()

ax.plot([1,2,3],[2,4,9],label='legend label')
ax.legend(loc='best')

plt.show()
```

出力
![スクリーンショット 2025-05-18 15.40.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/cc0ee772-5a18-4848-93df-1742c2da2c74.png)

※ loc='best' → データとの重なりが最小な位置に反例を出力。


### ファイル出力

入力
```
flg,ax = plt.subplots()
ax.set_title('subplot title')
flg.savefig('sample-figure.png')

```

### 棒グラフ

入力
```
flg,ax = plt.subplots()

x = [1,2,3]
y = [10,2,3]
ax.bar(x,y)

plt.show()
```

出力
![スクリーンショット 2025-05-18 15.48.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/720fe79e-94af-4928-aab4-54d963b45f54.png)

・横向きの棒グラフ

入力
```
flg,ax = plt.subplots()

x = [1,2,3]
y = [10,2,3]
ax.barh(x,y)

plt.show()
```

出力
![スクリーンショット 2025-05-18 15.54.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/b8249a46-dde0-4ae8-ac46-331ed3e60ecd.png)


### 散布図

入力
```
flg,ax = plt.subplots()

rng = np.random.default_rng(123)
x = rng.random(50)
y = rng.random(50)

ax.scatter(x,y)

plt.show()
```

出力

![スクリーンショット 2025-05-18 16.33.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/a884c405-9487-458b-b7be-4e4a65133813.png)

### ヒストグラム

入力
```
rng = np.random.default_rng(123)
mu = 100
sigma = 15
x = rng.normal(mu,sigma,1000)
flg,ax = plt.subplots()

n,bins,patches = ax.hist(x)

plt.show()
```

出力
![スクリーンショット 2025-05-18 16.36.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/1565fc70-9552-4e87-9fe6-ab5c273773a4.png)

・横向きのヒストグラム

入力
```
flg,ax = plt.subplots()

ax.hist(x,orientation='horizontal')

plt.show()
```

出力

![スクリーンショット 2025-05-18 16.39.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/56e850a1-83a7-4baf-a223-1634c352588b.png)


###  箱ひげ図

入力
```
rng = np.random.default_rng(123)
x0 = rng.normal(0,10,500)
x1 = rng.normal(0,15,500)
x2 = rng.normal(0,20,500)

flg,ax = plt.subplots()
labels = ['x0','x1','x2']
ax.boxplot((x0,x1,x2),labels=labels)

plt.show()
```

出力
![スクリーンショット 2025-05-18 16.44.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/24b00e6d-b6bc-4277-9482-808708153849.png)

・横向きの箱ひげ図

入力
```
flg,ax = plt.subplots()
labels = ['x0','x1','x2']
ax.boxplot((x0,x1,x2),labels=labels,vert=False)

plt.show()
```

出力

![スクリーンショット 2025-05-18 16.46.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/bc135f51-c72f-48fb-a028-ee8d1f758f81.png)


### 円グラフ

入力
```
labels = ['spam','ham','egg']
x = [10,3,1]

flg,ax = plt.subplots()

ax.pie(x,labels=labels)

plt.show()
```

出力
![スクリーンショット 2025-05-18 16.50.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/26466bda-1aea-46be-91b7-01367bc7266c.png)

・12時の位置から時計回りに出力

入力
```
flg,ax = plt.subplots()

ax.pie(x,labels=labels,startangle=90,counterclock=False)

plt.show()
```

出力
![スクリーンショット 2025-05-18 16.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/d3e3afb7-9f14-4a4a-a67a-b631138d8e22.png)


### 複数のグラフを組み合わせる

入力
```
flg,ax = plt.subplots()

x1 = [1,2,3]
y1 = [5,2,3]
x2 = [1,2,3,4]
y2 = [8,5,4,6]
ax.bar(x1,y1,label='y1')
ax.plot(x2,y2,label='y2')
ax.legend()

plt.show()
```

出力
![スクリーンショット 2025-05-18 17.09.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/5be9c5cb-714f-491a-aba0-8ba35909ce38.png)

### テキスト描画

入力
```
flg,ax = plt.subplots()

ax.text(0.2,0.4,'Text',size=20)

plt.show()
```

出力
![スクリーンショット 2025-05-18 17.13.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/47efc2f6-9bdd-49a0-b276-66b18a5b2373.png)


### pandasのオブジェクトからグラフ描画


入力
```
matplotlib.style.use('ggplot')

df = pd.DataFrame({'A':[1,2,3],'B':[3,1,2]})
df.plot()

plt.show()
```

出力

![スクリーンショット 2025-05-18 17.22.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/5a2fca52-d314-452c-a587-89f19b68e86b.png)


# scikt-learn
データマイニングやデータ解析用のライブラリ。

### 欠損値の補完

入力
```
from sklearn.impute import SimpleImputer

df = pd.DataFrame(
{'A':[1,np.nan,3,4,5],
 'B':[6,7,8,np.nan,10],
 'C':[11,12,13,14,15]
 }
)

imp = SimpleImputer(strategy='mean')
imp.fit(df)
print(imp.transform(df))

```

出力
```
[[ 1.    6.   11.  ]
 [ 3.25  7.   12.  ]
 [ 3.    8.   13.  ]
 [ 4.    7.75 14.  ]
 [ 5.   10.   15.  ]]
```

### カテゴリ変数のエンコーディング

入力
```
from sklearn.preprocessing import LabelEncoder

df = pd.DataFrame(
{'A':[1,2,3,4,5],
 'B':['a','b','a','b','c']
 }
)

le = LabelEncoder()

le.fit(df.loc[:,'B'])
print(le.transform(df.loc[:,'B']))
```

出力
```
[0 1 0 1 2]
```

・One-hotエンコーディング
カテゴリ変数に対して行う符号化処理。

入力
```
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
from sklearn.compose import ColumnTransformer 
わ

df_ohe = df.copy()

le = LabelEncoder()

df_ohe.loc[:,'B'] = le.fit_transform(df_ohe.loc[:,'B'])

ohe = ColumnTransformer([("OneHotEncoder",
                           OneHotEncoder(),[1])],
                           remainder='passthrough')
                           
df_ohe = ohe.fit_transform(df_ohe)
print(df_ohe)
```

出力
```
[[1. 0. 0. 1.]
 [0. 1. 0. 2.]
 [1. 0. 0. 3.]
 [0. 1. 0. 4.]
 [0. 0. 1. 5.]]
```

### 特徴量の正規化
特徴量の大きさを揃える。

・分散正規化
特徴量の平均が0、標準偏差が1となるように特徴量を変換する処理。

入力
```
from sklearn.preprocessing import StandardScaler

df = pd.DataFrame(
     {
        'A': [1,2,3,4,5],
        'B': [100,200,400,500,800]
     }
)     
stdsc = StandardScaler()

stdsc.fit(df)
print(stdsc.transform(df))

```

出力
```
[[-1.41421356 -1.22474487]
 [-0.70710678 -0.81649658]
 [ 0.          0.        ]
 [ 0.70710678  0.40824829]
 [ 1.41421356  1.63299316]]
 ```

 ・最小最大正規化
特徴量の最小値が0、最大値が1を取るように正規化する。

入力
```
from sklearn.preprocessing import MinMaxSacler

df = pd.DataFrame(
     {
        'A': [1,2,3,4,5],
        'B': [100,200,400,500,800]
     }
)     
mmsc = MinMaxSacler()

mmsc.fit(df)
print(mmsc.transform(df))

```

出力
```
[[0.         0.        ]
 [0.25       0.14285714]
 [0.5        0.42857143]
 [0.75       0.57142857]
 [1.         1.        ]]
 ```
 
## 分類
データのクラスを予測して分けるタスク。

```
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

iris = load_iris()
X,Y = iris.data,iris.target

X_train,X_test,y_train,y_test = train_test_split(
                X,y,test_size=0.3,random_state=123)

```

### サポートベクタマシン
線形分離できないデータを高次元の空間に写して線形分離することで分類を行うアルゴリズム。

入力
```
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVC

# 2番目のコードで定義されたプロット関数
def plot_boundary_margin_sv(X0, y0, X1, y1, kernel, C, xmin=-1, xmax=1, ymin=-1, ymax=1):
    # SVMモデルの作成と学習
    svc = SVC(kernel=kernel, C=C)
    svc.fit(np.vstack((X0, X1)), np.hstack((y0, y1)))

    # 散布図のプロット
    fig, ax = plt.subplots()
    ax.scatter(X0[:, 0], X0[:, 1], marker='o', label='class 0')
    ax.scatter(X1[:, 0], X1[:, 1], marker='x', label='class 1')

    # 決定境界とマージンのプロット
    xx, yy = np.meshgrid(np.linspace(xmin, xmax, 100),
                         np.linspace(ymin, ymax, 100))
    xy = np.vstack([xx.ravel(), yy.ravel()]).T
    p = svc.decision_function(xy).reshape((100, 100))
    ax.contour(xx, yy, p, colors='k', levels=[-1, 0, 1],
               alpha=0.5, linestyles=['--', '-', '--'])

    # サポートベクターのプロット
    ax.scatter(svc.support_vectors_[:, 0],
               svc.support_vectors_[:, 1],
               s=250, facecolors='none',
               edgecolors='black')

    # ラベルと凡例の設定
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.legend(loc='best')
    plt.show()

# 1番目のコードで生成されたデータ
rng = np.random.default_rng(123)

# クラス0のデータ生成
X0 = rng.uniform(size=(100, 2))
y0 = np.repeat(0, 100)

# クラス1のデータ生成
X1 = rng.uniform(-1.0, 0.0, size=(100, 2))
y1 = np.repeat(1, 100)

# プロット関数の呼び出し（カーネルは'linear'、C=1として実行）
plot_boundary_margin_sv(X0, y0, X1, y1, kernel='linear', C=1)
```

出力

![スクリーンショット 2025-05-21 21.13.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/addc7d0b-d286-43e1-aad7-9ef24b82ffeb.png)


### 決定木
データを分割するルールを次々と作成していく事による分類を実行。
「データを分割することによってどれだけ得をするか」という情報利得と、「どれだけクラスが混在しているか」という不純度について考える。不純度が下がることにより情報利得が増す。
情報利得は、親ノードの不純度から子ノードの不純度の合計を引くことで求められる。

入力
```
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

iris = load_iris()
X,y = iris.data,iris.target

X_train,X_test,y_train,y_test = train_test_split(
                 X,y,test_size=0.3,random_state=123)
tree = DecisionTreeClassifier(max_depth=3,
                              random_state=123)

tree.fit(X_train,y_train)
```

出力

![スクリーンショット 2025-05-21 23.04.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/b584a14c-97ff-4b76-82cd-3cc8885088df.png)


### ランダムフォレスト
データのサンプルと特徴量をランダムに選択して決定木を構築する処理を複数回繰り返し、各木の推定結果の多数決や平均値により分類・回帰を行う手法。


入力
```
from sklearn.ensemble import RandomForestClassifier

forest = RandomForestClassifier(n_estimators=100,
                                random_state=123)
forest.fit(X_train,y_train)

y_pred = forest.predict(X_test)
print(y_pred)
```

出力
```
[1 2 2 1 0 1 1 0 0 1 2 0 1 2 2 2 0 0 1 0 0 1 0 2 0 0 0 2 2 0 2 1 0 0 1 1 2
 0 0 1 1 0 2 2 2]
```

### 回帰
ある値を別の単一又は複数の値で説明するタスク。

入力
```
from sklearn.linear_model import LinearRegression
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split

# データの取得
housing = fetch_california_housing()
X, y = housing.data, housing.target

# データを訓練セットとテストセットに分割
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=123)

# 線形回帰モデルの作成
lr = LinearRegression()

# モデルの学習
lr.fit(X_train, y_train)
```

![スクリーンショット 2025-05-22 20.54.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/57eb3fc0-5501-4d0c-b805-d6ec31e9f7ca.png)


## 次元削減
データが持っている情報をなるべく損ねることなく次元を削減してデータを圧縮するタスク。

### 主成分分析
高次元のデータに対して分散が大きくなる方向を探して元の次元と同じかそれよりも低い次元にデータを変換する手法。



入力
```
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA

rng = np.random.default_rng(123)

X = rng.uniform(size=50)

Y = 2*X + 0.5*rng.uniform(size=50)

pca = PCA(n_components=2)

X_pca = pca.fit_transform(np.hstack((X.reshape(-1,1),
                                     Y.reshape(-1,1))))

fig, ax = plt.subplots()
ax.scatter(X_pca[:,0],X_pca[:,1])
ax.set_xlabel('PC1')
ax.set_ylabel('PC2')
ax.set_xlim(-1.1,1.1)
ax.set_ylim(-1.1,1.1)
plt.show()
```

![スクリーンショット 2025-05-22 21.31.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/26c39758-719f-4d47-b488-52db8dfea65e.png)


## モデルの評価

### カテゴリの分類精度

・適合率・・正例と予測したもののうち正例であった割合。
・再現率・・正例であったもののうち正例と予測したものの割合。
・F値・・適合率と再現率の調和平均。
・正解率・・予測と実績が一致したデータの割合。

入力
```
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

iris = load_iris()
X,y = iris.data[:100,:],iris.target[:100]

X_train,X_test,y_train,y_test = train_test_split(
                 X,y,test_size=0.3,random_state=123)

svc = SVC()

svc.fit(X_train,y_train)

y_pred = svc.predict(X_test)

print(classification_report(y_test,y_pred))

```

出力

![スクリーンショット 2025-05-22 23.13.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/7c494594-130c-4240-9c47-a48b7998d938.png)

・交差検証

入力
```
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

svc = SVC()

print(cross_val_score(svc,X,y,cv=10,scoring='precision'))
```

出力

```
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
```


### ROC曲線
縦軸に真陽性率、横軸に偽陽性率をプロットして描かれる。

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

# 偽陽性率と真陽性率を計算
fpr = np.array([0, 0, 0, 1, 1, 2, 3, 3, 3, 3, 4, 5, 5, 6,
                7, 8, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14])/14
tpr = np.array([0, 1, 2, 2, 3, 3, 3, 4, 5, 6, 6, 6, 7, 7,
                7, 7, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11])/11

# ROC曲線をプロット
import numpy as np
from sklearn.metrics import roc_curve

# 各データが正解したかどうかを表すダブル
labels = np.array([1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1,
                   0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0])

# 各データの予測正解確率
probs = np.array([0.98, 0.95, 0.9, 0.87, 0.85,
                  0.8, 0.75, 0.71, 0.63, 0.55,
                  0.51, 0.47, 0.43, 0.38, 0.35,
                  0.31, 0.28, 0.24, 0.22, 0.19,
                  0.15, 0.12, 0.08, 0.04, 0.01])

# 偽陽性率、真陽性率、しきい値を算出
fpr, tpr, threshold = roc_curve(labels, probs)

fig, ax = plt.subplots()
ax.step(fpr, tpr)
ax.set_xlabel('false positive rate')
ax.set_ylabel('true positive rate')
plt.show()
```

出力
![スクリーンショット 2025-05-23 23.28.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/ba91b7f0-584c-4f5a-b960-2fd0b1fce524.png)


## ハイパーパラメータの最適化

### グリッドサーチ
ハイパーパラメータを最適化する代表的な手法の一つ。ハイパーパラメータの候補を指定し、それぞれのハイパーパラメータで学習を行いテストデータセットに対する予測が最も良い値を選択する方法。

入力
```
from sklearn.datasets import load_iris
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.tree import DecisionTreeClassifier

# Irisデータセットをロード
iris = load_iris()
X, y = iris.data, iris.target

# データを訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=123)

# 決定木をインスタンス化
clf = DecisionTreeClassifier(random_state=123)
param_grid = {'max_depth': [3, 4, 5]}

# 10分割の交差検証を実行
cv = GridSearchCV(clf, param_grid=param_grid, cv=10)
cv.fit(X_train, y_train)

# 推定された最適なモデルを用いて予測
y_pred = cv.predict(X_test)
y_pred
```

出力
```
array([1, 2, 2, 1, 0, 1, 1, 0, 0, 1, 2, 0, 1, 2, 2, 2, 0, 0, 1, 0, 0, 1,
       0, 2, 0, 0, 0, 2, 2, 0, 2, 1, 0, 0, 1, 1, 2, 0, 0, 1, 1, 0, 2, 2,
       2])

```


## クラスタリング
ある基準を設定してデータ間の類似性を計算し、データをクラスタにまとめるタスク。

### k-means
データをK個のクラスタに分ける。

入力
```
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans

# Irisデータセットをロード
iris = load_iris()
data = iris.data

# 1, 3列目を抽出（がく片の幅と花弁の幅）
X = data[:100, [1, 3]]  # [1, 3]：がく片の幅（Sepal Width）、花弁の幅（Petal Width）

# データを3とするKMeansのインスタンスを生成
km = KMeans(n_clusters=3, init='k-means++', n_init=10, random_state=123)

# KMeansを実行
y_km = km.fit_predict(X)

# 散布図を描写
fig, ax = plt.subplots()

# 散布図（クラスター1）
ax.scatter(X[y_km == 0, 0], X[y_km == 0, 1], s=50,
           edgecolor='black', marker='s', label='cluster 1')

# クラスター中心（クラスター1）
ax.plot(np.mean(X[y_km == 0, 0]),
        np.mean(X[y_km == 0, 1]),
        marker='x', markersize=10, color='red')

# 散布図（クラスター2）
ax.scatter(X[y_km == 1, 0], X[y_km == 1, 1], s=50,
           edgecolor='black', marker='o', label='cluster 2')

# クラスター中心（クラスター2）
ax.plot(np.mean(X[y_km == 1, 0]),
        np.mean(X[y_km == 1, 1]),
        marker='x', markersize=10, color='red')

# 散布図（クラスター3）
ax.scatter(X[y_km == 2, 0], X[y_km == 2, 1], s=50,
           edgecolor='black', marker='v', label='cluster 3')

# クラスター中心（クラスター3）
ax.plot(np.mean(X[y_km == 2, 0]),
        np.mean(X[y_km == 2, 1]),
        marker='x', markersize=10, color='red')

# ラベル設定
ax.set_xlabel('Sepal width')
ax.set_ylabel('Petal width')

# 凡例
ax.legend()

# 表示
plt.show()
```

出力

![スクリーンショット 2025-05-24 13.03.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/890f9e8a-efc3-49c4-a357-b3bc80f4e3ef.png)


### 凝集型階層的クラスタリング
まず似ているデータをまとめて小さなクラスタを作り、次にそのクラスタと似ているデータをさらにまとめ、最終的にデータが一つのクラスタにまとめられるまで処理を繰り返す方法。

入力

```
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram

# Irisデータセットをロード
iris = load_iris()
data = iris.data

# 1, 3列目を抽出（がく片の幅と花弁の幅）
X = data[:100, [1, 3]]  # [1, 3]：がく片の幅（Sepal Width）、花弁の幅（Petal Width）

# 凝集型クラスタリングのインスタンスを生成（affinityをmetricに変更）
ac = AgglomerativeClustering(n_clusters=3, metric='euclidean', linkage='complete')

# データを更新し、含まれるクラスター番号を取得
labels = ac.fit_predict(X)

# クラスタ間の関係を抽出
children = ac.children_

# クラスタ間の距離を抽出
distance = np.arange(children.shape[0])

# 各データの観測番号
no_of_observations = np.arange(2, children.shape[0]+2)

# マージマス、クラスター間の距離、観測番号を利力向に結合
linkage_matrix = np.hstack((children,
                           distance.reshape(-1, 1),
                           no_of_observations.reshape(-1, 1))).astype(float)

# 樹形図をプロット
fig, ax = plt.subplots(figsize=(15, 3), dpi=300)
dendrogram(linkage_matrix, labels=np.arange(100),
           leaf_font_size=8, color_threshold=np.inf)

plt.show()

```


出力
![スクリーンショット 2025-05-24 13.19.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982162/37cf7445-609a-45d1-a9cc-4c60d2182822.png)

#

以上。Xも見てね

https://x.com/DB_sirro_SE