CSVファイルの読み書き
CSV(Comma separated Values)ファイルの読み書きについて例を示す。
CSVファイルの例を図1に示す。
図1 CSVファイルsample1.csv
CSVファイルは値をコンマ,で区切って並べたものであり、ファイル拡張子は「.csv」である。図1のファイルsample1.csvをテキストエディタで開くと図2のようになっている。
図2 CSVファイルをエディタで開いたもの
CSVファイルはテキストファイルであるので、テキストファイルとして読み書きできるが、Pandasのライブラリを用いると、読み書きが簡単にできる。
まず、CSVファイルの読み込みについて説明して、次に書き出しについて説明する。
図1に示されているCSVファイルの読み込みを行う。
CSVファイルsample1.csvは、pandasの関数read_csvによって読み込むことができる。コードを次に示す。
data_csv = pandas.read_csv('sample1.csv',
encoding='shift_jis')
引数encoding='shift_jis'は、ファイルに日本語が含まれているときに必要である。'shift_jis'が標準であるが、それでうまくいかないときは他のコードを設定する。Pythonのエディタで日本語を含むCSVファイルを作成したときは、'utf-8'である。図1のデータは、Excelで作成したものである。Excelで作成した図1のCSVファイルをPythonのエディタで開くときは、Pythonのエディタにコードが'shift_jis'であることを設定している。CSVファイルに日本語が含まれず、英語のみであれば、encoding='shift_jis'は要らない。
なお、PythonでCSVファイルを作成したとき、日本語を含む場合は、Excelで開くと文字化けを起こす。Calcの場合はインポート/文字列を「Unicode(UTF-8)」に設定すると文字化けを起こさない。
次のスクリプトでCSVファイルとExcelファイルを作成した。
import pandas as pd
data = {'A':['あ','い','う'], 'B':[1,2,3]}
pd.DataFrame(data).to_csv('jp_sj.csv')
pd.DataFrame(data).to_excel('jp_sj.xlsx')
CSVファイルの方は、Excelでは文字化けを起こしているが、Calcの方は文字化けはない。
Excelファイル(*.xlsx)の場合は、ExcelもCalcも文字化けなく表示されている。
読み込まれた内容は、pandasのDataFrame型として表される。DataFrame型は配列のようなものであり、列がCSVファイルの第1行目の値をキーとする辞書型の感覚で使えるが、便利な関数が用意されている。
上のスクリプト
data_csv = pandas.read_csv('sample1.csv',
encoding='shift_jis')
によって読み込んだ内容を、次のprint関数
print('data_csv =\n', data_csv)
で出力すると以下のようになる。
data_csv =
ケース識別子 変数1 変数2 変数3
0 太郎 100 50 5
1 次郎 150 30 3
2 花子 120 70 7
第1列目には、0から始まるデータの通し番号(index)が出力されている。
第1行目は、CSVファイルの第1行目の値で、keyとして用いられる。
2行目以降、2列目より右側に、CSVデータの2行目以降が出力されている。
次のコードは、keyを出力するものである。
print('data_csv.keys() =\n', data_csv.keys())
実行すると、次の出力を得る。
data_csv.keys() =
Index(['ケース識別子', '変数1', '変数2', '変数3'], dtype='object')
各keyに対する値は、次のコードで確認できる。
for nm in data_csv.keys():
print('key =',nm)
print('data_csv[key]
=\n', data_csv[nm])
実行すると、以下の出力を得る。
key = ケース識別子
data_csv[key] =
0 太郎
1 次郎
2 花子
Name: ケース識別子, dtype: object
key = 変数1
data_csv[key] =
0 100
1 150
2 120
Name: 変数1, dtype: int64
key = 変数2
data_csv[key] =
0 50
1 30
2 70
Name: 変数2, dtype: int64
key = 変数3
data_csv[key] =
0 5
1 3
2 7
Name: 変数3, dtype: int64
アトリビュートvaluesを用いるとkeyに対する値がndarray型の配列として得られる。次のコードではvaluesによって配列型として値を得ている。
for nm in data_csv.keys():
print('key =',nm)
print('data_csv[key].values
\n', data_csv[nm].values)
実行すると、以下の出力を得る。
key = ケース識別子
data_csv[key].values
['太郎' '次郎' '花子']
key = 変数1
data_csv[key].values
[100 150 120]
key = 変数2
data_csv[key].values
[50 30 70]
key = 変数3
data_csv[key].values
[5 3 7]
data_csvに読み込まれた値全体のndarray型の値を得るときは、keyを指定せずにvaluesを適用すればよい。次のコード
print('data_csv.vales =\n', data_csv.values)
を実行すると、以下の出力を得る。
data_csv.vales =
[['太郎' 100 50 5]
['次郎' 150 30 3]
['花子' 120 70 7]]
ndarray型であるので、numpyの関数が利用できる。
次のコードは、CSVファイルの2列目以降の列ごとの和を求めるものである。
print(numpy.sum(data_csv.values.T[1:],
axis=1))
実行すると次の出力を得る。
[370 150 15]
以上のスクリプトを1つのスクリプトにリスト1としてまとめた。
リスト1
import pandas
import numpy
data_csv = pandas.read_csv('sample1.csv',
encoding='shift_jis')
print('data_csv
=\n', data_csv)
print('data_csv.keys()
=\n', data_csv.keys())
print()
for nm in data_csv.keys():
print('key =',nm)
print('data_csv[key]
=\n', data_csv[nm])
print()
for nm in data_csv.keys():
print('key =',nm)
print('data_csv[key].values
\n', data_csv[nm].values)
print()
print('data_csv.vales
=\n', data_csv.values)
print()
print(numpy.sum(data_csv.values.T[1:], axis=1))
空白セルがある場合
CSVファイルに空白のセルがある場合、空白セルはNAN(Not a Number)に置き換えられる。
図3
図3のCSVファイルsample2.csvでは、2つのセルが空白である。
このファイルを次のコードで読み込み、出力してみる。
data_csv = pd.read_csv('sample2.csv',
encoding='shift-jis')
print('DataFrame
=\n', data_csv)
以下の出力を得る。
DataFrame =
ケース識別子 変数1 変数2 変数3
0 太郎 100.0 50 5.0
1 次郎 NaN 30 3.0
2 花子 120.0 70 NaN
空白セルがNaNになっていることが判る。
DataFrame型の値の部分をndarray型に変換して出力して見るための次のコードを用意した。
print('data_csv.values =\n', data_csv.values)
実行すると、以下の出力を得る。
data_csv.values =
[['太郎' 100.0 50 5.0]
['次郎' nan 30 3.0]
['花子' 120.0 70 nan]]
CSVファイルの空白セルが、nanになっていることが分かる。
セルの値がnanであるかどうかは、モジュールmathのisnan関数で調べることができる。
次のスクリプトは、isnanの使用例である。
for v in data_csv[data_csv.keys()[1]]:
print(f'{v}:', end='')
ck
= 'NAN' if math.isnan(v) else 'Not NAN'
print(' ', ck)
実行すると、以下の出力を得る。
Key = 変数1
100.0: Not NAN
nan: NAN
120.0: Not NAN
上の空白セルに関わる説明のスクリプトをまとめて、リスト2とした。
リスト2
import pandas as pd
import numpy
as np
import math
data_csv = pd.read_csv('sample2.csv',
encoding='shift-jis')
print('DataFrame
=\n', data_csv)
print('Keys =\n', data_csv.keys())
for nm in data_csv.keys():
print('Key =',nm)
print(data_csv[nm])
print('data_csv.values
=\n', data_csv.values)
for nm in data_csv.keys():
print('Key = ',nm, ', values =', data_csv[nm].values)
print()
print('Key =', data_csv.keys()[1])
for v in data_csv[data_csv.keys()[1]]:
print(f'{v}:', end='')
ck
= 'NAN' if math.isnan(v) else 'Not NAN'
print(' ', ck)
データはpandasのDataFrame型の関数to_csvを用いて、CSVファイルとして保存できる。
次のスクリプトは、辞書型データraw_dataをDataFrame型に変換して、CSVファイルdata1.csvに保存するものである。
raw_data = {'a':[1,2,3], 'b':[100,200,300]}
pd.DataFrame(raw_data).to_csv('data1.csv')
このスクリプトを実行すると、図4のCSVファイルdata1.csvが作成される。
図4
図4のCSVファイルでは、インデックスが自動的に作成されて第1列(A列)に表示されている。
このインデックスを挿入しないときは、関数to_csvの引数にindex=Falseを設定すればよい。
次のコード
pd.DataFrame(raw_data).to_csv('data2.csv', index=False)
で作成されたCSVファイルdata2.csvには、インデックスが無い(図5)。
図5
DataFrameの各keyの要素の数は同じでなければならないという制約がある。同じでないときは、numpy.nanを設定して、要素の数を揃えればよい。
次のスクリプトでは、辞書の各キーの値のリストの要素数をnumpy.nanを入れて3個に揃えている。
raw_data_ex = {'a':[1,2,3], 'b':[100,np.nan,200],
'c':[5,6,np.nan]}
pd.DataFrame(raw_data_ex).to_csv('data3.csv')
上のスクリプトの実行によって作成されたCSVファイルdata3.csvでは、numpy.nanの箇所は空白セルになっている(図6)。
図6
上の説明でのスクリプトは、リスト3としてまとめた。
リスト3
import pandas as pd
import numpy
as np
raw_data = {'a':[1,2,3], 'b':[100,200,300]}
pd.DataFrame(raw_data).to_csv('data1.csv')
pd.DataFrame(raw_data).to_csv('data2.csv', index=False)
raw_data_ex = {'a':[1,2,3], 'b':[100,np.nan,200],
'c':[5,6,np.nan]}
pd.DataFrame(raw_data_ex).to_csv('data3.csv')
DataFrame型のオブジェクトは、配列から簡単に作ることができる。
次のスクリプトでは、配列aからDataFrameが作成されている。
a = [[1,2,3],[4,5,6]]
df_a = pd.DataFrame(a)
print(df_a)
実行すると、次の出力を得る。
0 1
2
0
1 2 3
1
4 5 6
配列aが列単位にまとめられていることが分かる。列のkeyが0から2まで自動的に割り当てられ、行のindexが0か1まで自動的に割り当てられている。
行単位でまとめるために、配列aをndarray型に変換して転置行列を取る。
df_b = pd.DataFrame(np.array(a).T)
print(df_b)
実行すると次の出力を得る。
0 1
0
1 4
1
2 5
2
3 6
列のkeyを自動的に割り当てられる0からの整数ではなく、引数culumnsで明示的に設定することもできる。
df_c = pd.DataFrame(np.array(a).T, columns=['Var_A',
'Var_B'])
print(df_c)
実行すると、次の出力を得る。
Var_A Var_B
0 1 4
1 2 5
2 3 6
上のスクリプトに続いて、次のスクリプトを実行してCSVファイルとする。
df_c.to_csv('data_c.csv', index=False)
実行後、図7に示すCSVファイルdata_c.csvが作成される。
図7
上の説明でのスクリプトファイルをリスト4にまとめた。
リスト4
import pandas as pd
import numpy
as np
a = [[1,2,3],[4,5,6]]
df_a = pd.DataFrame(a)
print(df_a)
print()
df_b = pd.DataFrame(np.array(a).T)
print(df_b)
print()
df_c = pd.DataFrame(np.array(a).T, columns=['Var_A',
'Var_B'])
print(df_c)
df_c.to_csv('data_c.csv', index=False)