NumPyには、ndarrayの永続化方法としてsave
、load
関数があります。これらの関数を使うことで、PythonとNumPyから利用するだけであれば、データベースやファイル形式に悩むことなく簡単にデータを保存することができます。
np.save
やnp.load
を使うと、pickle
やnpy
、npz
形式のファイルを読 み書きすることでndarray
との変換をすることができます。
np.loadtext
とnp.savetxt
関数を使用することで、このような問題を解決しながらNumPyとデータ互換を維持することができます。今回はこのnp.loadtext
とnp.savetxt
を中心にデータの欠損がある箇所を適切な値で埋めてくれるgenfromtxt
関数を紹介します。
それぞれの関数の特徴
まずはそれぞれの関数の特徴をまとめます。
np.load
、np.save
関数の特徴
- 配列をそのまま保存できる、3次元以上の配列も保存可能
- 対応拡張子は
pickle
、npz
、npy
- ただし、扱うファイル形式は他のアプリケーションなどとの互換性はほとんどない
np.loadtxt
、np.savetxt
関数の特徴
- 他のアプリケーションと互換性のある.dat、.csv、.txt形式のファイルの読み書きができる
- 保存できる配列の次元は二次元まで
今回はnp.loadtxt
とnp.savetxt
関数について解説していきます。
np.savetxt、np.loadtxt
np.loadtext
関数のAPIドキュメントは以下の通りです。
np.loadtxt関数
numpy.loadtxt(fname, dtype=float, comments=’#’, delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding=’bytes’, max_rows=None, quotechar=None, like=None)
params:
パラメータ名 | 型 | 概要 |
---|---|---|
fname |
ファイル、文字列 またはファイルのパス |
読み込むファイルを指定します・拡張子が.gzや.bz2のときはまず解凍します。 |
dtype |
データ型 | (省略可能)初期値’float’ 出力される配列のデータ型を指定します。辞書型やタプルの配列を指定することで簡易的にCSVのような構造化データを読むこともできます |
comments |
文字列またはシーケンス | (省略可能)初期値’#’ ファイルの内容におけるコメント部分が何で始まっているのかを指定します。 |
delimiter |
文字列(string) | (省略可能)初期値None 値と値を区切る文字が何であるかを指定する。デフォルトはスペース区切り。 |
converters |
辞書(dict)もしくはcallable(関数等) | (省略可能)初期値None 値の解析をカスタマイズするためのコンバータ関数。 convertersが関数で実行可能な場合、その関数はすべての列に適用されます。 そうでない場合、列番号をキーにして 値をパーサー関数にマップする辞書型である必要があります。 |
skiprows |
int もしくは シーケンス |
(省略可能)初期値0 何行文読み飛ばすかを指定します。 |
usecols |
intもしくは シーケンス |
(省略可能)初期値None 0を最初の行として、どの行を読み取るのかを指定します。デフォルトでは全ての列を読み取ります。 |
unpack |
bool値 | (省略可能)初期値False Trueにすると出力される配列は転置(transpose)されます。各々の列の値を別々の変数に代入したいときなどに用いられます。 |
ndmin |
int 有効なのは0,1,2 |
(省略可能)初期値0 返される配列の最低次元数を指定します。ここが指定されないと要素数が1の次元の軸(axes)に関しては次元の削減が行われます。 |
encoding |
string | (省略可能)初期値'bytes' 。ファイルを読み込む際に使う文字コードを指定する。 ‘bytes’は特別な値で後方互換性のため、可能な限りバイト配列を受け渡し可能になり、 'latin1' エンコーディングの文字列を渡せるようになります。None でシステムのデフォルトが使用されます。 |
quotechar |
ユニコード文字または None | (省略可能)初期値None。 ひとつのフィールドとして認識させるため引用文字の開始と終了を示すために使用される文字。 引用フィールド内では、delimiterやコメント文字は無視される。 これは引用サポートが無効であることを意味する。 引用フィールド内にquotecharが連続して2回現れる場合、最初のものはエスケープ文字として扱われる |
like |
array_like | NumPy配列以外の参照オブジェクトで生成します。__array_function__ プロトコルを継承しているオブジェクトを指定することができます |
returns:
ファイルから読み込まれたデータが出力されます。
このloadtxt
関数には9つもの引数が存在しています。これらを用いてどのような形でファイルを読み込んでいくかを詳細に指定することができます。引数を詳細に指定することで、様々な形式に対応することができます。
np.savetxt関数
次に、savetxt
関数のAPIドキュメントを見ていきます。
numpy.savetxt(fname, X, fmt=’%.18e’, delimiter=’ ‘, newline=’\n’, header=’’, footer=’’, comments=’#’, encoding=None)
params:
パラメータ名 | 型 | 概要 |
---|---|---|
fname |
ファイル名または ファイル・ハンドル |
保存するファイルを指定します。.gzが拡張子のときはgzip形式のファイルとして保存します。 |
X |
array_like (配列に相当するもの) |
保存データを指定します。 |
fmt |
stringまたは stringのシーケンス |
(省略可能)初期値’%.18e’ それぞれの列ごとにおける有効桁数を指定します。 |
delimiter |
string | (省略可能)初期値’ ‘ 列ごとを区切る文字を指定します。 |
newline |
string | (省略可能)初期値’\n’ 行ごとを区切る文字を指定します。 |
header |
string | (省略可能)初期値’‘ ファイルの最初に何を書き込むかを指定します。 |
footer |
string | (省略可能)初期値’‘ ファイルの最後に何を書き込むかを指定します。 |
comments |
string | (省略可能)初期値’#’ headerやfooterを挿入する際、先頭に入力する文字を指定します。 |
encoding |
string or None | 出力ファイルに使用されるエンコード。 出力ストリームには適用されません。デフォルトは 'latin1' です。 |
どちらも引数が多いですが、参照しながらどのような形式で読み書きしたいのかを考えて使いこなしていきましょう。
サンプルコード
では、この2つの関数を使って実際にコードを見ながら使い方を見ていきます。まずはシンプルにファイルの書き込み、読み込みをしていきます。
次は区切り文字を変えていきます。,
に変更してみましょう。
実際にファイルを開いて見てどうなっているか確認してみましょう。
-9.849506405118685359e-01,-5.410541661151561099e-01,1.052582274254199479e+00,1.071015596176571272e+00
1.311936581354347986e+00,1.093439550506633662e+00,-1.297775904738235564e+00,7.832240368728708990e-01
-1.543443447806609692e+00,-1.465546557520085447e+00,4.028518723924314759e-01,1.302891977491596742e-01
ちなみに、先ほど使用したsample.txt
の方はどうなっているのでしょうか。
-9.849506405118685359e-01 -5.410541661151561099e-01 1.052582274254199479e+00 1.071015596176571272e+00
1.311936581354347986e+00 1.093439550506633662e+00 -1.297775904738235564e+00 7.832240368728708990e-01
-1.543443447806609692e+00 -1.465546557520085447e+00 4.028518723924314759e-01 1.302891977491596742e-01
こちらはデフォルト通り、スペースでデータが区切られていますね。では、,
で区切ったテキストファイルを読み込んでみます。
np.savetxt
関数ではデータを保存する際に有効桁数を指定することができます。デフォルトで指定されている’%.18e’というのは小数点以下18桁まで表示し、オーダーをe+08
やe-01
のような形式で表すことを示します(1番大きい桁が1の位に来るように表記されるということです)。
’%.18f’にすると小数点以下18桁まで表示されますがオーダーを表す記号が存在せず、322.248..
のように表示されます。整数部の上限もつけることができ’%3.f’とすれば1000の位までしか表記できなくなります。
dtype = complex
(複素数)のときは’%.3e + .2ej’のように表すことができます。タプルやリストの形式で複数の列に対して個々の有効桁数を指定することができます。
有効桁数2桁でまずはやってみましょう。
ファイルの中身は以下のようになっています。
-9.85e-01 -5.41e-01 1.05e+00 1.07e+00
1.31e+00 1.09e+00 -1.30e+00 7.83e-01
-1.54e+00 -1.47e+00 4.03e-01 1.30e-01
では次はeからfに変えて見ます。
ファイルの中身は以下のようになります。
-0.98 -0.54 1.05 1.07
1.31 1.09 -1.30 0.78
-1.54 -1.47 0.40 0.13
eの表記が消えたのがわかるでしょうか。次は複素数を保存して見ます。
もちろん実部虚部を別々に指定せず'%.2e'
のようにして両方とも同じ値を設定することもできます。ファイルの中身を見て見ましょう。
1.010e+01 + 3.210e+00j 1.0e+02 + 3.2e+01j
2.000e+01 + 2.000e-01j 2.2e+01 + -1.0e+00j
ちゃんと指定した有効桁数通りになっていますね。
次はloadtxt
で抜き出す列や行を変えていきます。sample4.txt
を使っていきます。
次はheader
とfooter
を指定します。最初の乱数配列であるa
を保存します。
中身を確認してみます。
# this is a header
-9.850e-01 -5.411e-01 1.053e+00 1.071e+00
1.312e+00 1.093e+00 -1.298e+00 7.832e-01
-1.543e+00 -1.466e+00 4.029e-01 1.303e-01
# this is a footer
#
を頭文字としてちゃんと入力されていることがわかりますね。では、ここの#
の部分を>>>
に変えてみましょう。np.loadtxt
を使って対象行を無視してみます。
np.loadtxt
,np.savetxt
共にcomments
に指定すれば対象行を無視することができます。
ファイルの中身も確認しておきましょう。sample8.txt
の中身を見て見ます。
>>>this is a header
-9.850e-01 -5.411e-01 1.053e+00 1.071e+00
1.312e+00 1.093e+00 -1.298e+00 7.832e-01
-1.543e+00 -1.466e+00 4.029e-01 1.303e-01
>>>this is a footer
ちゃんと指定できていました。
次に、loadtxt
を使ってデータ型を指定して見ます。以下のようなアンケート結果のようなcsvデータを考えて見ます。(ファイル名はfoo.csv
扱います。)
# age gender tall[cm] driver's_lisense
18 female 154.1 No
21 male 172.3 Yes
22 female 160.8 Yes
23 male 180.1 Yes
25 female 145.0 No
左か年齢、性別、身長、運転免許の有無についてです。これらを列ごとにデータ型を指定しながら読み込んでいきます。
unpack = True
にすることで転置をほどこすことができ、要素ごとに配列へ収納することができます。
引数converters
を用いて文字列データをあらかじめ数値に変えておくとのちの処理も楽になるかもしれません。例えば性別でmale
を1,female
を-1とし、driver's_lisense
でYes
を1
, No
を-1
にするとします。以下のように2つの関数を設定してから読み込みます。
このconverters
引数を用いることによって空の値に対してデフォルトの値を与えることができます。では、先ほどのデータでgender
欄に穴を開けて、そこの値をNaN
にするよう設定して見ます。うまく認識されなかったため、ここでデータの区切りをスペースから,
に変更しました。
# age gender tall[cm] driver's_lisense
18,,154,No
21,male,172,Yes
22,,160,Yes
23,,180,Yes
25,female,145,No
np.genfromtxt
np.savetxt
関数の変形版としてnp.genfromtxt
関数というのも存在します。この関数を使うことで、データの欠落に対する挙動を指定することができます。
いちいち列ごとに指定する必要がなく、全ての列に対して一括で指定できます。
まずはAPIドキュメントを確認してみましょう。
np.genfromtxt(fname, dtype = ‘float’, comments=’#’, delimiter=None, skip_header=0, skip_footer=0, converters=None, missing_values = None, filling_values=None, usecols=None, names=None, excludelist=None, deletechars=None, replace_space=’_’, autostrip=False, case_sensitive=True, defaultfmt=’f%i’, unpack=None, usemask=False, loose=True, invalide_raise=True, max_rows=None, encoding=’bytes’, …, ndmin=0, like=None)
params;
パラメータ名 | 型 | 概要 |
---|---|---|
fname |
file, str またはファイルのパス |
読み込むファイルを指定します。 |
dtype |
データ型 | (省略可能)初期値’float’ 返される配列における要素のデータ型を指定します。 |
comments |
str | (省略可能)初期値’#’ ヘッダーやフッターの目印として使われる文字を指定します。この文字が現れたあとにある文字列やデータは全て読み込まれません。 |
delimiter |
strやint またはシーケンス |
(省略可能)初期値None データを区切る記号を指定します。デフォルトではスペース(空白)となっています。 |
skip_header |
int | (省略可能)初期値0 最初に読み飛ばす行数を指定します。 |
skip_footer |
int | (省略可能)初期値0 ファイルの末尾で読み飛ばす行数を指定します。 |
converters |
dict(辞書) | (省略可能)初期値None 列ごとにどのような関数を適用するかを指定します。loadtxtと同じ使い方です。 |
missing_values |
variable | (省略可能)初期値None 欠損データに対応する文字列の組みを指定します。 |
filling_values |
variable | (省略可能)初期値None データが欠損しているときに穴埋めする値を指定します。 |
usecols |
シーケンス | (省略可能)初期値None どの列を読み込むのか指定します。デフォルトの値では全ての列を読み込みます。 |
names |
{None, True, str, シーケンス}のいずれか | (省略可能)初期値None それぞれの列に対して名称をつけます。 |
excludelist |
シーケンス | (省略可能)初期値None 除外するデータを指定します。 |
deletechars |
str | (省略可能)初期値None namesから消去する必要のある無効な文字を指定します。 |
defaultfmt |
str | (省略可能)初期値’f%i’ デフォルトのフィールド名を定義します。 |
autostrip |
bool値 | (省略可能)初期値False 値からスペース(空白)を自動的に取り除くかどうかを指定します。 |
replace_space |
文字 | (省略可能)初期値’_‘ スペース(空白)があった場合、そこにどんな値を入れていくかを指定します。 |
case_sensitive |
{True, False, ‘upper’, ‘lower’}のいずれか | (省略可能)初期値True 各フィールドの名前を大文字にするかどうかを指定します。 True のときはそのままで、upper やFalse のときは大文字にし、lower のときは小文字にします。 |
unpack |
bool値 | (省略可能)初期値None 返す配列を転置させるかどうかを指定します。 |
usemask |
bool値 | (省略可能)初期値False マスクされた配列(無効な値などが含まれている可能性のある配列)として出力するかどうかを指定します。 |
loose |
bool値 | (省略可能)初期値True Trueの場合、無効な値を含んでいてもエラーを返しません。 |
invalid_raise |
bool値 | (省略可能)初期値True Trueの場合、列数で矛盾が発生した場合例外を発生させます。Falseの場合、警告が発せられ、行の追加が見送られます。 |
max_rows |
int | (省略可能)初期値None 最大で何行読み込むかを指定します。デフォルトでは全てを読み込みます。 |
encoding |
ファイルを読み込む際に使う文字コードを指定する。 初期値で設定されている’bytes’は後方互換のためバイトデータを読むように指定する特別な値です。 |
|
ndmin |
int | loadtxtと同じです。 |
like |
array_like | NumPy配列以外の参照オブジェクトで生成します。__array_function__ プロトコルを継承しているオブジェクトを指定することができます |
returns:
データを読み込んだ配列が返されます。
引数の数がnp.savetxt
以上に多い上、実際に使われているものの種類が少ないため上記の表を見ながら使っていきましょう。
以下のようにデータに欠損のあるファイルを読み込ませて見ます。ファイル名はbar.txt
です。
1.1,,
2.3, 5.2, -9.1
0.1,, 2.0
これを読み込ませてみると、
このように、欠損部分がnan
として返されています。データの区切りが,
だったのでdelimiter
でそれを指定しています。データ型も変更してみます。
このようにnp.genfromtxt
は特に何も指定しなくても欠損データのところに値を入れてくれます。
参考
- numpy.loadtxt — NumPy v1.13 Manual - Numpy and Scipy Documentation
- numpy.load — NumPy v1.13 Manual - Numpy and Scipy Documentation
- numpy.savetxt — NumPy v1.13 Manual
- numpy.save — NumPy v1.13 Manual - Numpy and Scipy Documentation
- numpy.genfromtxt — NumPy v1.13 Manual
- numpy > ファイル読み書き > np.save() / np.load() / np.savetxt() / np.loadtxt() > バイナリ読み書き / csv読み書き -Qiita
- numpy arrayの保存 - 亀の歩み
- Python: オブジェクトを漬物 (Pickle) にする - CUBE SUGAR CONTAINER