幸せになり隊

幸せってなに?どうやったら幸せになれるの?そんな思いを密かに燃えたぎらせる人たちの試行錯誤の記録。

Pythonで機械学習を始めるなら知っておきたいNumPyの使い方

f:id:wbhappy:20150206203439j:plain

最近流行りの機械学習ですが、実は一番大変なのはデータ処理だったりします。

NumPyPythonで良く使われる数値計算ライブラリで、柔軟な配列操作が可能であり、データ処理も簡単にできるようになっています。Pandasやscikit-learnなど、機械学習でよく使われる有名なライブラリでも使われているので、NumPyを使いこなせるととても幸せになれます(多分)。

この記事では備忘録もかねてユースケース別にNumPyの使い方をまとめたいと思います。 

基本的な使い方はこちらのサイト(Pythonの数値計算ライブラリ NumPy入門)がとても参考になります。 

はじめに

※numpyはnpという名前で使えるようにimportしておきます。

import numpy as np

 

目次

  1. テストデータを生成する
  2. ある行、列だけを抽出する(インデックスで指定)
  3. 条件に合うデータだけ抽出する(条件式で指定)
  4. 欠損値を置き換える
  5. 欠損値を含む行または列を削除する
  6. 配列を連結する(行方向、列方向)
  7. 集計する(基本統計量、行方向、列方向)
  8. ソートしてトップ3を抽出する
  9. 配列の各要素に対してユーザ定義の関数を適用する

テストデータを作成する

# 0が10個ある配列
>>> np.zeros(10)
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

# 1が10個ある配列
>>> np.ones(10)
array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])

# 1ずつ増える配列
>>> np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# nずつ増える配列
>>> np.arange(10, step=2) # 2ずつ増える
array([0, 2, 4, 6, 8])

# 正規分布に従う乱数を10個生成
>>> np.random.randn(10)
array([ 0.14209739, -0.89635699, -0.24578741,  2.61610246, -0.39411796,
       -0.3427316 ,  0.74725415,  0.54529444, -1.0530754 , -1.52333327])

# 二項分布に従う乱数を10個生成
>>> np.random.binomial(n=100, p=0.1, size=(10))
array([16,  5, 12,  7, 16,  9,  6,  8, 12,  9])

# ポアソン分布に従う乱数を10個生成
>>> np.random.poisson(lam=10, size=(10))
array([ 7,  6, 13, 12, 16,  9,  5, 11,  8,  5])

# ある範囲の整数をランダムで生成(一様分布)
>>> np.random.randint(low=0, high=2, size=10) # 0からhigh-1が生成される範囲
array([0, 0, 1, 1, 1, 1, 0, 0, 0, 0])

# 2*3の行列を生成
>>> np.arange(6).reshape((2,3)) 
array([[0, 1, 2],
       [3, 4, 5]])

# 2*3*4*5の行列を生成
>>> np.arange(2*3*4*5).reshape((2,3,4,5))
array([[[[  0,   1,   2,   3,   4],
         [  5,   6,   7,   8,   9],
         [ 10,  11,  12,  13,  14],
         [ 15,  16,  17,  18,  19]],
    ・・・・
        [[100, 101, 102, 103, 104],
         [105, 106, 107, 108, 109],
         [110, 111, 112, 113, 114],
         [115, 116, 117, 118, 119]]]])

 

ある行、列だけを抽出する(インデックスで指定)

x = np.array([[1,2,3],[4,5,6]])
>>> x = np.arange(9).reshape((3,3))
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

# 2列目を抽出
>>> x[:,1]
array([1, 4, 7])

# 2行目以降を抽出
>>> x[1:]
array([[3, 4, 5],
       [6, 7, 8]])

# 2列目以降を抽出
>>> x[:, 1:]
array([[1, 2],
       [4, 5],
       [7, 8]])

# 2列目までを抽出
>>> x[:, :2]
array([[0, 1],
       [3, 4],
       [6, 7]])

 

条件に合うデータだけを置き換える(条件式で指定)

>>> x = np.arange(9).reshape((3,3))
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> y = np.eye(3)
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])

# 条件に合うデータを抽出
>>> x[x>=5] # 5以上を抽出
array([ 5,  6,  7,  8]) 

>>> x[(x>=5)&(x<8)] # 5以上8未満を抽出
array([ 5,  6,  7]) 

# yが1になっているxのデータを抽出
>>> x[y==1]
array([0, 4, 8])

# 5未満のxを0, 5以上のxを1にする
>>> x[x<5]=0
>>> x[x>=5] = 1
array([[0, 0, 0],
       [0, 0, 1],
       [1, 1, 1]])

 

欠損値を置き換える

>>> x = np.array([[1,2,3],[4,np.nan,5],[6,7,8]])
array([[  1.,   2.,   3.],
       [  4.,  nan,   5.],
       [  6.,   7.,   8.]])

# 欠損値を0に置き換え
>>> x[np.isnan(x)] = 0
>>> x
array([[ 1.,  2.,  3.],
       [ 4.,  0.,  5.],
       [ 6.,  7.,  8.]])

# 欠損値を平均値(欠損値を除いた平均値)に置き換え
>>> x[np.isnan(x)] = np.nanmean(x)
array([[ 1. ,  2. ,  3. ],
       [ 4. ,  4.5,  5. ],
       [ 6. ,  7. ,  8. ]])

 

欠損値を含む行または列を除外する

>>> x = np.array([[1,2,3],[4,np.nan,5],[6,7,8]])
array([[  1.,   2.,   3.],
       [  4.,  nan,   5.],
       [  6.,   7.,   8.]])

# 欠損値を含む行を除外
>>> x[~np.isnan(x).any(axis=1)]
array([[ 1.,  2.,  3.],
       [ 6.,  7.,  8.]])

# 欠損値を含む列を除外
>>> np.ma.compress_cols(np.ma.masked_invalid(x))
array([[ 1.,  3.],
       [ 4.,  5.],
       [ 6.,  8.]])

 

配列を連結する(行方向、列方向)

>>> x1 = np.arange(start=0, stop=3)
array([0, 1, 2])
>>> x2 = np.arange(start=3, stop=6)
array([3, 4, 5])

# 行を追加
>>> np.vstack([x1, x2])
array([[0, 1, 2],
       [3, 4, 5]])

# 列を追加
>>> np.hstack([x1, x2])
array([0, 1, 2, 3, 4, 5])
>>> np.r_[x1,x2] # ↑と同じ
array([0, 1, 2, 3, 4, 5])

# 行を追加(補足)
>>> np.dstack([x1, x2])
array([[[0, 3],
        [1, 4],
        [2, 5]]])
>>> np.c_[x1,x2] # ↑と同じ
array([[0, 3],
       [1, 4],
       [2, 5]])
>>> np.vstack([x1, x2]).T  # vstackの結果を転置(↑と同じ)
array([[0, 3],
       [1, 4],
       [2, 5]])

 

集計する(基本統計量、行方向、列方向)

>>> x = np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# 合計
>>> x.sum()
45
>>> np.sum(x)
45

# 平均
>>> x.mean()
4.5
>>> np.mean(x)
4.5

# 分散
>>> np.var(x)
8.25

# 標準偏差
>>> np.std(x)
2.8722813232690143

# 行列の行方向の計算
x = x.reshape((2,5))
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
>>> np.mean(x,axis=1)
array([ 2.,  7.])

# 行列の列方向の計算
>>> np.mean(x, axis=0)
array([ 2.5,  3.5,  4.5,  5.5,  6.5])

 

ソートしてトップ3を抽出する

>>> x = np.arange(5)*2
>>> np.random.shuffle(x)
array([2, 0, 8, 6, 4])

# 昇順にソート
>>> np.sort(x)
array([0, 2, 4, 6, 8])

# 降順にソート
>>> np.sort(x)[::-1]
array([8, 6, 4, 2, 0])

# 数値の大きい順にtop3を取得
>>> np.sort(x)[-3:][::-1]
array([8, 6, 4])

# 昇順にソートして、その要素の元のインデックスを取得
>>> np.argsort(x)
array([1, 0, 4, 3, 2])

 

配列の各要素に対してユーザ定義の関数を適用する

>>> x = np.arange(5)
array([0, 1, 2, 3, 4])

# 要素を2乗する
>>> vf = np.vectorize(lamda: x: x*x)
>>> vf(x)
array([ 0,  1,  4,  9, 16])

 

他にも便利な関数が用意されていますので興味がある方はぜひ公式のドキュメントを眺めてみてください。

 

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

Pythonで体験するベイズ推論 PyMCによるMCMC入門

Pythonで体験するベイズ推論 PyMCによるMCMC入門

  • 作者: キャメロンデビッドソン=ピロン,Cameron Davidson‐Pilon,玉木徹
  • 出版社/メーカー: 森北出版
  • 発売日: 2017/04/06
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る