NumPyが提供するsavetxt関数関数を使って、CSVファイルなどにデータを書き込む方法を紹介する。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
import numpy as np
from pathlib import Path
x = np.random.randn(2, 3) # 以下の値は一例
print(x)
#[[-2.45567984 1.33310634 0.59013369]
# [ 0.25731195 0.78458477 -0.64572527]]
# 基本的な使い方
np.savetxt('test.csv', x)
print(Path('test.csv').read_text())
#-2.455679835942072398e+00 1.333106339746787494e+00 5.901336922847821853e-01
#2.573119457585911207e-01 7.845847696453233100e-01 -6.457252711716952032e-01
# 区切り文字を変更する
np.savetxt('test.csv', x, delimiter=',') # 区切り文字をカンマ「,」に
print(Path('test.csv').read_text())
#-2.455679835942072398e+00,1.333106339746787494e+00,5.901336922847821853e-01
#2.573119457585911207e-01,7.845847696453233100e-01,-6.457252711716952032e-01
# 書き出すフォーマットの指定
# 指数表記
np.savetxt('test.csv', x, fmt='%.8e') # 小数点以下の精度を8桁に
print(Path('test.csv').read_text())
#-2.45567984e+00 1.33310634e+00 5.90133692e-01
#2.57311946e-01 7.84584770e-01 -6.45725271e-01
np.savetxt('test.csv', x, fmt='%18.8e') # 最小の出力幅を指定
print(Path('test.csv').read_text())
# -2.45567984e+00 1.33310634e+00 5.90133692e-01
# 2.57311946e-01 7.84584770e-01 -6.45725271e-01
# 浮動小数点数値(指数表記をしない)
np.savetxt('test.csv', x, fmt='%12.8f') # 精度の後に「f」を指定
print(Path('test.csv').read_text())
# -2.45567984 1.33310634 0.59013369
# 0.25731195 0.78458477 -0.64572527
# 左寄せ
np.savetxt('test.csv', x, fmt='%-18.8e') # 「-」で左寄せを指定
print(Path('test.csv').read_text())
#-2.45567984e+00 1.33310634e+00 5.90133692e-01
#2.57311946e-01 7.84584770e-01 -6.45725271e-01
# 符号を常に付加
np.savetxt('test.csv', x, fmt='%+18.8e') # 「+」で符号を常に付加
print(Path('test.csv').read_text())
# -2.45567984e+00 +1.33310634e+00 +5.90133692e-01
# +2.57311946e-01 +7.84584770e-01 -6.45725271e-01
# 0埋め
np.savetxt('test.csv', x, fmt='%018.8e') # 「0」で0埋めを指定
print(Path('test.csv').read_text())
#-0002.45567984e+00 00001.33310634e+00 00005.90133692e-01
#00002.57311946e-01 00007.84584770e-01 -0006.45725271e-01
# 整数値
nums = np.array([[111, 222, 333],
[444, 555, 666]])
np.savetxt('test.csv', nums, fmt='%d')
print(Path('test.csv').read_text())
#111 222 333
#444 555 666
np.savetxt('test.csv', nums, fmt='%.5d') # 0埋め
print(Path('test.csv').read_text())
#00111 00222 00333
#00444 00555 00666
np.savetxt('test.csv', nums, fmt='%6d') # 出力される最小の文字数を指定
print(Path('test.csv').read_text())
# 111 222 333
# 444 555 666
np.savetxt('test.csv', nums, fmt='%6.4d') # 数字の最小文字数を指定
print(Path('test.csv').read_text())
# 0111 0222 0333
# 0444 0555 0666
# 改行文字を変更する
np.savetxt('test.csv', x, newline='\n\n')
print(Path('test.csv').read_text())
#-2.455679835942072398e+00 1.333106339746787494e+00 5.901336922847821853e-01
#
#2.573119457585911207e-01 7.845847696453233100e-01 -6.457252711716952032e-01
#
# ヘッダーを付加する
np.savetxt('test.csv', x, header='col1 col2 col3')
print(Path('test.csv').read_text())
## col1 col2 col3
#-2.455679835942072398e+00 1.333106339746787494e+00 5.901336922847821853e-01
#2.573119457585911207e-01 7.845847696453233100e-01 -6.457252711716952032e-01
# フッターを付加する
np.savetxt('test.csv', x, footer='generated: 2021/08/27')
print(Path('test.csv').read_text())
#-2.455679835942072398e+00 1.333106339746787494e+00 5.901336922847821853e-01
#2.573119457585911207e-01 7.845847696453233100e-01 -6.457252711716952032e-01
## generated: 2021/08/27
NumPyが提供するnumpy.savetxt関数(以下、savetxt関数)を使うと、NumPyの配列、リストなどの値を、特定の文字で区切って、CSVファイルなどに出力できる。ただし、出力可能なのは1次元または2次元の配列やリスト(array_likeオブジェクト)に限る。
savetxt関数の構文を以下に示す。
numpy.savetxt(fname, x, fmt='%.18e', delimiter=' ', newline='\n', header='',
footer='', comments='# ', encoding=None)
指定可能なパラメーターは次の通り。
最も基本的な使い方を以下に示す。
import numpy as np
from pathlib import Path
x = np.random.randn(2, 3)
print(x)
#[[-2.45567984 1.33310634 0.59013369]
# [ 0.25731195 0.78458477 -0.64572527]]
# 基本的な使い方
np.savetxt('test.csv', x)
print(Path('test.csv').read_text())
#-2.455679835942072398e+00 1.333106339746787494e+00 5.901336922847821853e-01
#2.573119457585911207e-01 7.845847696453233100e-01 -6.457252711716952032e-01
この例では、2行3列のNumPy配列(numpy.ndarray)を作成して(その値はランダムであるため、読者が本稿のコードを実行したときには、違う値の配列が得られる点には注意されたい)、それをsavetxt関数に渡しているだけだ。出力されたファイルの内容を見ると、小数点以下の精度が18桁の指数表記の値が空白文字で区切られて出力されていることが分かる。これはfmtパラメーターのデフォルト値が「#.18e」(小数点以下の精度が18桁の指数表記)に、delimiterのデフォルト値が「' '」(空白文字)となっているからだ。
なお、上記ではNumPy配列を扱っているが、例えばPythonのリストもこの関数を使って書き出せる。
mylist = x.tolist()
np.savetxt('test.csv', mylist)
print(Path('test.csv').read_text())
#7.731030073194588015e-01 -1.741182180141600311e+00 9.348418996663322711e-02
#4.149555709304568740e-01 -1.150815368506415970e+00 -7.909651117231002171e-02
区切り文字を変更するには、delimiterパラメーターに区切り文字を指定する。以下に例を示す。
np.savetxt('test.csv', x, delimiter=',') # 区切り文字をカンマ「,」に
print(Path('test.csv').read_text())
#-2.455679835942072398e+00,1.333106339746787494e+00,5.901336922847821853e-01
#2.573119457585911207e-01,7.845847696453233100e-01,-6.457252711716952032e-01
ここでは、「delimiter=','」としているので、出力ファイルの内容を見ると、各値がカンマで区切られている。
fmtパラメーターには、各要素を出力時にどのように書式化するかを指定できる。その値は「%[flag][width][.precision]specifier」という形式で指定する。先頭の「%」とspecifierに指定する値以外は省略可能だ。
例えば、配列の要素を指数表記でCSVファイルに書き込むには次のようにする。
np.savetxt('test.csv', x, fmt='%.8e') # 小数点以下の精度を8桁に
print(Path('test.csv').read_text())
#-2.45567984e+00 1.33310634e+00 5.90133692e-01
#2.57311946e-01 7.84584770e-01 -6.45725271e-01
上の例では「%」の後には.precisionとして「.8」が、specifierとして「e」が記述されている(flagとwidthは省略)。このため、小数点以下8桁の指数表記の数値としてCSVファイルに書き込みが行われている。
np.savetxt('test.csv', x, fmt='%18.8e') # 最小の出力幅を指定
print(Path('test.csv').read_text())
# -2.45567984e+00 1.33310634e+00 5.90133692e-01
# 2.57311946e-01 7.84584770e-01 -6.45725271e-01
この例では、「%」に続けてwidthとして「18」が、他の要素については上と同じ値が指定されている。この結果、全体としては各要素が18文字の文字列として出力されている。このとき、符号に1文字(ある場合)、整数部に1文字、小数点に1文字、小数点以下に8文字、指数表記に4文字が使われて15文字(または14文字)の文字列となるので、余った部分は空白文字で埋められている。
以下は指数表記ではない小数表記を行う例だ。
np.savetxt('test.csv', x, fmt='%12.8f') # 精度の後に「f」を指定
print(Path('test.csv').read_text())
# -2.45567984 1.33310634 0.59013369
# 0.25731195 0.78458477 -0.64572527
この例では、「%」の後にwidthとして「12」が、.precisionとして「.8」が、最後にspecifierとして「f」が指定されている。
書式化された出力を左寄せでCSVファイルに出力するにはflagに「-」を指定する。以下に例を示す。
np.savetxt('test.csv', x, fmt='%-18.8e') # 「-」で左寄せを指定
print(Path('test.csv').read_text())
#-2.45567984e+00 1.33310634e+00 5.90133692e-01
#2.57311946e-01 7.84584770e-01 -6.45725271e-01
この例では、全体の文字数が18文字で、精度は8桁の指数表記(e)となっているものを左寄せしている。そのため、各値の後ろにパディングとしての空白文字が付加されている。
書式化の際に常に符号を付加するには、flagに「+」を指定する。以下に例を示す。
np.savetxt('test.csv', x, fmt='%+18.8e') # 「+」で符号を常に付加
print(Path('test.csv').read_text())
# -2.45567984e+00 +1.33310634e+00 +5.90133692e-01
# +2.57311946e-01 +7.84584770e-01 -6.45725271e-01
ここまでは全体の文字数に、書式化後の値の文字数が満たなかった場合に空白文字でパディングが行われていたが、0埋めをするのであれば、flagに「0」を指定する。以下に例を示す。
np.savetxt('test.csv', x, fmt='%018.8e') # 「0」で0埋めを指定
print(Path('test.csv').read_text())
#-0002.45567984e+00 00001.33310634e+00 00005.90133692e-01
#00002.57311946e-01 00007.84584770e-01 -0006.45725271e-01
整数を要素とする配列を書き込むときには、specifierに「d」を指定する。
nums = np.array([[111, 222, 333],
[444, 555, 666]])
np.savetxt('test.csv', nums, fmt='%d')
print(Path('test.csv').read_text())
#111 222 333
#444 555 666
このときには、.precisionは整数として初期化された文字の最小文字数を意味するようになる。
np.savetxt('test.csv', nums, fmt='%.5d') # 0埋め
print(Path('test.csv').read_text())
#00111 00222 00333
#00444 00555 00666
この例では、.precisionとして「.5」が指定されているので、最小でも5文字の文字列として各値が書式化されるので、余った部分は0埋めされている。
一方、widthは書式化された値の最大の文字数を指定するものだ。以下の例ではwidthとして「6」を指定している。
np.savetxt('test.csv', nums, fmt='%6d') # 出力される最小の文字数を指定
print(Path('test.csv').read_text())
# 111 222 333
# 444 555 666
このときには、0埋めではなく、空白文字列を使ってパディングが行われている。以下はwidthに「6」を、.precisionに「.4」を指定した例だ。
np.savetxt('test.csv', nums, fmt='%6.4d') # 数字の最小文字数を指定
print(Path('test.csv').read_text())
# 0111 0222 0333
# 0444 0555 0666
このときには、全体は6文字だが、数字として書式化する最小の文字数が4なので「 0XXX」のようになっている。
最後にfmtパラメーターは各列の書式化方法を個別に指定することもできる。詳しくは説明しないが、簡単に例だけを示しておこう。
fmt1 = '%.4f %.6f %.2f' # 書式指定を区切り文字で区切った文字列
np.savetxt('test.csv', x, fmt=fmt1)
print(Path('test.csv').read_text())
#-2.4557 1.333106 0.59
#0.2573 0.784585 -0.65
fmt2 = ['%.4f', '%.8f', '%.2f'] # 書式指定を要素とするリスト
np.savetxt('test.csv', x, fmt=fmt2)
print(Path('test.csv').read_text())
# 上に同じ
改行文字を変更することはあまりないだろうが、newlineパラメーターを使って、変更可能だ。以下に例を示す。
np.savetxt('test.csv', x, newline='\n\n')
print(Path('test.csv').read_text())
#-2.455679835942072398e+00 1.333106339746787494e+00 5.901336922847821853e-01
#
#2.573119457585911207e-01 7.845847696453233100e-01 -6.457252711716952032e-01
#
この例では、「newline='\n\n'」としているので、各行の後に空行ができている(numpy.loadtxt関数でこのファイルを読み込むことは確認した)。
CSVファイルにヘッダーやフッターを付加するには、headerパラメーターとfooterパラメーターを指定する。以下に例を示す。
# ヘッダーを付加する
np.savetxt('test.csv', x, header='col1 col2 col3')
print(Path('test.csv').read_text())
## col1 col2 col3
#-2.455679835942072398e+00 1.333106339746787494e+00 5.901336922847821853e-01
#2.573119457585911207e-01 7.845847696453233100e-01 -6.457252711716952032e-01
# フッターを付加する
np.savetxt('test.csv', x, footer='generated: 2021/08/27')
print(Path('test.csv').read_text())
#-2.455679835942072398e+00 1.333106339746787494e+00 5.901336922847821853e-01
#2.573119457585911207e-01 7.845847696453233100e-01 -6.457252711716952032e-01
## generated: 2021/08/27
実際のヘッダーとフッターは「# 」で始まり、それに続けてheaderパラメーターもしくはfooterパラメーターに指定した文字列が出力されている点に注意されたい。この文字列はcommentsパラメーターを使って変更することも可能だ(例は割愛する)。
Copyright© Digital Advantage Corp. All Rights Reserved.
Deep Insider 記事ランキング