6. NumPy配列の基本¶

In [1]:
# データファイルの準備
import urllib.request

basedir = 'https://amanotk.github.io/python-resume-public/data/'
files = ['helix1.dat', 'helix2.dat', 'cbinary.dat']
for f in files:
    urllib.request.urlretrieve(basedir+f, f)
In [2]:
import numpy as np
from matplotlib import pylab as plt

基本的な使い方¶

In [3]:
np.arange(10)
Out[3]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [4]:
N = 10
x = np.arange(N)/N * 2*np.pi
y = np.cos(x)
In [5]:
plt.plot(x, y)
Out[5]:
[<matplotlib.lines.Line2D at 0x7fe6461d0c70>]

配列オブジェクト¶

In [6]:
x = np.arange(10)
In [7]:
# データ型
x.dtype
Out[7]:
dtype('int64')
In [8]:
# 次元数
x.ndim
Out[8]:
1
In [9]:
# 全要素数
x.size
Out[9]:
10
In [10]:
# 形状
x.shape
Out[10]:
(10,)
In [11]:
# 2次元配列の形状
np.array([[1, 2, 3], [4, 5, 6]]).shape
Out[11]:
(2, 3)
In [12]:
# 古い形式の64bit浮動小数点数
np.dtype('d')
Out[12]:
dtype('float64')
In [13]:
# 古い形式の32bit整数
np.dtype('i')
Out[13]:
dtype('int32')

生成¶

In [14]:
# listより生成
np.array([0, 1, 2, 3, 4])
Out[14]:
array([0, 1, 2, 3, 4])
In [15]:
# tupleより生成
np.array((0, 1, 2))
Out[15]:
array([0, 1, 2])
In [16]:
# listのlistを2次元配列に変換
np.array([[0, 1,], [2, 3], [4, 5]])
Out[16]:
array([[0, 1],
       [2, 3],
       [4, 5]])
In [17]:
# start, stop, strideの形
np.arange(10, 20, 2)
Out[17]:
array([10, 12, 14, 16, 18])
In [18]:
# dtypeでデータ型を指定
np.arange(10, dtype=np.float64)
Out[18]:
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
In [19]:
# ゼロで初期化(デフォルトでfloat64)
np.zeros(10)
Out[19]:
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
In [20]:
# 多次元配列の場合は形状をtupleで指定
np.zeros((2, 4), dtype=np.int32)
Out[20]:
array([[0, 0, 0, 0],
       [0, 0, 0, 0]], dtype=int32)
In [21]:
# 同じ形状・データ型の配列
x = np.zeros((3, 3), dtype=np.float32)
np.zeros_like(x)
Out[21]:
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]], dtype=float32)
In [22]:
# 1で初期化すること以外はzerosと同じ
np.ones((3, 3))
Out[22]:
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])
In [23]:
# 1で初期化すること以外はzeros_likeと同じ
x = np.zeros((3, 3), dtype=np.float32)
np.ones_like(x)
Out[23]:
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]], dtype=float32)
In [24]:
# 等間隔の配列(端点含む!)
np.linspace(0.0, 1.0, 11)
Out[24]:
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
In [25]:
# logで等間隔の配列
np.logspace(-1, +1, 11)
Out[25]:
array([ 0.1       ,  0.15848932,  0.25118864,  0.39810717,  0.63095734,
        1.        ,  1.58489319,  2.51188643,  3.98107171,  6.30957344,
       10.        ])
In [26]:
# logspaceと引数の意味が違う以外は同じ
np.geomspace(0.1, 10.0, 11)
Out[26]:
array([ 0.1       ,  0.15848932,  0.25118864,  0.39810717,  0.63095734,
        1.        ,  1.58489319,  2.51188643,  3.98107171,  6.30957344,
       10.        ])
In [27]:
# geomspace / logspaceと同じ
10**np.linspace(np.log10(0.1), np.log10(10.0), 11)
Out[27]:
array([ 0.1       ,  0.15848932,  0.25118864,  0.39810717,  0.63095734,
        1.        ,  1.58489319,  2.51188643,  3.98107171,  6.30957344,
       10.        ])
In [28]:
# 乱数配列
np.random.random(5)
Out[28]:
array([0.69920186, 0.984085  , 0.08579051, 0.1429193 , 0.72806606])
In [29]:
# 整数の乱数配列
np.random.randint(0, 5, size=10)
Out[29]:
array([4, 3, 2, 0, 2, 4, 1, 2, 4, 1])
In [30]:
# 2次元の乱数配列
np.random.random((3, 2))
Out[30]:
array([[0.26798215, 0.73555338],
       [0.79495978, 0.54670385],
       [0.50731011, 0.56923991]])

入出力¶

テキスト入出力¶

In [31]:
# helix1.datの中身を確認
!cat helix1.dat
 0.81  0.59  0.50
 0.31  0.95  1.00
-0.31  0.95  1.50
-0.81  0.59  2.00
-1.00  0.00  2.50
-0.81 -0.59  3.00
-0.31 -0.95  3.50
 0.31 -0.95  4.00
 0.81 -0.59  4.50
 1.00 -0.00  5.00
 0.81  0.59  5.50
 0.31  0.95  6.00
-0.31  0.95  6.50
-0.81  0.59  7.00
-1.00  0.00  7.50
-0.81 -0.59  8.00
-0.31 -0.95  8.50
 0.31 -0.95  9.00
 0.81 -0.59  9.50
 1.00 -0.00 10.00
 0.81  0.59 10.50
 0.31  0.95 11.00
-0.31  0.95 11.50
-0.81  0.59 12.00
-1.00  0.00 12.50
-0.81 -0.59 13.00
-0.31 -0.95 13.50
 0.31 -0.95 14.00
 0.81 -0.59 14.50
 1.00 -0.00 15.00
 0.81  0.59 15.50
 0.31  0.95 16.00
In [32]:
# 読み込み
x = np.loadtxt('helix1.dat')
x.shape
Out[32]:
(32, 3)
In [33]:
# 読み込んだデータを出力
np.savetxt('output.dat', x, fmt='%5.2f')
In [34]:
# output.datの中身を確認
!cat output.dat
 0.81  0.59  0.50
 0.31  0.95  1.00
-0.31  0.95  1.50
-0.81  0.59  2.00
-1.00  0.00  2.50
-0.81 -0.59  3.00
-0.31 -0.95  3.50
 0.31 -0.95  4.00
 0.81 -0.59  4.50
 1.00 -0.00  5.00
 0.81  0.59  5.50
 0.31  0.95  6.00
-0.31  0.95  6.50
-0.81  0.59  7.00
-1.00  0.00  7.50
-0.81 -0.59  8.00
-0.31 -0.95  8.50
 0.31 -0.95  9.00
 0.81 -0.59  9.50
 1.00 -0.00 10.00
 0.81  0.59 10.50
 0.31  0.95 11.00
-0.31  0.95 11.50
-0.81  0.59 12.00
-1.00  0.00 12.50
-0.81 -0.59 13.00
-0.31 -0.95 13.50
 0.31 -0.95 14.00
 0.81 -0.59 14.50
 1.00 -0.00 15.00
 0.81  0.59 15.50
 0.31  0.95 16.00

バイナリ入出力¶

In [35]:
# 配列を準備
x = np.linspace(0.0, np.pi, 100)
y = np.cos(x)
In [36]:
# xをNPY形式で保存
np.save("binary1.npy", x)
In [37]:
# x, yをNPZ形式で保存(各配列に名前を付けておく)
np.savez("binary2.npz", x_name=x, y_name=y)
In [38]:
# NPY形式のファイルを読み込み
xx = np.load("binary1.npy")

# 値が同じことを確認
print(np.alltrue(x == xx))
True
In [39]:
# NPZ形式のファイルを読み込み
data = np.load("binary2.npz")

# dataはdict-likeなオブジェクト
print(list(data.keys()))
['x_name', 'y_name']
In [40]:
xx = data['x_name']
yy = data['y_name']

# ファイルから読んだ配列と元の配列の値が同じことを確認する
print(np.alltrue(x == xx))
print(np.alltrue(y == yy))
True
True

生のバイナリファイル¶

In [41]:
# ファイルを開く
fp = open('cbinary.dat', 'r')

# データ型(ここではnp.float64)およびデータ数(ここでは10)はあらかじめ知っておく必要あり
z = np.fromfile(fp, np.float64, 10)

# ファイルを閉じる
fp.close()

# 値を出力
print(z)
[1.  1.5 2.  2.5 3.  3.5 4.  4.5 5.  5.5]

unformatted形式(Fortran)¶

In [42]:
# モジュール読み込み
from scipy.io import FortranFile

# ファイルを開く
fp = FortranFile('helix2.dat')

# データ読み込み
x = fp.read_record(np.float64)
y = fp.read_record(np.float64)
z = fp.read_record(np.float64)

# ファイルを閉じる
fp.close()
In [43]:
# 結果を確認
for i in range(x.size):
    print('{:5.2f} {:5.2f} {:5.2f}'.format(x[i], y[i], z[i]))
 0.81  0.59  0.50
 0.31  0.95  1.00
-0.31  0.95  1.50
-0.81  0.59  2.00
-1.00  0.00  2.50
-0.81 -0.59  3.00
-0.31 -0.95  3.50
 0.31 -0.95  4.00
 0.81 -0.59  4.50
 1.00 -0.00  5.00
 0.81  0.59  5.50
 0.31  0.95  6.00
-0.31  0.95  6.50
-0.81  0.59  7.00
-1.00  0.00  7.50
-0.81 -0.59  8.00
-0.31 -0.95  8.50
 0.31 -0.95  9.00
 0.81 -0.59  9.50
 1.00 -0.00 10.00
 0.81  0.59 10.50
 0.31  0.95 11.00
-0.31  0.95 11.50
-0.81  0.59 12.00
-1.00  0.00 12.50
-0.81 -0.59 13.00
-0.31 -0.95 13.50
 0.31 -0.95 14.00
 0.81 -0.59 14.50
 1.00 -0.00 15.00
 0.81  0.59 15.50
 0.31  0.95 16.00

各種演算¶

算術演算¶

In [44]:
# 以下全てにおいて要素ごとに各種算術演算がなされる
a = np.arange(4)
b = np.arange(4) + 4
In [45]:
a + b
Out[45]:
array([ 4,  6,  8, 10])
In [46]:
a - b
Out[46]:
array([-4, -4, -4, -4])
In [47]:
a * b
Out[47]:
array([ 0,  5, 12, 21])
In [48]:
a / b
Out[48]:
array([0.        , 0.2       , 0.33333333, 0.42857143])
In [49]:
a**2
Out[49]:
array([0, 1, 4, 9])

ユニバーサル関数¶

In [50]:
# degree to radian
np.deg2rad(90.0)
Out[50]:
1.5707963267948966
In [51]:
# radian to degree
np.rad2deg(np.pi/2)
Out[51]:
90.0
In [52]:
# lowest common multiple
np.lcm(4, 6)
Out[52]:
12
In [53]:
# greatest common divisor
np.gcd(12, 20)
Out[53]:
4
In [54]:
# 複素数の偏角
np.angle(1.0 + 1.0j)
Out[54]:
0.7853981633974483

メソッド¶

In [55]:
x = np.arange(10)
np.sum(x)
Out[55]:
45
In [56]:
x.sum()
Out[56]:
45
In [57]:
x.max()
Out[57]:
9
In [58]:
x.min()
Out[58]:
0
In [59]:
x.mean()
Out[59]:
4.5

インデックス操作¶

In [60]:
x = np.arange(10)
In [61]:
# 3番目の要素
x[2]
Out[61]:
2
In [62]:
# 3, 4, 5番目の要素(結果もNumPy配列)
x[2:5]
Out[62]:
array([2, 3, 4])
In [63]:
# 0, 2, 4, 6番目の要素に-1を代入
x[:8:2] = -1
x
Out[63]:
array([-1,  1, -1,  3, -1,  5, -1,  7,  8,  9])
In [64]:
# 順番を反転
x[::-1]
Out[64]:
array([ 9,  8,  7, -1,  5, -1,  3, -1,  1, -1])
In [65]:
# 最後の要素
x[-1]
Out[65]:
9
In [66]:
# 最後から2番目の要素
x[-2]
Out[66]:
8
In [67]:
# インデックス配列
i = np.arange(1, 10, 2)
i
Out[67]:
array([1, 3, 5, 7, 9])
In [68]:
# 指定された要素のみ2倍にする
x[i] *= 2
x
Out[68]:
array([-1,  2, -1,  6, -1, 10, -1, 14,  8, 18])
In [69]:
# 1つずらしたインデックス
x[i-1]
Out[69]:
array([-1, -1, -1, -1,  8])
In [70]:
# 1次元配列から2次元配列にreshape
y = np.arange(20).reshape((4, 5))
y
Out[70]:
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
In [71]:
# ':' は全ての要素
y[0,:]
Out[71]:
array([0, 1, 2, 3, 4])
In [72]:
# 2次元目のみ指定
y[:,1]
Out[72]:
array([ 1,  6, 11, 16])
In [73]:
# 各次元の2番目から4番目の要素のみ指定
y[1:3,1:3]
Out[73]:
array([[ 6,  7],
       [11, 12]])
In [74]:
# 1次元配列から3次元配列にreshape
z = np.arange(18).reshape((2, 3, 3))
z
Out[74]:
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8]],

       [[ 9, 10, 11],
        [12, 13, 14],
        [15, 16, 17]]])
In [75]:
# 3次元目のみ指定
z[...,0]
Out[75]:
array([[ 0,  3,  6],
       [ 9, 12, 15]])
In [76]:
# 1次元目と3次元のみ指定
z[1,...,0]
Out[76]:
array([ 9, 12, 15])
In [77]:
# 1次元目のみ指定
z[1]
Out[77]:
array([[ 9, 10, 11],
       [12, 13, 14],
       [15, 16, 17]])
In [78]:
# 配列の全要素に代入
x[:] = 10
x
Out[78]:
array([10, 10, 10, 10, 10, 10, 10, 10, 10, 10])
In [79]:
# 整数10をxに代入(xの配列を破棄されxはスカラーになる)
x = 10
x
Out[79]:
10
In [ ]: