0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで〇×ゲームのAIを一から作成する その203 numpy のデータ型

Last updated at Posted at 2025-11-18

目次と前回の記事

Python のバージョンとこれまでに作成したモジュール

本記事のプログラムは Python のバージョン 3.13 で実行しています。また、numpy のバージョンは 2.3.5 です。

以下のリンクから、これまでに作成したモジュールを見ることができます。本文で説明しますが、下記の ai.py は前回のファイルから修正を行っています

リンク 説明
marubatsu.py Marubatsu、Marubatsu_GUI クラスの定義
ai.py AI に関する関数
mbtest.py テストに関する関数
util.py ユーティリティ関数の定義
tree.py ゲーム木に関する Node、Mbtree クラスなどの定義
gui.py GUI に関する処理を行う基底クラスとなる GUI クラスの定義

AI の一覧とこれまでに作成したデータファイルについては、下記の記事を参照して下さい。

numpy のデータ型

これまでの記事では numpy のデータ型についてあまり詳しく説明してきませんでしたが、次回の記事の説明で必要となるので numpy のデータ型 について説明します。

Python の組み込みデータ型と区別できる ように、本記事では numpy のデータ型 を np.int64 のように 先頭に np. をつけて記述 することにします。この np は import numpy as np のように numpy を np という名前でインポートした場合のものです。

以前の記事で説明したように、ndarray は基本的に 同じデータ型のデータしか扱えない1という特徴があります。また、これまでの記事では説明していませんでしたが、ndarray のデータ型 は Python の int や str などの 組み込みデータ型とは異なるもの なので、その点に注意が必要です。例えば、Python の 整数 を表す 組み込みデータ型は int だけ ですが、ndarray で利用できる numpy モジュールで定義されている 整数を表すデータ型 には np.int8np.int16np.int32np.int64 などの 複数のデータ型 が存在します。

なお、numpy のデータ型は本記事で紹介する以外にも多数存在します。詳細は下記のリンク先を参照して下さい。

numpy のデータ型を表すクラス

numpy モジュールで利用できる データ型 は、Python の組み込みデータ型である int などと同様に クラスとして定義 されており、例えば np.int64 というデータ型のデータは下記のプログラムの np.int64(10) のように 実引数に整数を表すデータを記述 してそのインスタンスを作成することができます。

import numpy as np

i = np.int64(10)
print(i)
print(i.dtype)

実行結果

10
int64

ndarrayデータ型に関する情報は dtype 属性に記録 されており、print で表示すると そのデータ型を表す文字列 が上記のプログラムのように表示されます。

numpy のデータ型の種類や性質については後述します。

dtype 属性に代入されるデータは、numpy のデータ型に関する情報を記録するオブジェクトです。詳細は下記のリンク先を参照して下さい。

データ型を表す文字列

ndarray を作成 する np.arraynp.full などの関数は、キーワード引数 dtype で作成する ndarray の データ型を指定 することができます。その際にキーワード引数 dtype には np.int64 などのクラス以外にも データ型を表す文字列を記述 することもできます。

データ型を表す文字列 としては クラスの名前と同じ文字列 と、データ型を 短く表現する文字列2 種類を指定 できます。例えば後述する 1 バイトの整数型を表す np.int8 の場合は下記のプログラムのように "int8" または "i1" という文字列で指定できます。短いほうの "i1" のような記述方法についてはこの後で説明します。

なお、下記のプログラムでは 3 つの要素 を持つ 1 次元の ndarray を作成していますが、その場合の ndarray の 形状3 という 1 つの要素を持つ tuple で指定します。その際に、以前の記事で説明したように 要素が 1 つの tuple(3, ) のように () を省略できず、最初の要素の数値の後に , を記述する必要がある 点に注意して下さい。

a = np.full((3, ), 0, dtype=np.int8)
print(a)
print(a.dtype)
a = np.full((3, ), 0, dtype="int8")
print(a)
print(a.dtype)
a = np.full((3, ), 0, dtype="i1")
print(a)
print(a.dtype)

実行結果

[0 0 0]
int8
[0 0 0]
int8
[0 0 0]
int8

numpy では同じデータ型を表すクラスを別の名前で記述することができる場合があります。例えば np.in64 は下記のプログラムのように np.int_ と記述できます。

i = np.int_(10)
print(i)
print(i.dtype)

実行結果

10
int64

このようなクラス名などの 名前の別名 の事を エイリアス(alias)と呼び、np.int64np.int_ のエイリアスです。

上記の np.int_名前の最後に _ がついている のは、Python の 組み込みデータ型である int 型とは異なる データ型であることを 明確にするため です。他にも Python の bool に相当する numpy のクラスも np.bool_ のように命名されています。

ただし、下記のプログラムのようにキーワード引数 dtype に文字列としてデータ型を指定する場合は "int""bool" のように _ を省略してもかまわないようです。

a = np.full((3, ), 0, dtype="int_")
print(a)
print(a.dtype)
a = np.full((3, ), 0, dtype="int")
print(a)
print(a.dtype)
a = np.full((3, ), 0, dtype="bool_")
print(a)
print(a.dtype)
a = np.full((3, ), 0, dtype="bool")
print(a)
print(a.dtype)

実行結果

[0 0 0]
int64
[0 0 0]
int64
[False False False]
bool
[False False False]
bool

主な numpy のデータ型

numpy の主なデータ型 について紹介します。

整数型

numpy の 整数を表すデータ型 には、下記の表のように「符号の有無」と「データのサイズ」が異なる 複数のデータ型 があります。符号の有無 によって「0 以上の整数のみを表現する」か、「負の値も含めた整数を表現する」かが異なります。また、データのサイズ によって 表現できる整数の範囲 が異なります。「短縮」の列については後述します。

データ型 短縮 符号 バイト数 最小値 最大値
uint8 "u1" なし 1 0 255
uint16 "u2" なし 2 0 65535
uint32 "u4" なし 4 0 $2^{32} - 1$
(約 40 憶)
uint64 "u8" なし 8 0 $2^{64} - 1$
(約 2000 京)
int8 "i1" あり 1 -128 127
int16 "i2" あり 2 -32768 32767
int32 "i4" あり 4 $-2^{31}$
(約 -20 憶)
$2^{31} - 1$
(約 20 憶)
int64 "i8" あり 8 $-2^{63}$
(約 -1000 京)
$2^{63} - 1$
(約 1000 京)

numpy の整数型を表すクラスの名前は C 言語の整数型の名前を元に名づけられており、上記のデータ型はそれらのエイリアス(別名)です。C 言語が由来のクラス名については下記のリンク先を参照して下さい。

ただし、C 言語を知らない人にとっては上記のデータのサイズを元に命名されたエイリアスのほうがわかりやすいと思いますので、無理に C 言語が由来のクラス名を利用する必要はないと思います。

データ型の名前

numpy の整数型2のデータ型の名前は 符号(sign)なし の整数(integer)の場合は unsigned integer の略である uint符号あり の整数の場合は integer の略である int先頭に表記 し、その後に データサイズのビット数を表す数値 を並べた名前になります。1 バイトは 8 ビット なので uint8 のバイト数は $8 ÷ 8 = 1$ となります。

ndarray を作成する関数のキーワード引数 dtype には下記のいずれかを指定して上記の表の整数のデータ型を設定することができます。

  • np.データ型np.int8 など
  • データ型の文字列。"int8" など
  • 「短縮」の列の文字列。"i1" など。短縮の列の文字列符号あり の場合は i符号なし の場合は u の後に データサイズバイト数を表す数値 を並べて表記する

下記は np.int64 の ndarray を np.full のキーワード引数 dtype に上記の 3 種類のデータを指定して作成 するプログラムで、同じデータが作成される ことが確認できます。

i = np.full((3, ), 0, dtype=np.int64)
print(i)
print(i.dtype)
i = np.full((3, ), 0, dtype="int64")
print(i)
print(i.dtype)
i = np.full((3, ), 0, dtype="i8")
print(i)
print(i.dtype)

実行結果

[0 0 0]
int64
[0 0 0]
int64
[0 0 0]
int64

短縮された文字列でデータ型を表記する方法についての詳細は下記のリンク先を参照して下さい。

整数型のデータ型の精度

データ型が 表現できるデータの範囲 のことを 精度 と呼び、データサイズが大きい程精度が高くなり、表現できる整数の範囲が広くなります。

符号なし の numpy の整数型のデータは 2 進数でそのまま表現 されるので、8 ビット のデータで表現される np.uint88 桁の 2 進数00000000 から 11111111 までの $\boldsymbol{2^8 = 256}$ 種類 の整数を表現できます。0 から整数を表現 するので具体的には $\boldsymbol{0}$ ~ $\boldsymbol{2^8 - 1 = 255}$ までの範囲の整数を表現できます。他の符号なしの整数のデータ型も同様で、n ビット の符号なし整数の場合は $\boldsymbol{0}$ ~ $\boldsymbol{2^{n} - 1}$ の範囲の整数 を表現することができます。

符号あり の整数は 2 進数で表現できる数値の半分を 0 以上の値、残りの半分を負の値に割り当てるため、n ビット の符号あり整数の場合は $\boldsymbol{-2^{n-1}}$ ~ $\boldsymbol{2^{n-1} - 1}$ の範囲の整数 を表現することができます。具体的には 2 の補数 という方法で表現されますが、説明すると長くなるので詳細は下記のリンク先を参照して下さい。

ndarray がどのようにデータを記録しているかについては、前回の記事で紹介した tobytes メソッドの返り値を見ることで確認することができます。

ndarray のデータ型が 扱える範囲外の値 を ndarray の 要素に代入 しようとすると、下記のプログラムのように OverflowError というエラーが発生 します3。「Python integer 1000 out of bounds for int8」は「Python の int 型の 1000 は np.int8 の範囲外(out of bound)である」という意味です。

i = np.zeros((3, ), dtype=np.int8)
i[0] = 1000

実行結果

---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
Cell In[7], line 2
      1 i = np.zeros((3, ), dtype=np.int8)
----> 2 i[0] = 1000

OverflowError: Python integer 1000 out of bounds for int8

Python の整数を表す組み込みデータ型である int は公式のドキュメントに「整数には精度の制限がありません」と説明されているようにデータのサイズが決まっておらず、表現できる整数の範囲に制限はありませんが、numpy の整数型や Python 以外の多くのプログラム言語の整数型はデータのサイズが決まっており、表現できる整数の範囲に制限があります。

CPU が一度の計算で扱うことができるデータのサイズは決まっており、そのデータサイズのビット数を使って「64 ビットの CPU」のように CPU の性能を表記します。

細かい話になりますが np.int_ のデータサイズは CPU のビット数になるので、32 ビットの CPU では np.int32 が、64 ビットの CPU では np.int64np.int_ のエイリアスになります。筆者のパソコンの CPU は 64 ビットなので先程のように np.int_(10) のデータ型を表示すると int64 が表示されます。最近のコンピューターの CPU はほとんど 64 ビットだと思いますので、np.int_ は基本的には np.int64 と同じだと思って良いでしょう。

実は CPU のビット数の意味には計算できるデータのサイズ以外にもいくつかの種類があります。興味がある方は下記の Wikipedia のリンク先などを参照して下さい。

np.iinfo による整数型のデータ型の情報の表示

numpy の 整数型 のデータ型の 情報np.iinfo4 によって表示することができます。下記は np.uint16np.int16 の情報を np.iinfo で表示するプログラムで、実行結果のようにそれぞれのデータ型が 表現できる整数の範囲 が表示されます。興味がある方は他の numpy の整数のデータ型についても表示してみて下さい。

print(np.iinfo(np.uint16))
print(np.iinfo(np.int16))

実行結果

Machine parameters for uint16
---------------------------------------------------------------
min = 0
max = 65535
---------------------------------------------------------------

Machine parameters for int16
---------------------------------------------------------------
min = -32768
max = 32767
---------------------------------------------------------------

np.iinfo の詳細については下記のリンク先を参照して下さい。

浮動小数点数型

numpy の 浮動小数点数型を表すデータ型 は、下記の表のように データのサイズが異なる複数のデータ型 があり、データのサイズによって表現できる 数値の範囲有効桁数 などの 精度が異なります。なお、整数型と異なり浮動小数点数型には すべて符号があります

データ型 バイト数 有効桁数 最小値 最大値
float16 2 3 約 $-6.55 × 10^4$ 約 $6.55 × 10^4$
float32 4 6 約 $-3.40 × 10^{38}$ 約 $3.40 × 10^{38}$
float64 8 15 約 $-1.79 × 10^{308}$ 約 $1.79 × 10^{308}$

Python の浮動小数点数の組み込みデータ型である float は CPU のビット数によって異なり、一般的に 32 ビットの CPU の場合は np.float32、64 ビットの CPU の場合は np.float64 と同じ形式でデータを記録しているようです。

コンピュータの環境によっては 12 バイトと 16 バイトで浮動小数点数を表現する float96 と float128 を利用できる場合があるようですが、残念ながら筆者のコンピューターでは利用できませんでした。

データ型の名前

numpy の浮動小数点数型のデータ型の名前は float の後に データのビット数を表す数値 を並べた名前になります。例えば float16 のデータサイズは 16 ビットで、そのバイト数は $16 ÷ 8 = 2$ となります。

ndarray を作成する関数のキーワード引数 dtype には下記のいずれかを指定して上記の表の浮動小数点数型のデータ型を設定することができます。

  • np.データ型np.float16 など
  • データ型の文字列。"float16" など
  • 「短縮」の列の文字列。"f2" など。短縮の列の文字列f の後に データサイズバイト数を表す数値 を並べて表記する

下記は np.float64 の ndarray を np.full のキーワード引数 dtype に上記の 3 種類のデータを指定して作成 するプログラムで、同じデータが作成される ことが確認できます。

なお、numpy では 整数型浮動小数点数型 のデータを 区別できるように、numpy の 浮動小数点数型 のデータを print で表示する場合は、0 のような 整数であっても 下記の実行結果のように 小数点が表示されます

f = np.full((3, ), 0, dtype=np.float64)
print(f)
print(f.dtype)
f = np.full((3, ), 0, dtype="float64")
print(f)
print(f.dtype)
f = np.full((3, ), 0, dtype="f8")
print(f)
print(f.dtype)

実行結果

[0. 0. 0.]
float64
[0. 0. 0.]
float64
[0. 0. 0.]
float64

浮動小数点数型のデータ型の精度

浮動小数点数型 のデータの 精度 には、表現できる 数値の範囲 だけでなく、有効桁数 という 10 進数 で表記した際に 一番上の桁から何桁までの数値を正確に表現できるか を表す指標があります。例えば np.float16有効桁数は 3 なので、下記のプログラムのように 1.23456 に対する np.float16 のインスタンスを作成して print で表示すると、一番上の桁から 3 桁分の 1.234 まで の数値が表示されます。これは、有効桁数以後の数値np.float16 では表現できないので 捨てられた ことを意味します。

print(np.float16(1.23456))

実行結果

1.234

np.float16 が表現できる数値の 最大値 は約 $6.55 × 10^4$ = 約 65500 なので、下記のプログラムのように それ以上の数値を指定 すると 無限大(infinity)を表す 数値に変換されinf が表示 されます。また、その際に 表現可能な数値を超えた(overflow)ことを表す RuntimeWarning: overflow encountered in cast という 警告(warning)のメッセージが表示されます。なお、警告のメッセージは エラーではない ので、プログラムが 中断することはありません

print(np.float16(1000000))

実行結果

inf
C:\Users\ys\AppData\Local\Temp\ipykernel_263196\2302096247.py:1: RuntimeWarning: overflow encountered in cast
  print(np.float16(1000000))

浮動小数点数型のデータがどのようにデータを表現しているかはかなり複雑なので本記事では説明は省略しますが、有効桁数 と表現できる 数値の範囲決まっている ことだけは理解しておいてください。参考までに浮動小数点数の Wikipedia のリンクを下記に紹介しますので、興味がある方は勉強してみて下さい。

np.finfo による整数型のデータ型の情報の表示

numpy の 浮動小数点数型 のデータ型の 情報np.finfo5 によって表示することができます。下記は np.float64 の情報を np.finfo で表示するプログラムで、実行結果のように多くの情報が表示されますがその中の precision が有効桁数 を、min と max が最小値と最大値 を表します。その他の情報については下記の np.iinfo のドキュメントや、先ほどの Wikipedia の記事などを調べて下さい。

print(np.finfo(np.float64))

実行結果

Machine parameters for float64
---------------------------------------------------------------
precision =  15   resolution = 1.0000000000000001e-15
machep =    -52   eps =        2.2204460492503131e-16
negep =     -53   epsneg =     1.1102230246251565e-16
minexp =  -1022   tiny =       2.2250738585072014e-308
maxexp =   1024   max =        1.7976931348623157e+308
nexp =       11   min =        -max
smallest_normal = 2.2250738585072014e-308   smallest_subnormal = 4.9406564584124654e-324
---------------------------------------------------------------

bool(論理) 型

numpy にも Python の組み込みデータ型である bool と同様TrueFalse2 種類のデータ を表す np.bool_6 というデータ型があります。nbp.bool_1 バイトで表現 されるデータで内部では True を整数の 1False を整数の 0同じデータで表現 します7

ndarray を作成する関数のキーワード引数 dtype には下記のいずれかを指定して numpy の bool 型のデータ型を設定 することができます。

  • np.bool_ またはそのエイリアスである np.bool
  • 文字列の "bool_" または "bool" または "?"

下記は np.bool_ の ndarray を np.full のキーワード引数 dtype に上記の 5 種類のデータを指定して作成 するプログラムです。実行結果から "?" 以外 を指定した場合に 同じデータが作成される ことが確認できます。

b = np.full((3, ), False, dtype=np.bool_)
print(b)
print(b.dtype)
b = np.full((3, ), False, dtype=np.bool)
print(b)
print(b.dtype)
b = np.full((3, ), False, dtype="bool_")
print(b)
print(b.dtype)
b = np.full((3, ), False, dtype="bool")
print(b)
print(b.dtype)
b = np.full((3, ), False, dtype="?")
print(i)
print(i.dtype)

実行結果

[False False False]
bool
[False False False]
bool
[False False False]
bool
[False False False]
bool
[0 0 0]
int8

dtype"?" を指定した場合は すべての要素が 0np.int8 の ndarray が作成されますが、以下の理由からこの場合も 同じデータが作成 されています。

  • np.int8np.bool_ のデータサイズは同じ 1 バイトである
  • np.bool_ では Falsenp.int80 と同じデータで記録する

同じデータが記録される ことは、下記のプログラムのように tobytes で記録されたデータを表示 した際に、同じ内容が表示 されることから確認することができます。

print(np.full((3, ), False, dtype=np.bool_).tobytes())
print(np.full((3, ), False, dtype="?").tobytes())

実行結果

b'\x00\x00\x00'
b'\x00\x00\x00'

文字列型

numpy には ユニコードの文字列 を表す np.str_ 型があります。np.str_ はユニコードの 1 文字を 4 バイトで表現 する UTS4 という形式でデータを記録するので、1 文字あたりのデータサイズは 4 バイト です。

文字列型の ndarray作成した時点 で要素に代入できる 文字列の長さが決まり後から変更できない という性質がある点に注意が必要です。その理由についても説明します。

以前の記事で説明したように、コンピューターは文字を数値で表現し、数値で表現された文字のことを文字コード、文字と文字コードを対応づける表の事を文字コード表と呼びます。ユニコードは世界中の文字を表現できる文字コード表で、近年ではコンピューターで文字を記録する際に標準的に利用されています。

ユニコードをデジタルデータとしてメモリやファイルに記録する方式のことを文字符号化形式と呼び、UTF-8、UTF-16、UTF-32 が定められています。上記の UTS4 は UTF-32 のことで 1 文字を必ず 4 バイトで表現しますが、良く使われている UTF-8 という形式は 1 文字を文字の種類によって異なる 1 ~ 4 バイトで表現します。

興味がある方は下記のリンク先を参照して下さい。

np.str_ の文字数と np.str_ の ndarray が記録できる文字列の長さ

np.str_ は Python の組み込みデータ型の str と同様に インスタンスを作成した際 に記述した文字列の 文字数によってその長さが決まり まる。また、str と同様に イミュータブルなデータ型 なので、後から 文字列の内容を変更することはできません

例えば、下記のプログラムは 3 文字の "abc" を指定して np.str_ のインスタンスを作成するので、作成された np.str_ のインスタンスの 文字列の長さは 3 文字 になります。

s = np.str_("abc")
print(s)
print(len(s))

実行結果

abc
3

記録する文字数の長さ によって np.str_ のデータには 異なる長さのデータが記録 されるので、そのことを 区別するため に以後は n 文字の np.str_ のデータを「n 文字の np.str_」のように表記することにします。

numpy では n 文字np.str_ のデータ型を "<Un" のように "<U"8 の後 に文字列の 文字数を表す数値を並べた文字列 で表現します。例えば、上記の 3 文字の np.str_ のデータ型print で表示すると 実行結果のように <U3 が表示されます。

print(s.dtype)

実行結果

<U3

"<U5" の先頭の < という記号はエンディアンという、複数バイトのデータを記録する際の方式を表します。エンディアンの概念は少し複雑でわかりにくいもので、その違いを正しく理解していないといけない状況は存在するのですが、ほとんどの場合はその違いを気にする必要なくプログラムを記述することができます。

〇× ゲームのプログラムを作成する際にエンディアンを気にする場面はおそらくないと思いますので説明は省略します。参考までに Wikipedia のエンディアンの項目のリンクを下記に示します。

np.str_ を要素として持つ ndarray の性質

ndarray は原則として すべての要素同じデータ型のデータを記録 します。これは、すべての要素同じ長さのデータで記録する ということなので、np.str_ の場合はすべての要素で記録できる 文字列の長さの最大値が同じ になります。

np.str_ を要素として持つ ndarray の要素に記録できる 文字列の文字数の最大値 は、以下の方法で決まります。

  • np.array の実引数に 文字列のみを要素として持つ list を記述して作成した場合は、list の要素の中で 最も長い文字列の長さ になる
  • dtype"<U3" のような 文字数を含めた np.str_ を表す データ型を記述 した場合は 指定した文字数 になる

下記は上記の方法で np.str_ の ndarray を作成するプログラムです。一つ目の ndarray は 文字列のみを要素として持つ list から作成 していますが、list の要素の 最も長い文字列の長さ 3 なので、実行結果の <U3 のように 3 文字np.str_ の ndarray が作成されます。2 つ目は dtype"<U5" を指定しているので 5 文字np.str_ の ndarray が作成されます。

s1 = np.array(["a", "bc", "def"])
print(s1)
print(s.dtype)
s2 = np.full((3, ), "", dtype="<U5")
print(s2)
print(s2.dtype)

実行結果

['a' 'bc' 'def']
<U3
['' '' '']
<U5

dtype に長さを含めた文字列型を表す文字列を記述する場合は dtype="U5" のように先頭のエンディアンを表す < を省略することができます。

n 文字の np.str_ の ndarray の要素には 上記の s1"a" の要素のように n 文字未満 の文字列を 代入することができます が、n 文字より長い文字列を代入することはできず、代入しようとした場合はエラーにはなりませんが、下記のプログラムの実行結果のように n 文字目以降の文字は切り捨てられます

s2[0][0] = "abcdefg"
print(s2)

実行結果

['abcde' '' '']

n 文字の np.str_ の ndarray の要素に n 文字未満の文字列を代入した場合でも、下記の方法でその要素のデータには n 文字分のデータが記録されます。

文字列を表すデータでは 0 という数値が文字列の終了を表し、n 文字の np.str_ の ndarray の要素に n 文字未満の文字列を代入した場合は、残りの文字を表す部分に 0 を記録します。例えば上記の s1 に代入しあ 3 文字の np.str_ の ndarray の最初の要素である "a" を表すデータは 1 文字なので、最初の 4 バイトに 1 文字目の "a" を表す数値が記録され、残りの 2 文字分の 8 バイトに 0 が記録されます。

ndarray を作成した際のデータ型

ndarray を作成した際 の ndarray の データ型 について説明します。

仮引数 dtype を記述した場合の ndarray のデータ型

ndarray のデータ型np.arraynp.full などの ndarray を作成する関数の キーワード引数 dtype によって設定 することができますが、その際の注意点について説明します。

記述したデータと dtype のデータ型が異なる場合の処理

np.arraynp.full などで記述した ndarray の要素のデータdtype で指定したデータ型が異なる場合 は、dtype で指定した データ型への変換 が行われます。

下記のプログラムのように、整数型を浮動小数点数型に変換 する場合は 同じ値の浮動小数点数に変換されます

ndarray = np.array([1, 2, 3], dtype=np.float64)
print(ndarray)
print(ndarray.dtype)

実行結果

[1. 2. 3.]
float64

一方、浮動小数点数型を整数型に変換 する場合のように、正確に変換できない場合一部のデータが捨てられる ことになります。例えば 1.5 のような整数でない値を np.int64 に変換 すると、実行結果のように 小数点以下の値が切り捨てられる ようです。

ndarray = np.array([1.0, 1.5, 2.0], dtype=np.int64)
print(ndarray)
print(ndarray.dtype)

実行結果

[1 1 2]
int64

なお、整数型を浮動小数点数型に変換 する場合でも、有効桁数が足りない ことが原因で 正確に変換できない 場合があります。下記のプログラムは 123456789有効桁数が 6 桁の np.float16 に変換 しようとしたため、有効桁数の先頭の 1 から右に 6 桁分の 1234567 まで は正確に変換できていますが、その先が正しく変換できない ため 1.2345679e+08 = 123456790 に変換されています。なお、e+08 は $10^8$ を表す指数表記です。

ndarray = np.array([123456789], dtype=np.float32)
print(ndarray)
print(ndarray.dtype)

実行結果

[1.2345679e+08]
float32

上記から、変換前と変換後のデータ型の精度の違い によって 正しく変換されない場合がある 点に注意が必要です。

変換できないデータ型を指定した場合

dtype で指定したデータ型に 変換することができない場合はエラーが発生 します。下記のプログラムは np.full で作成する ndarray の要素に dtype で指定した 整数型である np.int64 に変換できない "a" という文字列を記述 したためエラーが発生します。

print(np.full((3, ), "a", dtype=np.int64))

実行結果

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[18], line 1
----> 1 print(np.full((3, ), "a", dtype=np.int64))

File c:\Users\ys\Anaconda3\envs\marubatsu313\Lib\site-packages\numpy\_core\numeric.py:387, in full(shape, fill_value, dtype, order, device, like)
    385     dtype = fill_value.dtype
    386 a = empty(shape, dtype, order, device=device)
--> 387 multiarray.copyto(a, fill_value, casting='unsafe')
    388 return a

ValueError: invalid literal for int() with base 10: np.str_('a')

仮引数 dtype を省略した場合の ndarray のデータ型

仮引数 dtype はデフォルト引数として設定 されているので 省略することができ、省略した場合に作成される ndarray のデータ型 は下記のように 関数によって異なります

下記で紹介する以外の関数については下記の numpy のドキュメントを参照して下さい。

np.array の場合

list などから ndarray を作成 する np.array の場合は、list の要素から 自動的に ndarray のデータ型が決まります。下記のプログラムは、様々な要素を持つ list から ndarray を作成し、その データ型を表示 するプログラムです。

datalist = [
    [1, 2, 3],           # int(整数)のみを要素とする list
    [1.0, 1.5, 2.0],     # float(浮動小数点数)のみを要素とする list
    ["a", "b", "c"],     # 1 文字の str(文字列)のみを要素とする list
    ["a", "bc", "def"],  # 最長 3 文字の str(文字列)を要素とする list
    ["", "", ""],        # 0 文字の str(文字列)のみを要素とする list
    [True, False],       # bool(論理型)を要素とする list
    [1, 2.0],            # int と float が混じった list
    [1, "a"],            # int と str が混じった list
]

for data in datalist:
    ndarray = np.array(data)
    print(ndarray)
    print(ndarray.dtype)

実行結果

[1 2 3]
int64
[1.  1.5 2. ]
float64
['a' 'b' 'c']
<U1
['a' 'bc' 'def']
<U3
['' '' '']
<U1
[ True False]
bool
[1. 2.]
float64
['1' 'a']
<U21

実行結果から以下の事が確認できます。なお、Python では 小数点をつけた数値は float であるとみなされる ので、1.1.0 は float のデータです。

  • int(整数型)の 要素のみ を持つ場合は np.int64 になる9。numpy の整数型の要素は 1 のように小数点のない形式で表示される
  • float(浮動小数点数型)の 要素のみ を持つ場合は np.float64 になる。numpy の浮動小数点型の要素は 1 のような整数であっても 1. のように小数点が表示される
  • str(文字列型)の 要素のみ を持つ場合は、先程説明したように要素の中で 最も長い文字列と同じ長さの np.str_ になる。ただし、文字列の長さが 0 の "" のみを要素として持つ場合でも、最低でも 1 文字の np.str_ になる
  • bool(論理型)の要素のみを持つ場合は np.bool_ になる
  • int と float 型の要素が混在している場合は np.float64 になる
  • int と str の要素が混在している場合は np.str_ になる10

np.array の詳細については下記のリンク先を参照して下さい。

np.zerosnp.ones の場合

すべての要素が 0 の ndarray を作成する np.zeros は、下記のプログラムのようにキーワード引数 dtypes を記述しない場合 のデータ型は np.float64 になり、記述した場合はそのデータ型になります。

ndarray = np.zeros((5, ))
print(ndarray)
print(ndarray.dtype)
ndarray = np.zeros((5, ), dtype=np.int64)
print(ndarray)
print(ndarray.dtype)

実行結果

[0. 0. 0. 0. 0.]
float64
[0 0 0 0 0]
int64

なお、np.bool_False を内部では整数の 0 で表現 しているので、下記のプログラムのように np.zerosnp.bool_ の ndarray を作成 した場合は実行結果のように False を要素とする ndarray が作成 されます。同様の理由で すべての要素が 1 の ndarray を作成する np.onesnp.bool_ の ndarray を作成 した場合は実行結果のように True を要素とする ndarray が作成 されます。

print(np.zeros((3, ), dtype=np.bool_))
print(np.ones((3, ), dtype=np.bool_))

実行結果

print(np.zeros((3, ), dtype=np.bool_))
print(np.ones((3, ), dtype=np.bool_))

np.zerosnp.ones の詳細については下記のリンク先を参照して下さい。

np.full の場合

すべての要素が指定した値 になる ndarray を作成する np.full の場合は、下記のプログラムの実行結果のように指定した値の Python のデータ型に対応した numpy のデータ型の ndarray が作成されます。

datalist = [
    1,      # int
    1.5,    # float
    "a",    # 1 文字の str
    "abc",  # 3 文字の str
    True,   # bool
]

for data in datalist:
    ndarray = np.full((5, ), data)
    print(ndarray)
    print(ndarray.dtype)

実行結果

[1 1 1 1 1]
int64
[1.5 1.5 1.5 1.5 1.5]
float64
['a' 'a' 'a' 'a' 'a']
<U1
['abc' 'abc' 'abc' 'abc' 'abc']
<U3
[ True  True  True  True  True]
bool

実行結果からわかるように作成される ndarray のデータ型np.arrayすべてが同じデータ型の要素を持つ list から ndarray を作成した際と 同じになります

np.full の詳細については下記のリンク先を参照して下さい。

ndarray の astype メソッドによるデータ型の変換

ndarray には、別の numpy のデータ型 に ndarray を 変換する astype メソッドがあり、例えば下記のプログラムのように 実引数に変換後のデータ型を記述 することで np.int64 の ndarray を np.float64 の ndarray に 変換する ことができます。

ndarray = np.array([1, 2, 3])
print(ndarray)
print(ndarray.dtype)
ndarray2 = ndarray.astype(np.float64)
print(ndarray2)
print(ndarray2.dtype)

実行結果

[1 2 3]
int64
[1. 2. 3.]
float64

なお、先ほど説明したように データ型の精度が異なる ことが原因で、異なるデータ型に 正しく変換できない場合がある 点に注意して下さい。

異なるデータ型どうしの演算結果

比較演算子以外 の演算子で 同じ numpy のデータ型どうしの計算 を行った場合は、基本的に計算結果の データ型は変化しません が、異なる numpy のデータ型 の演算を行った場合の 計算結果のデータ型には注意する必要 があります。

比較演算子の計算

比較演算子 は、計算する データの種類に関わらず True または False を計算 します。そのため、下記のプログラムのように 比較演算子の計算 を行うと np.bool_ になります。b3b4 のように ndarray に対する比較演算子の演算結果は np.bool_ の ndarray になります。

# np.int64 と np.float64 の比較
b1 = np.int64(10) == np.float64(10)
print(b1)
print(b1.dtype)
# np.int64 と Python の int の比較
b2 = np.int64(10) == 10
print(b2)
print(b2.dtype)
# np.int64 と np.float64 の ndarray の比較
a1 = np.array([1, 2, 3])
a2 = np.array([2., 2., 2.])
b3 = a1 <= a2
print(b3)
print(b3.dtype)
# np.int64 と Python の int の比較
b4 = a1 > 1
print(b4)
print(b4.dtype)

実行結果

True
bool
True
bool
[ True  True False]
bool
[False  True  True]
bool

Python の数値型と numpy の数値型の計算

異なる numpy のデータ型 に対して 比較演算子以外 の計算を行った場合は 基本的にはより精度が高いデータ型のデータ が計算されます。例えば下記のプログラムのように np.int8np.int16 の加算 を行うと より精度が高い np.int16 が計算 されます。

i1 = np.int8(10)
i2 = np.int16(20)
i3 = i1 + i2
print(i3)
print(i3.dtype)

実行結果

30
int16

だたし、必ずしも精度が高いデータ型が計算されない場合もあるようです。筆者も完全に理解しているわけでありませんが、異なる numpy のデータを計算 した際に、思ったような計算結果にならなかった場合 は計算結果の データ型を確認する ことをお勧めします。

詳細は下記のリンク先を参照して下さい。

どの numpy のデータ型を利用すべきか

ndarray を利用する際注意すべき点 は、以下の通りです。

  • ndarray に 記録するデータ が「整数」、「浮動小数点数」、「文字列」、「論理値」の いずれかであるか
  • 記録する データの精度 は何か
    • 整数の場合は数値の範囲
    • 浮動小数点数の場合は数値の有効桁数と範囲
    • 文字列の場合は文字数
    • 論理値の場合は True と False しか値がないので精度を気にする必要はない
  • 要素の数が多い場合などで、データサイズが重要 になる場合
  • 処理速度が重要 になる場合

データ型の種類に関する注意点

データ型の種類 に関しては下記の点に注意すると良いでしょう。

np.array で list から ndarray を作成する場合

np.array を利用して list から ndarray を作成 する場合は、ndarray の要素として 整数以外の数値を計算したい場合 は list の要素が整数であっても [1.0, 2.0] のように小数点をつけるのを忘れない ようにして下さい。その場合のデータ型は np.float64 になりますが、後述するデータサイズや処理速度が重要でない場合は np.float64 をそのまま利用して問題ない と思います。

逆に 整数しか利用しない場合小数点をつけてはいけません。その場合のデータ型は np.int64 になりますが、データサイズや処理速度が重要でない場合は np.int64 をそのまま利用して問題ない と思います。

list の要素の値のデータ型 が何であるかに 自信が持てない場合dtype=np.int32 のように 具体的なデータ型を指定 すると良いでしょう。

文字列型 のデータを利用したい場合は ndarray の要素に代入したい 文字列の最大長を考慮する必要 があります。list の要素 の中に記録されている 文字列の最大の長さが何であるかに自信が持てない場合dtype=<U10" のように dtype で文字列の長さを指定するべき です。

np.full で ndarray 作成する場合

np.full で要素の値を指定して ndarray を作成する場合の注意点は np.array で作成する場合の注意点と同じ です。

np.zeros で ndarray を作成する場合

dtype を記述しない場合np.float64 になるので、それ以外のデータ型を利用したい場合dtypeデータ型を指定する 必要があります。整数型 の場合は特に理由がなければ np.int64 または "int" を指定 すればよいと思います。

データサイズに関する注意点

要素の数が少ない場合データサイズについて気にする必要はありません が、要素の数が多い場合データサイズが重要になる 場合があります。

ndarray の要素全体データサイズ は、「データ型のデータサイズ × 要素の数」になります。また、その値は ndarray の nbytes11属性で確認 することができます。

要素の数が多くなるメモリにデータが収まりきらなくなる場合がある ので、そのような場合は データサイズが小さいデータ型を選択する必要 が生じます。例えば、10000 以下の整数しか扱わない ことがわかっている場合は、2 バイトの np.int16 を 8 バイトの np.int64 の代わりに利用することで、全体のデータサイズを 1/4 にする ことができます。

下記は 10000 個の要素 を持つ np.int16np.int64データサイズを表示 するプログラムで、実行結果から実際に データサイズが 4 倍違う ことが確認できます。

a1 = np.zeros((10000, ), dtype=np.int16)
print(a1.nbytes)
a2 = np.zeros((10000, ), dtype=np.int64)
print(a2.nbytes)

実行結果

20000
80000

下記は 1 兆個 の要素を持つ ndarray を作成するプログラムです。np.float64データサイズは 8 バイト なので、この ndarray の要素の データサイズ は 8 兆 = 8 T(テラ)バイト になります。現在のコンピュータのメモリサイズ数十 GB なので、このような ndarray のデータをメモリに記録することはできず、実行結果のように MemoryError が発生 します。

np.zeros((1000000000000,))

実行結果

---------------------------------------------------------------------------
MemoryError                               Traceback (most recent call last)
Cell In[30], line 1
----> 1 np.zeros((1000000000000,))

MemoryError: Unable to allocate 7.28 TiB for an array with shape (1000000000000,) and data type float64

処理速度に関する注意点

numpy の関数によってデータ型によって処理速度が変わる場合がある ようです。その点については次回の記事で説明します。なお、処理速度が重要でない場合データ型の種類について気にする必要はない と思います。

今回の記事のまとめ

今回の記事では、numpy のデータ型について説明しました。次回の記事では処理速度に関する説明を行い、numpy を利用した別の方法で〇×ゲームのゲーム盤を表現する方法について説明する予定です。

本記事で入力したプログラム

リンク 説明
marubatsu.ipynb 本記事で入力して実行した JupyterLab のファイル

次回の記事

  1. 例外として ndarray の要素に Python のオブジェクトを記録するデータ型も存在しますが、その場合は numpy の強みを活かすことができなくなるのであまり利用されないのではないかと思います。本記事では説明は省略しますが、興味がある方はこちらのリンク先を参照して下さい

  2. 整数型のデータは一般的には固定小数点数型と呼びますが、本記事では整数型と表記することにします。固定小数点型の名前の意味は小数点の位置が固定されていることが由来です。詳細はこちらのリンク先を参照して下さい

  3. overflow はあふれるという意味の英単語で、プログラム言語では表現できる数値の範囲を超えたことを意味します

  4. iinfo は整数型(integer)の情報(information)の略だと思います

  5. finfo は浮動小数点数型(float)の情報(information)の略だと思います

  6. 最後に _ をつけるのは、Python の組み込みデータ型である bool とは異なるデータ型であることを明確にするためです

  7. 多くのプログラム言語では bool 型と同様のデータ型の true を整数の 1、false を整数の 0 で表現するようです

  8. "<U5" の U はユニコード(Unicode)の U を表します

  9. 説明は省略しますが、np.int64 で表現できる範囲を超えた整数を記述した場合は np.int64 とは別のデータ型になります

  10. この場合の numpy の文字列の長さは上記では <U21 のように 21 文字になるようですが、この文字数は必ずしも 21 文字になるわけではなく、list の要素の値によって変換するようです

  11. number of bytes の略です

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?