Python NumPy初心者向け使い方

Python NumPy初心者向け使い方

pythonを用いると必ず出てくるnumpy
いったい何なのでしょうか。

早い話が配列を作成するライブラリです。
ただリストとは違いデータ型は1種類のみです。
つまり[1,2,3,4,5]や[“a”,”b”,”c”,”d”]はよいが
[1,”a”,2,”b”,3]のような配列は文字型となってしまいます。
それによって計算能力を高めているという特徴があります。
※実行環境:Python 3.8.8 win10 64bit

本記事は下記の書籍を参考に記述しています。

Pythonによるあたらしいデータ分析の教科書 第2版

もくじ

  1. 配列の作成
  2. 要素を変更及び追加する
  3. 要素を削除する
  4. 要素の参照
  5. 四則演算
  6. ユニバーサル関数

1.配列の作成

import numpy as np
numpyをインポートします。
as npとすることでnumpy を npで利用できるようになります。

a = np.array([1,2,3,4,5])によってnumpy配列を作成できます。
※array()は配列を作成する関数です。
配列のデータ型を確認します。
print(type(a))
配列要素のデータ型も調べてみましょう。
print(a.dtype)

a = np.array([1,2,3,4,5])
print(type(a))
<class 'numpy.ndarray'>
print(a.dtype)
int32

ちなみにリスト型はこんな感じです。

a = [1,2,3,4,5]
print(type(a))
<class 'list'>


文字列型も作ってみましょう。

b  = np.array(["apple","beach","cook","do"])
print(type(b))
<class 'numpy.ndarray'>
print(b.dtype)
<U5

文字列の場合<Uです。
後ろの数字は文字列の最大文字数となっています。

浮動小数はどうなるでしょう。

c = np.array([1.0,2.34,3.0,4.11,5.0])
print(type(c))
<class 'numpy.ndarray'>
print(c.dtype)
float64

float64 これが浮動小数の場合のデフォルトのデータ型となります。

次に配列要素のデータ型を変更します。

a = np.array([1,2,3,4,5]
print(a.dtype)
int32

int32でも問題はないのですが
小さいデータでもint32になりますのでメモリを無駄にする可能性があります。
dtype = np.データ型としてデータ型を指定できます。

a = np.array([1,2,3,4,5],dtype = np.int16)
print(type(a))
<class 'numpy.ndarray'>
print(a.dtype)
int16

つまり16ビットとして扱うことになります。
2の16乗で65536通りの値を識別できます。

連続する整数値でndarrayを作りたい場合は
arange()も利用することができます。

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


2次元配列をつくることもできます。

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

(2,3)から2行3列であることがわかります。
ここから変形(reshape)することも可能です。
※要素数が合わないとエラーとなります。

e = e.reshape(1,6)
print(e)
[[1 2 3 4 5 6]]

2次元配列を1次元にするにはravelメソッドもあります。

e = np.array([[1,2,3],[4,5,6]])
print(e)
[[1 2 3]
 [4 5 6]]
e = e.ravel()
print(e)
[1 2 3 4 5 6]

乱数の配列を作成することもできます。

f = np.random.random((3,2))
print(f)
[[0.37844464 0.43652324]
 [0.40321252 0.7053158 ]
 [0.32793222 0.00464435]]

指定の値で埋めることもできます。

a = np.pi
print(a)

3.141592653589793
b = np.full((2,5),np.pi)
print(b)
[[3.14159265 3.14159265 3.14159265 3.14159265 3.14159265]
 [3.14159265 3.14159265 3.14159265 3.14159265 3.14159265]]

欠損値の穴埋めに使われる特殊な数値であるnp.nanを解説します。
nanはnot a numberの略です。
数値でないということを宣言しています。
※nanはデータ型としてはfloatになりますので、それにあわせて1や2もfloat型(1. 2.)になっています。

a = np.array([1,2,np.nan])
print(a)
[ 1.  2. nan]

範囲指定で均等割り配列を作成することもできます。

a = np.linspace(0,100,11)
print(a)
[  0.  10.  20.  30.  40.  50.  60.  70.  80.  90. 100.]

2.要素を変更及び追加する

配列を連結します。

a = np.array([1,2,3])
b = np.array([4,5,6])
c = np.concatenate([a,b])
print(a)
print(b)
print(c)

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

インデックス値[2]の値2を5に書き換える処理です。

a  = np.arange(0,3)
print(a)
[0 1 2]
a[2] = 5
print(a)
[0 1 5]

2次元配列の0行目を7に置き換えます。

e = np.array([[1,2,3],[4,5,6]])
print(e)
[[1 2 3]
 [4 5 6]]
e[0,:] = 7
print(e)
[[7 7 7]
 [4 5 6]]

配列に要素を追加します。

f = np.array([1,2,3])
f = np.append(f,4)
print(f)
[1 2 3 4]

appendは末端に追加します。
場所を指定したい場合はnp.insert()です。

f = np.array([1,2,3])
f = np.insert(f,3,4)
print(f)
[1 2 3 4]

0列目に0を入力してみましょう。

f = np.insert(f,0,0)
print(f)
[0 1 2 3 4]

多次元配列に追加する場合です。
行の追加です。
2つ目の引数の1は1行目を意味します。
4つ目の0は行追加を意味して、1にすると列追加となります。

g = np.array([[1,2,3],[4,5,6],[7,8,9]])
h = np.array([0,0,0])

g = np.insert(g,1,h,0)
print(g)

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

以下のように行追加も可能です。
vstackメソッドも利用できます。
最終行に追加されます。

g = np.array([[1,2,3],[4,5,6],[7,8,9]])
h = np.array([0,0,1])

g = np.vstack([g,h])
print(g)

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

列の追加です。
2つ目の引数の2は2行目を意味します。
4つ目の1は列追加を意味しています。

g = np.array([[1,2,3],[4,5,6],[7,8,9]])
h = [0,0,0]
g = np.insert(g,2,h,1)
print(g)

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

以下のように列追加も可能です。
hstackメソッドも利用できます。
最終列に追加されます。

g = np.array([[1,2,3],[4,5,6],[7,8,9]])
h = [[0],[0],[0]]
g = np.hstack([g,h])
print(g)

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

次は分割してみましょう。
列で分割します。

print(g)
[[1 2 3 0]
 [4 5 6 0]
 [7 8 9 0]]

first,second = np.hsplit(g,[3])
print(first)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
print(second)
[[0]
 [0]
 [0]]

行で分割します。

print(g)
[[1 2 3 0]
 [4 5 6 0]
 [7 8 9 0]]

first,second = np.vsplit(g,[2])
print(first)
[[1 2 3 0]
 [4 5 6 0]]
print(second)
[[7 8 9 0]]

2次元配列の行と列を入れ替えます。
転置といいます。

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

ドット積になります。
掛ける順番を逆にすると答えが変わることに注意しましょう。
※np.dot(a,b)はa@bという記述もできます。

a = np.array([[1,2,3],[1,1,1]])
b = np.array([[10,10],[1,1],[1,1]])
np.dot(a,b)
array([[15, 15],
       [12, 12]])

a = np.array([[1,2,3],[1,1,1]])
b = np.array([[10,10],[1,1],[1,1]])
np.dot(b,a)
array([[20, 30, 40],
       [ 2,  3,  4],
       [ 2,  3,  4]])

3.要素を削除する

np.deleteを用います。

i = np.arange(0,5)
print(i)
i = np.delete(i,0)
print(i)
[0 1 2 3 4]
[1 2 3 4]


多次元配列の削除をおこないます。
3つ目の引数0は行削除を意味します。

g = [[1,2,3],[4,5,6],[7,8,9]]
g = np.delete(g,0,0)
print(g)
[[4 5 6]
 [7 8 9]]


3つ目の引数を1とすると列削除になります。

g = [[1,2,3],[4,5,6],[7,8,9]]
g = np.delete(g,0,1)
print(g)
[[2 3]
 [5 6]
 [8 9]]

4.要素の参照

fruits = np.array([“apple”,”orange”,”grapes”])
要素番号の指定で参照できます。

fruits = np.array(["apple","orange","grapes"])
print(fruits[0])

apple
print(fruits[0:])

['apple' 'orange' 'grapes']
print(fruits[-1])
grapes


次に多次元での参照をおこないます。
fruits_sports = np.array([[“apple”,”orange”,”grapes”],[“baseball”,”soccer”,”tennis”]])

fruits_sports = np.array([["apple","orange","grapes"],["baseball","soccer","tennis"]])
print(fruits_sports[1])
['baseball' 'soccer' 'tennis']
print(fruits_sports[1,2])
tennis
print(fruits_sports[:,[0,2]])
[['apple' 'grapes']
 ['baseball' 'tennis']]

判定・論理値になります。
count_nonzeroメソッドにて0でない要素数を返します。
sumメソッドは条件に一致した要素数を返します。

a = np.array([0,1,2,3,4,5,6])
b = np.count_nonzero(a)
c = np.sum(a > 3)
print(b)
print(c)
6
3
# sumは要素の合計を求めることができる。
np.sum(a)
21
# anyは条件に一致した要素があるかないかを返す。
np.any(a > 4)
True
np.any(a > 6)
False

5.四則演算

ndarrayでは四則演算が可能です。

k = np.array([1,2,3])
print(k +1)
print(k -1)
print(k *2)
print(k / 2)

[2 3 4]
[0 1 2]
[2 4 6]
[0.5 1.  1.5]

また配列同士を演算することもできます。

k = np.array([1,2,3])
l = np.array([4,5,6])
print(k + l)
[5 7 9]


多次元配列の場合です。

m  = np.array([[1,2,3],[4,5,6]])
n = np.array([[2,2,2],[2,2,2]])
print(m + n)
print(m * n)

[[3 4 5]
 [6 7 8]]
[[ 2  4  6]
 [ 8 10 12]]

6.ユニバーサル関数

全要素に対して計算処理を適用できる関数をユニバーサル関数と呼びます。
適当に配列をまず作ります。
o = np.array([1.23,3.98,4.556,3.0,9.5])
print(o)

この配列に対して全要素に切り捨てを行います。
o = np.floor(o)
print(o)

o = np.array([1.23,3.98,4.556,3.0,9.5])
print(o)
o = np.floor(o)
print(o)
[1.23  3.98  4.556 3.    9.5  ]
[1. 3. 4. 3. 9.]

切り上げ、四捨五入も可能です。
o = np.array([1.23,3.98,4.556,3.0,9.5])
p = np.ceil(o) ※切り上げ
print(p)
q = np.round(o) ※四捨五入
print(q)

o = np.array([1.23,3.98,4.556,3.0,9.5])
p = np.ceil(o)
print(p)
q = np.round(o) 
print(q)
[ 2.  4.  5.  3. 10.]
[ 1.  4.  5.  3. 10.]

配列コピーについて

ここではコピーと参照の違いを解説します。
配列a[0,1,2]を作成します。
配列aを配列a1に代入します。
配列aに変更を加えた場合、その変更が配列a1にも適応されます。
これは配列a1は配列aを参照しているからになります。

a  = np.arange(0,3)
a1 = a
print(a1)

[0 1 2]
a[2] = 5
print(a)

[0 1 5]
print(a1)
[0 1 5]

もしそれぞれを独立させたいのならばcopyメソッドを用います。
a1 = a.copy()にて作成します。
配列aと配列a1は別物になります。
補足としてravelメソッドは参照でflattenメソッドはコピーになります。