Numpy入門(上)

Numpy

Numpyの基本的な使い方について見ていきます。
Numpyは、配列処理を効率的に行うことができるPythonモジュールです。

本記事の内容は、Numpy公式ページに詳しく説明されています。
初心者向けの記事の流れに沿ってメモってます。

Numpyのインストール

pip install numpy

ソースコードで、numpyモジュールを読み込みます。

import numpy as np

as npで、内部でnumpyをnpの名前で使用することできます。

配列を定義する

単純な1次元配列

a1 = np.array(
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
)
print(a1)
出力
[ 1  2  3  4  5  6  7  8  9 10]

2次元配列

a2 = np.array(
    [
        [1, 2, 3, 4, 5],
        [6, 7, 8, 9, 10]
    ]
)
print(a2)
出力
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]]

すべての要素が0の配列を定義する

b = np.zeros(
    (2, 3)
)
print(b)

引数には、配列の次元を指定します。上の場合は、2行3列の配列の場合。

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

すべての要素が1の配列を定義する

c = np.ones(
    (2, 3)
)
print(c)
出力
[[1. 1. 1.]
 [1. 1. 1.]]

連番・等差数列を定義する

d = np.arange(4)
print('d = ', d)

e = np.arange(2, 9, 2)
print('e = ', e)

配列eの引数は、左からそれぞれ、最小値、最大値-1、要素ごとの差を表します。

出力
d =  [0 1 2 3]
e =  [2 4 6 8]

同様の配列定義は、np.linspace()を利用することでも実現できます。

e2 = np.linspace(2, 8, num=4, dtype='int32')
print('e2 = ', e2)

num引数で要素数を指定します。
dtype引数で、要素の型を指定します。(今回の場合、指定しないとfloat32型で作成されます)
arangeの場合と違って、第2引数は最大値そのものを指します。(最大値−1ではありません)

出力
e2 =  [2 4 6 8]

単位行列を定義する

単位行列と呼ばれる、片方の対角の要素がすべて1となるような配列を定義します。

f = np.identity(4)
print(f)
出力
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]

配列を結合する

配列を結合するには、np.concatenate()を利用します。

b = np.array(
    [1, 2, 3, 4]
) 
c = np.array(
    [5, 6, 7, 8]
)
print(np.concatenate((b, c)))
出力
[1 2 3 4 5 6 7 8]
d = np.array(
    [
        [1, 2],
        [3, 4]
    ]
)
e = np.array(
    [
        [5, 6]
    ]
)
print(np.concatenate(
    (d, e), axis=0
))
出力
[[1 2]
 [3 4]
 [5 6]]

配列の要素をソートする

a = np.array(
    [2, 1, 5, 3, 7, 4, 6, 8]
)
print(a)
print(np.sort(a))
出力
[2 1 5 3 7 4 6 8]
[1 2 3 4 5 6 7 8]

配列の次元数、要素数、次元ごとの要素数

a = np.array(
    [
        [
            [0, 1, 2, 3],
            [4, 5, 6, 7]
        ],
        [
            [0, 1, 2, 3],
            [4, 5, 6, 7]
        ],
        [
            [0, 1, 2, 3],
            [4, 5, 6, 7]
        ]
    ]
)
print(a) 
print(a.ndim)
print(a.size)
print(a.shape)
出力
[[[0 1 2 3]
  [4 5 6 7]]

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

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

これは、3次元の配列です。
要素数は、24個です。
これは、3×2×4の配列です。

配列を組み替える

a = np.arange(6)
print('a =' , a)

b = a.reshape(3, 2)
print('b = ', b) 
出力
a = [0 1 2 3 4 5]
b =  [[0 1]
   [2 3]
   [4 5]]

1次元配列[0, 1, 2, 3, 4, 5]を3行2列の配列へ組み替えています。

配列に次元を追加する

a = np.array(
    [1, 2, 3, 4, 5]
)
b = np.expand_dims(a, axis=0)
print('b.shape = ', b.shape)
print('b = ', b)

c = np.expand_dims(a, axis=1)
print('c.shape = ', c.shape)
print('c = ', c)
c = np.expand_dims(c, axis=2)
print('c.shape = ', c.shape)
print('c = ', c)
出力
b.shape =  (1, 5)
b =  [[1 2 3 4 5]]
c.shape =  (5, 1)
c =  [[1]
 [2]
 [3]
 [4]
 [5]]
c.shape =  (5, 1, 1)
c =  [[[1]]

 [[2]]

 [[3]]

 [[4]]

 [[5]]]

配列の要素を取り出す

PythonのListと同じようにインデックス指定、スライスができます。

a = np.array(
    [1, 2, 3, 4, 5]
)
print('a[0] = ', a[0])
print('a[0:2] = ', a[0:2])
print('a[1:] = ', a[1:])
print('a[-2:] = ', a[-2:])
出力
a[0] =  1
a[0:2] =  [1 2]
a[1:] =  [2 3 4 5]
a[-2:] =  [4 5]

条件に当てはまる要素を取得する

b = np.array(
    [
        [1, 2, 3, 4],
        [5, 6, 7, 8],
        [9, 10, 11, 12]
    ]
)
print('値が5未満の要素 = ', b[b < 5])

five_up = (b <= 5)
print('five_up = ', five_up) 
print('値が5以下の要素 = ', b[five_up])

division_by_2 = (b % 2 == 0)
print('偶数の要素 = ', b[division_by_2])

c = b[(b > 2) & (b < 11)]
print('2より大きくて11より小さい要素 = ', c)
出力
値が5未満の要素 =  [1 2 3 4]
five_up =  [[ True  True  True  True]
 [ True False False False]
 [False False False False]]
値が5以下の要素 =  [1 2 3 4 5]
偶数の要素 =  [ 2  4  6  8 10 12]
2より大きくて11より小さい要素 =  [ 3  4  5  6  7  8  9 10]

five_upには、条件に当てはまっているか否かのBoolean値が入っています。
この結果に基づいて、Trueの要素を取り出しているんですね。

0以外の要素を取り出す np.nonzero()

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

e = np.nonzero(d < 5)
print('e = ', e)
print('d[e] = ', d[e])

f = np.nonzero(d < 8)
print('f = ', f)
print('d[f] = ', d[f]) 
出力
e =  (array([0, 0, 0, 0]), array([0, 1, 2, 3]))
d[e] =  [1 2 3 4]
f =  (array([0, 0, 0, 0, 1, 1, 1]), array([0, 1, 2, 3, 0, 1, 2]))
d[f] =  [1 2 3 4 5 6 7]

eの出力結果には、非0要素のインデックスが返されます。
この結果から元要素の非0部分の値を取り出すことができます。

eのarray([0, 0, 0, 0])は、行インデックスを表しています。
eのarray([0, 1, 2, 3])は、列インデックスを表しています。
つまり、dの要素の中で、(0, 0)、(0, 1)、(0, 2)、(0, 3)の要素が条件を満たしていることを
表しています。

配列から要素を切り出すスライス、結合、分割

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

b = a[3:8]
print('b = ', b)

c = np.array(
    [
        [1, 1],
        [2, 2]
    ]
)
d = np.array(
    [
        [3, 3],
        [4, 4]
    ]
)
e = np.vstack(
    (c, d) 
)
print('e = ', e)
f = np.hstack(
    (c, d) 
)
print('f = ', f)
出力
a =  [ 1  2  3  4  5  6  7  8  9 10]
b =  [4 5 6 7 8]
e =  [[1 1]
 [2 2]
 [3 3]
 [4 4]]
f =  [[1 1 3 3]
 [2 2 4 4]]

スライスは、すでに見ていますね。
vstackでは、2つの配列を行方向に結合しています。
hstackでは、2つの配列を列方向に結合しています。

g = np.arange(1, 25).reshape(2, 12)
print('g = ', g)
print('np.hsplit(g, 3) = ', np.hsplit(g, 3))
print('np.hsplit(g, (3,)) = ', np.hsplit(g, (3,)))
print('np.hsplit(g, (3, 4)) = ', np.hsplit(g, (3, 4))
出力
g =  [[ 1  2  3  4  5  6  7  8  9 10 11 12]
   [13 14 15 16 17 18 19 20 21 22 23 24]]
np.hsplit(g, 3) =  [
    array([
        [ 1,  2,  3,  4],
           [13, 14, 15, 16]]
    ), 
    array([
        [ 5,  6,  7,  8],
           [17, 18, 19, 20]]
    ), 
    array([
        [ 9, 10, 11, 12],
           [21, 22, 23, 24]]
    )
]
np.hsplit(g, (3,)) =  [
       array([
              [ 1,  2,  3],
           [13, 14, 15]]), 
    array([
       [ 4,  5,  6,  7,  8,  9, 10, 11, 12],
           [16, 17, 18, 19, 20, 21, 22, 23, 24]])]
np.hsplit(g, (3, 4)) =  [
    array([
       [ 1,  2,  3],
           [13, 14, 15]]), 
    array([
       [ 4],
           [16]]), 
    array([
       [ 5,  6,  7,  8,  9, 10, 11, 12],
           [17, 18, 19, 20, 21, 22, 23, 24]])
]

np.hsplit(g, 3)では、配列を3要素に分割しています。
np.hsplit(g, (3,))では、配列を3列目で2つに分割しています。
np.hsplit(g, (3, 4))では、配列を3列目と4列目で3つに分割しています。

長いので今回はこの辺りにします。
次回Numpy初心者向け講座の後半部分を見ていきます。

コメント

タイトルとURLをコピーしました