このシリーズでは、データ分析に必要な基礎知識からPythonによる実装までをまとめます。

今回の記事では、データ分析において重要なPythonライブラリである「Numpy」の概要と使い方について紹介します。

Google colabを使用して、簡単に実装することができますので、ぜひ最後までご覧ください。

今回の内容

・Numpyの基本操作

・行列の演算

・配列操作とブロードキャスト

Numpyとは

Numpyは基本的な配列処理や数値計算に用いるライブラリです。

高度で複雑な計算が可能であり、処理速度が速いことが特徴です。

Numpyの基本操作

まずはnumpyの基本操作から見ていくことにします。

Google Colab環境では、簡単に使用することができます。

import numpy as np

配列

まずは、1から10までの配列を作成してみます。

Numpyにおいて、配列はarrayオブジェクトとして構成されます。

# 配列の作成
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
data

array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

Numpyで扱うデータは、データの「型(type)」というものが設定されています。

データ型とは、「整数(int)」や「浮動小数(float)」などの値の種類のことです。

「整数」と「浮動小数」とでは計算量が異なるため、全体の処理速度に影響してきます。

# データの型
data.dtype

dtype('int64')

今回扱うデータは、64bit長の符号付き整数であることがわかりました。

次元数と要素数も表示してみます。

# 次元数と要素数
print('次元数:', data.ndim,'要素数:', data.size)

次元数: 1 要素数: 10

今回扱うデータは、1次元の要素数が10個ある配列であることがわかりました。

配列の計算

四則演算について、見てみましょう。

以下のように、np.arrayのそれぞれの要素に対して、演算をすることができます。

# それぞれの数字に四則演算
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(data + 3)
print(data - 4)
print(data * 5)
print(data / 10)
print(data **2)

[ 4  5  6  7  8  9 10 11 12 13]
[-3 -2 -1  0  1  2  3  4  5  6]
[ 5 10 15 20 25 30 35 40 45 50]
[0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]
[  1   4   9  16  25  36  49  64  81 100]

np.array同士の要素に対して、演算をすることもできます。

# np.arrayの同士の四則演算
print(np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + np.array([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]))
print(np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) - np.array([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]))
print(np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) * np.array([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]))
print(np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) / np.array([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]))

[11 11 11 11 11 11 11 11 11 11]
[-9 -7 -5 -3 -1  1  3  5  7  9]
[10 18 24 28 30 30 28 24 18 10]
[ 0.1 0.222 0.375 0.571 0.833 1.2 1.75 2.667 4.5 10]

配列のソート(昇順・降順)

配列の要素を並べ替えることができます。

以下の例では、昇順ソートと降順ソートを行います。

[n:m:s]のように記述すると、「n番目からm-1番目を、sずつ飛ばして取り出す」というスライス機能が実装できます。

nやmを省略したときは「すべて」という意味になるため、[::-1]とすることで「末尾から1つずつ取り出す」という意味になり、降順ソートを行うことができるようになります。

# 配列のソート(昇順・降順)
data = np.array([5, 2, 7, 4, 1, 6, 7, 3, 10, 9, 8])
print('入力データ:', data)

# 昇順ソート
data.sort()
print('昇順ソート:', data)

# 降順ソート
data[::-1].sort()
print('降順ソート:', data)

入力データ: [ 5  2  7  4  1  6  7  3 10  9  8]
昇順ソート: [ 1  2  3  4  5  6  7  7  8  9 10]
降順ソート: [10  9  8  7  7  6  5  4  3  2  1]

最大・最小・合計・平均

配列の要素の最大値、最小値、合計値、平均値を計算することができます。

# 最小、最大、合計、平均の計算
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# 最小値
print('Min:', data.min())
# 最大値
print('Max:', data.max())
# 合計
print('Sum:', data.sum())
# 平均
print('mean:', data.mean())

Min: 1
Max: 10
Sum: 55
Sum: 5.5

平方根・ネイピア指数関数

配列の要素の平方根、ネイピア指数関数を計算することができます。

# ユニバーサル関数
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print('平方根:',np.sqrt(data))
print('ネイピア指数関数:',np.exp(data))

平方根: [1.    1.414 1.732 2.    2.236 2.449 2.646 2.828 3.    3.162]
ネイピア指数関数: [2.718e+00 7.389e+00 2.009e+01 5.460e+01 1.484e+02 4.034e+02 1.097e+03 2.981e+03 8.103e+03 2.203e+04]

積み上げの計算

cumsumにより、前から順番に足し上げていく積上演算を行うことができます。

# 積み上げ、積み上げ割合の計算
data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# 積み上げ
print('Cum:', data.cumsum())
# 積み上げ割合
print('Ratio:', data.cumsum() / data.sum())

Cum: [ 1  3  6 10 15 21 28 36 45 55]
Ratio: [0.018 0.055 0.109 0.182 0.273 0.382 0.509 0.655 0.818 1.   ]

重複データの削除

uniqueメソッドを使用することで、重複データを削除することができます。

# 重複要素の削除
data = np.array([5,6,5,7,9,10,6,8,5,5,6,10])
print('入力',data)
print('重複削除後',np.unique(data))

入力 [ 5  6  5  7  9 10  6  8  5  5  6 10]
重複削除後 [ 5  6  7  8  9 10]

行列の演算

numpyの形状変換と行列

行列の演算を行うために、行列を作成します。

まずは以下のように配列を定義します。

np.arange(9)

array([0, 1, 2, 3, 4, 5, 6, 7, 8])

reshapeメソッドにより、3×3の行列に変換することができます。

# 形状変換で行列を作成
array1 = np.arange(9).reshape(3,3)
print(array1)

[[0 1 2]
 [3 4 5]
 [6 7 8]]

n行目・n列目を表示

行列のn行目・n列目を表示することができます。

# 1行目
array1[0,:]

array([0, 1, 2])
# 1列目を表示
array1[:,0]

array([0, 3, 6])

行列の積

積の計算をするため、別の行列を定義します。

array2 = np.arange(4,13).reshape(3,3)

print(array2)
[[ 4  5  6]
 [ 7  8  9]
 [10 11 12]]

dotメソッドにより、行列の積の計算が可能です。

# 行列の積
print(array1)
print(array2)
np.dot(array1, array2)

[[0 1 2]
 [3 4 5]
 [6 7 8]]

[[ 4  5  6]
 [ 7  8  9]
 [10 11 12]]

array([[ 27,  30,  33],
       [ 90, 102, 114],
       [153, 174, 195]])

行列の積ではなく、要素同士の積を計算することもできます。

# 要素どうしの積
array1 * array2

array([[ 0,  5, 12],
       [21, 32, 45],
       [60, 77, 96]])

先頭からn番目までの配列を取り出す

sliceメソッドにより、先頭からn番目までの配列を取り出すことができます。

以下の例では、先頭から5番目までの要素を取り出します。

# 先頭からn番目までの配列を取り出す
# 入力
in_array = np.arange(10)
# スライス
in_array_slice = in_array[0:5]

print('入力:',in_array)
print('スライス後:',in_array_slice)

入力: [0 1 2 3 4 5 6 7 8 9]
スライス後: [0 1 2 3 4]

先頭からn番目までの要素を置換

先頭からn番目までの要素を置換することができます。

以下の例では、3番目までの要素を「10」に置換しています。

# 先頭からn番目までの要素を置換
# 入力
in_array = np.arange(10)
print('入力:',in_array)

# 要素を置換
in_array[0:3] = 10
print('置換後:',in_array)

入力: [0 1 2 3 4 5 6 7 8 9]
置換後: [10 10 10  3  4  5  6  7  8  9]

配列をcopyして別の配列を作成

copyメソッドにより、元の配列をコピーして、複製することができます。

以下の例では、元の配列をコピーして、比較のために一部要素を置換しています。

# 配列をcopyして別の配列を作成
in_array = np.arange(20)
# copyして別の配列を作成
in_array_copy = np.copy(in_array)
# copyした配列の一部を置換
in_array_copy[0:7] = 20

print('入力:',in_array)
print('コピー:',in_array_copy)

入力: [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]
コピー: [20 20 20 20 20 20 20  7  8  9 10 11 12 13 14 15 16 17 18 19]

ブールインデックス参照

bool(TrueかFalseかの真偽値)によってどのデータを取り出すかを決める、ブールインデックス参照を行うことができます。

# ブールインデックス参照
import numpy.random as random
sample_names = np.array(['a','b','c','d','a'])
random.seed(0)
data = random.randn(5,5)

print(sample_names)
print(data)

['a' 'b' 'c' 'd' 'a']
[[ 1.764  0.4    0.979  2.241  1.868]
 [-0.977  0.95  -0.151 -0.103  0.411]
 [ 0.144  1.454  0.761  0.122  0.444]
 [ 0.334  1.494 -0.205  0.313 -0.854]
 [-2.553  0.654  0.864 -0.742  2.27 ]]

この入力データについて、要素の値が「’a’」である部分だけがTrueになる結果を取り出すことができます。

sample_names == 'a'

array([ True, False, False, False,  True])

Trueになる要素だけを取り出すことができます。

data[sample_names == 'a']

array([[ 1.764,  0.4  ,  0.979,  2.241,  1.868],
       [-2.553,  0.654,  0.864, -0.742,  2.27 ]])

条件制御

whereメソッドにより、2つのデータがあるとき、条件を満たすかどうかによって取得するデータを選択することができます。

以下の例では、AとBの配列に対して、条件データ(ブールの配列)に対応した要素を出力しています。

(条件データがTrueの場合はA、Falseの場合はBを返す)

# 条件制御
# 条件制御のためのブールの配列を作成
cond_data = np.array([True,True,False,False,True])

A= np.array([1,2,3,4,5])
B= np.array([100,200,300,400,500])

# 条件制御実施
print(np.where(cond_data,A,B))

[  1   2 300 400   5]

表形式にすると、結果がわかりやすくなります。

pandas as pd
df = pd.DataFrame(data=[[1,2,3,4,5], [100,200,300,400,500],[np.where(cond_data,A,B)][0]], columns=[True,True,False,False,True],index = ['A','B','W'])
index True True False False True
A 1 2 3 4 5
B 100 200 300 400 500
W 1 2 300 400 5

真偽値の判定

anyやallを使うと、要素の条件判定ができます。

anyは少なくとも1つ満たすものがあればTrue、allはすべて満たす場合にTrueを返します。

# 真偽値の配列関数
cond_data = np.array([True,True,False,False,True])

print('Trueが少なくとも1つあるかどうか:',cond_data.any())
print('すべてTrueかどうか:',cond_data.all())

Trueが少なくとも1つあるかどうか: True
すべてTrueかどうか: False

行列の最小・最大・平均・合計の計算

最小、最大、平均、合計等の計算ができます。

パラメータとしてaxisを指定すると、行や列の指定もできます。

#最小、最大、平均、合計の計算

data = np.arange(9).reshape(3,3)
print(data)

print('最小値:',data.min())
print('最大値:',data.max())
print('平均:',data.mean())
print('合計:',data.sum())

# 行列を指定して合計値を求める
print('行の合計:',data.sum(axis=1))
print('列の合計:',data.sum(axis=0))

[[0 1 2]
 [3 4 5]
 [6 7 8]]
最小値: 0
最大値: 8
平均: 4.0
合計: 36
行の合計: [ 3 12 21]
列の合計: [ 9 12 15]

対角成分・対角成分の和

行列の対角成分と対角成分の和を計算することができます。

# 対角成分・対角成分の和
data = np.arange(9).reshape(3,3)
print(data)

print('対角成分:',np.diag(data))
print('対角成分の和:',np.trace(data)

[[0 1 2]
 [3 4 5]
 [6 7 8]]
対角成分: [0 4 8]
対角成分の和: 12

配列操作とブロードキャスト

再形成

Numpyでは、行列の次元を変えることを再形成と言います。

reshapeメソッドにより、再形成することができます。

data = np.arange(10)
#2行5列の行列に再形成
data = data.reshape(2,5)
print(data)

#5行2列の行列に再形成
data = data.reshape(5,2)
print(data)

[[0 1 2 3 4]
 [5 6 7 8 9]]

[[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]

結合

concatenateを使うと、データを行方向、列方向のそれぞれに結合できます。

array1 = np.array([[1,2,3],[4,5,6]])
array2 = np.array([[7,8,9],[10,11,12]])
print('array1',array1)
print('array2',array2)

array1 
[[1 2 3]
 [4 5 6]]
array2 
[[ 7  8  9]
 [10 11 12]]

行方向に結合する場合は、concatenateメソッドでaxis=0とするか、vstackメソッドを用います。

# 行方向に結合(axis:0)
print('---行方向に結合---')
print(np.concatenate([array1,array2],axis=0))
print(np.vstack([array1,array2]))

---行方向に結合---
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]

列方向に結合する場合は、concatenateメソッドでaxis=1とするか、hstackメソッドを用います。

# 列方向に結合(axis:1)
print('---列方向に結合---')
print(np.concatenate([array1,array2],axis=1))
print(np.hstack([array1,array2]))

---列方向に結合---
[[ 1  2  3  7  8  9]
 [ 4  5  6 10 11 12]]
[[ 1  2  3  7  8  9]
 [ 4  5  6 10 11 12]]

ブロードキャスト

NumPy配列の二項演算ではブロードキャスト(broadcasting)という仕組みにより、それぞれの形状shapeが同じになるように自動的に変換される。

まとめ

最後までご覧いただきありがとうございました。

今回の記事では、データ分析において重要なPythonライブラリである「Numpy」の概要と使い方について紹介しました。

このシリーズでは、データ分析に必要な基礎知識からPythonによる実装の方法を紹介しておりますので、是非ご覧ください。

データ分析・機械学習まとめ

このシリーズでは、データ分析と機械学習の手法をまとめています。 データ分析に必要なPythonライブラリ Numpyの基礎 時系列分析 Dartsではじめる時系列分析入門① Dartsで…