1.3.3. より込み入った配列¶
1.3.3.1. さらなるデータ型¶
1.3.3.1.1. キャスト¶
“より広い”型が色んな型が混ざった演算で勝つ:
>>> np.array([1, 2, 3]) + 1.5
array([ 2.5,  3.5,  4.5])
代入は型を変更しません!:
>>> a = np.array([1, 2, 3])
>>> a.dtype
dtype('int64')
>>> a[0] = 1.9     # <-- float is truncated to integer
>>> a
array([1, 2, 3])
キャストの強制:
>>> a = np.array([1.7, 1.2, 1.6])
>>> b = a.astype(int)  # <-- truncates to integer
>>> b
array([1, 1, 1])
丸め:
>>> a = np.array([1.2, 1.5, 1.6, 2.5, 3.5, 4.5])
>>> b = np.around(a)
>>> b                    # still floating-point
array([ 1.,  2.,  2.,  2.,  4.,  4.])
>>> c = np.around(a).astype(int)
>>> c
array([1, 2, 2, 2, 4, 4])
1.3.3.1.2. データ型のサイズの違い¶
整数(符号付き):
| int8 | 8ビット | 
| int16 | 16ビット | 
| int32 | 32ビット(32ビットのプラットフォーム上の  | 
| int64 | 64ビット(64ビットのプラットフォームでの  | 
>>> np.array([1], dtype=int).dtype
dtype('int64')
>>> np.iinfo(np.int32).max, 2**31 - 1
(2147483647, 2147483647)
符号無し整数:
| uint8 | 8ビット | 
| uint16 | 16ビット | 
| uint32 | 32ビット | 
| uint64 | 64ビット | 
>>> np.iinfo(np.uint32).max, 2**32 - 1
(4294967295, 4294967295)
浮動小数点数:
| float16 | 16ビット | 
| float32 | 32ビット | 
| float64 | 64ビット( | 
| float96 | 96ビット、プラットフォーム依存(  | 
| float128 | 128ビット、プラットフォーム依存 ( | 
>>> np.finfo(np.float32).eps
1.1920929e-07
>>> np.finfo(np.float64).eps
2.2204460492503131e-16
>>> np.float32(1e-8) + np.float32(1) == 1
True
>>> np.float64(1e-8) + np.float64(1) == 1
False
浮動小数点数による複素数:
| complex64 | 2つの32ビット浮動小数点数 | 
| complex128 | 2つの64ビット浮動小数点数 | 
| complex192 | 2つの96ビット浮動小数点数、プラットフォーム依存 | 
| complex256 | 2つの128ビット浮動小数点数、プラットフォーム依存 | 
小さなデータ型
特殊なデータ型について知る必要があるのかわからない場合、おそらく知る必要はありません。
float64 の代わりに float32 を使って比較してみましょう:
- メモリとディスク上では半分のサイズになります 
- 必要となるメモリバンド幅も半分になります(いくつかの演算ではそれより高速かもしれません) - In [1]: a = np.zeros((1e6,), dtype=np.float64) In [2]: b = np.zeros((1e6,), dtype=np.float32) In [3]: %timeit a*a 1000 loops, best of 3: 1.78 ms per loop In [4]: %timeit b*b 1000 loops, best of 3: 1.07 ms per loop 
- しかし: 丸め誤差は大きくなります – ときおり驚くようなところで起きます (つまり、本当に必要なとき以外使わないで下さい) 
1.3.3.2. 構造化されたデータ型¶
| sensor_code | (4文字の文字列) | 
| position | (float) | 
| value | (float) | 
>>> samples = np.zeros((6,), dtype=[('sensor_code', 'S4'),
...                                 ('position', float), ('value', float)])
>>> samples.ndim
1
>>> samples.shape
(6,)
>>> samples.dtype.names
('sensor_code', 'position', 'value')
>>> samples[:] = [('ALFA',   1, 0.37), ('BETA', 1, 0.11), ('TAU', 1,   0.13),
...               ('ALFA', 1.5, 0.37), ('ALFA', 3, 0.11), ('TAU', 1.2, 0.13)]
>>> samples     
array([('ALFA', 1.0, 0.37), ('BETA', 1.0, 0.11), ('TAU', 1.0, 0.13),
       ('ALFA', 1.5, 0.37), ('ALFA', 3.0, 0.11), ('TAU', 1.2, 0.13)],
      dtype=[('sensor_code', 'S4'), ('position', '<f8'), ('value', '<f8')])
フィールドへのアクセスはフィールド名によるインデックスで動きます:
>>> samples['sensor_code']    
array(['ALFA', 'BETA', 'TAU', 'ALFA', 'ALFA', 'TAU'],
      dtype='|S4')
>>> samples['value']
array([ 0.37,  0.11,  0.13,  0.37,  0.11,  0.13])
>>> samples[0]    
('ALFA', 1.0, 0.37)
>>> samples[0]['sensor_code'] = 'TAU'
>>> samples[0]    
('TAU', 1.0, 0.37)
一度に複数のフィールド:
>>> samples[['position', 'value']]
array([(1.0, 0.37), (1.0, 0.11), (1.0, 0.13), (1.5, 0.37), (3.0, 0.11),
       (1.2, 0.13)],
      dtype=[('position', '<f8'), ('value', '<f8')])
例によってファンシーインデクスも動作します:
>>> samples[samples['sensor_code'] == 'ALFA']    
array([('ALFA', 1.5, 0.37), ('ALFA', 3.0, 0.11)],
      dtype=[('sensor_code', 'S4'), ('position', '<f8'), ('value', '<f8')])
1.3.3.3. maskedarray: 欠損値(とその伝達) を扱う¶
- 浮動小数点数ならばは NaN を使えますが、マスクは全ての型で動きます: - >>> x = np.ma.array([1, 2, 3, 4], mask=[0, 1, 0, 1]) >>> x masked_array(data = [1 -- 3 --], mask = [False True False True], fill_value = 999999) >>> y = np.ma.array([1, 2, 3, 4], mask=[0, 1, 1, 1]) >>> x + y masked_array(data = [2 -- -- --], mask = [False True True True], fill_value = 999999) 
- 通常の関数のマスク版: - >>> np.ma.sqrt([1, -1, 2, -2]) masked_array(data = [1.0 -- 1.41421356237... --], mask = [False True False True], fill_value = 1e+20) 
注釈
他の便利なものが array siblings にあります
numpy の章としては話題が外れますが、よいコーディング習慣について触れる時間をとりましょう、この時間は本当に、長い時間かけるのに値します:
良い習慣
- 明示的な変数名(変数が何なのかを説明するコメントが不要になります) 
- スタイル: カンマの後や - =の周り等にスペースを入れる。- “きれいな”ソースコードを書くためのいくつかの規則が Style Guide for Python Code. に与えられています (みんなで同じ規則を使う, という意味でもより重要です)。さらに (help の文字列を扱うための) Docstring Conventions ページもあります。 
- めったなことが無い限り、変数名とコメントは英語にしましょう。 
