CSVファイルの読み書き
データは、CSV(comma-separated values)形式で保存されることがある。これは、データをテキストで表して、コンマ,で区切って並べたものである。この形式のファイルは、例えばExcelで作成したデータをファイル拡張子として「.csv」選んで、保存すればCSV形式のファイルとして保存される。例えば、データを図1のように用意したとする。
図1
このデータを、ファイル拡張子として「.csv」を指定して保存するとCSV形式のファイルとして保存される。図2は、このファイルをメモ帳で開いたものである。
図2 CSV形式
Excelで作成したデータに日本語が含まれているときは、Python IDLEのエディタで開くとき、図3のダイアログボックスが表示される。
図3
これは、Excelで日本語を入力したとき、シフトJISコードが用いられたことによる。Encodingとして「s-jis」を設定すれば(図4)、開くことができる(図5)。
図4
図5
読み込み(入力)の場合と書き込み(出力)の場合に分けて説明する。ファイル入出力については、<岡本安晴「いまさら聞けないPythonでデータ分析」丸善出版>の第3章で説明している。ファイル拡張子が「.xlsx」であるExcelファイルについては、別のウェブサイトで扱っている。
CSVファイルの読み込み
CSVファイルの読み込みを、テキストファイルとして読み込む場合、モジュールcsvを用いる場合、モジュールpandasを用いる場合について説明する。
CSV形式のファイルはテキストファイルであるので、テキストファイルとして読み込むことができる。例えば、図1のファイル(sample_data.csv)は、次のコードで読み込むことができる。
f = open('sample_data.csv', 'r')
data = f.readlines()
f.close()
dataに読み込まれた内容を次のコード
print('data
=\n', data)
で出力すると、以下のようになる。
data =
['項目_1,項目-2,項目-3\n',
'10,A,1.1\n', '20,B,2.2\n', '30,C,3.3\n', '40,D,4.4\n', '50,E,5.5\n']
1行分のデータが1つの文字列として表され、1行内の各データはコンマ,で区切られている。また、各行のデータは制御文字’\n’で終わっている。
読み込んだデータdataを1行分(文字列1つ分)ずつ取り出し、行末の’\n’をメソッドstripで取り除いて、さらにメソッドsplitでコンマ,で区切られた値を切り離して出力するコードを以下のように用意した。
print('After stripping and splitting
=')
for s in data:
s = s.strip('\n')
print(s.split(','))
このコードを実行すると、以下の出力を得る。
After stripping and splitting =
['項目_1', '項目-2', '項目-3']
['10', 'A', '1.1']
['20', 'B', '2.2']
['30', 'C', '3.3']
['40', 'D', '4.4']
['50', 'E', '5.5']
上の1行単位の出力を要素とするリストXを以下のように作成した。
X = []
for s in data:
X.append((s.strip('\n')).split(','))
print('X =')
print(X)
Xの内容の出力は、以下の通りである。
X =
[['項目_1', '項目-2', '項目-3'], ['10', 'A', '1.1'], ['20', 'B', '2.2'], ['30', 'C', '3.3'],
['40', 'D', '4.4'], ['50', 'E', '5.5']]
リストXの内容を、変数名のリストVarNamesと変数値の配列VarValuesにまとめ、それらの内容を出力するコードを以下のように用意した。
VarNames = X[0]
VarValues = []
for i in range(len(X) - 1):
VarValues.append(X[i + 1])
print('項目名 =\n', VarNames)
print('素値 =')
for v in VarValues:
print(v)
このコードの出力は、以下のようになる。
項目名 =
['項目_1', '項目-2', '項目-3']
素値 =
['10', 'A', '1.1']
['20', 'B', '2.2']
['30', 'C', '3.3']
['40', 'D', '4.4']
['50', 'E', '5.5']
CSVファイルから読み込まれた値は、数値データを表すものもそのまま文字列として読み込まれているので、これらを数値に変換する必要がある。数値への変換と、その変換後のデータを出力するコードを以下のように用意した。
for i in range(len(VarValues)):
VarValues[i][0] =
int(VarValues[i][0])
VarValues[i][2] =
float(VarValues[i][2])
print('変換後の値 =')
for v in VarValues:
print(v)
出力は、以下のようになる。
変換後の値 =
[10, 'A', 1.1]
[20, 'B', 2.2]
[30, 'C', 3.3]
[40, 'D', 4.4]
[50, 'E', 5.5]
上で説明したコードを1つのスクリプトにまとめ、リスト1とした。
リスト1 テキストファイルとして読み込む例
f = open('sample_data.csv', 'r')
data = f.readlines()
f.close()
print('data =\n', data)
print('After stripping and splitting
=')
for s in data:
s = s.strip('\n')
print(s.split(','))
X = []
for s in data:
X.append((s.strip('\n')).split(','))
print('X =')f =
open('sample_data.csv', 'r')
data = f.readlines()
f.close()
print('data =\n', data)
print('After stripping and splitting
=')
for s in data:
s = s.strip('\n')
print(s.split(','))
X = []
for s in data:
X.append((s.strip('\n')).split(','))
print('X =')
print(X)
VarNames = X[0]
VarValues = []
for i in range(len(X) - 1):
VarValues.append(X[i + 1])
print('項目名 =\n', VarNames)
print('素値 =')
for v in VarValues:
print(v)
for i in range(len(VarValues)):
VarValues[i][0] =
int(VarValues[i][0])
VarValues[i][2] =
float(VarValues[i][2])
print('変換後の値 =')
for v in VarValues:
print(v)
print(X)
VarNames = X[0]
VarValues = []
for i in range(len(X) - 1):
VarValues.append(X[i + 1])
print('項目名 =\n', VarNames)
print('素値 =')
for v in VarValues:
print(v)
for i in range(len(VarValues)):
VarValues[i][0] =
int(VarValues[i][0])
VarValues[i][2] =
float(VarValues[i][2])
print('変換後の値 =')
for v in VarValues:
print(v)
モジュールcsvを使用して、図1のCSVファイル(sample_data.csv)を読み込むコードを次のように書いてみた。
f = open('sample_data.csv', 'r')
f_data = csv.reader(f)
f_dataの内容を出力するコードを以下のように用意した。
print('f_data =')
print(f_data)
出力は以下のようである。
f_data =
<_csv.reader object at
0x000001BFC037AA60>
f_dataからデータを取り出し、出力するコードを以下のように用意した。
X = [s for s in f_data]
f.close()
print('X =')
print(X)
出力は、以下のようである。
X =
[['項目_1', '項目-2', '項目-3'], ['10', 'A', '1.1'], ['20', 'B', '2.2'], ['30', 'C', '3.3'],
['40', 'D', '4.4'], ['50', 'E', '5.5']]
リストXの内容に基づいて、変数名をリストVarNamesに、データ値をリスト型配列VarValuesに格納するコードと、それらの内容を出力するコードを以下のように用意した。
VarNames = X[0]
VarValues = []
for i in range(len(X) - 1):
VarValues.append(X[i + 1])
print('項目名 =\n', VarNames)
print('素値 =')
for v in VarValues:
print(v)
出力は、以下のようである。
項目名 =
['項目_1', '項目-2', '項目-3']
素値 =
['10', 'A', '1.1']
['20', 'B', '2.2']
['30', 'C', '3.3']
['40', 'D', '4.4']
['50', 'E', '5.5']
CSVファイルから読み込まれた値は、数値データもその値を表す文字列として読み込まれている。これらの数値データを、それらの表す数値に変換するコードを用意し、その変換結果を出力するコードを以下のように用意した。
for i in range(len(VarValues)):
VarValues[i][0] =
int(VarValues[i][0])
VarValues[i][2] =
float(VarValues[i][2])
print('変換後の値 =')
for v in VarValues:
print(v)
出力は、以下の通りである。
変換後の値 =
[10, 'A', 1.1]
[20, 'B', 2.2]
[30, 'C', 3.3]
[40, 'D', 4.4]
[50, 'E', 5.5]
上のコードを1つのスクリプトにまとめ、リスト2とした。
リスト2 モジュールcsvによる読み込み
import csv
f = open('sample_data.csv', 'r')
f_data = csv.reader(f)
print('f_data =')
print(f_data)
X = [s for s in f_data]
f.close()
print('X =')
print(X)
VarNames = X[0]
VarValues = []
for i in range(len(X) - 1):
VarValues.append(X[i + 1])
print('項目名 =\n', VarNames)
print('素値 =')
for v in VarValues:
print(v)
for i in range(len(VarValues)):
VarValues[i][0] =
int(VarValues[i][0])
VarValues[i][2] =
float(VarValues[i][2])
print('変換後の値 =')
for v in VarValues:
print(v)
モジュールpandasを利用して図1のCSVファイル(sample_data.csv)を読み込むコードを以下のように作成した。
import pandas as pd
p_data =
pd.read_csv('sample_data.csv', encoding = 's-jis')
パラメータ「encoding = 's-jis'」は、Excelで作成したデータに日本語が含まれていることに対応するためである。
pandasのread_csvによってCSVファイルが読み込まれると、DataFrameオブジェクトとして読み込み内容が返される。
p_dataの内容を出力するコードを次のように用意した。
print('p_data
=\n', p_data)
出力は、以下の通りである。数値データは数値として読み込まれている。
p_data =
項目_1 項目-2 項目-3
0 10 A 1.1
1 20 B 2.2
2 30 C 3.3
3 40 D 4.4
4 50 E 5.5
DataFrameオブジェクトp_dataから、項目名をVarNamesに、データ値をVarValuesに取り出し、その内容を書き出すコードを以下のように用意した。
VarNames = p_data.columns.values
VarValues = p_data.values
print('項目名 =')
print(VarNames)
print('データ値 =')
print(VarValues)
出力は、以下の通りである。
項目名 =
['項目_1' '項目-2' '項目-3']
データ値 =
[[10 'A' 1.1]
[20 'B' 2.2]
[30 'C' 3.3]
[40 'D' 4.4]
[50 'E' 5.5]]
数値データは数値として、文字列データは文字列として扱われている。
上のコードを1つのスクリプトファイルとしてまとめたものをリスト3に示す。
リスト3 モジュールpandasによるCSVファイルの読み込み
import pandas as pd
p_data =
pd.read_csv('sample_data.csv', encoding = 's-jis')
print('p_data =\n', p_data)
VarNames = p_data.columns.values
VarValues = p_data.values
print('項目名 =')
print(VarNames)
print('データ値 =')
print(VarValues)
CSVファイルの書き出し
次のデータをCSV(Comma-Separated Values)形式のファイル(図2)として保存することを考える。
X = [['CaseID', '変数ー1', '変数ー2', '変数ー3'],
[10, 'A', 100, 0.1],
[20, 'B', 200, 0.2],
[30, 'C', 300, 0.3],
[40, 'D', 400, 0.4],
[60, 'E', 500, 0.5]]
テキストファイルとして書き出す場合、モジュールcsvを用いる場合、モジュールpandasを用いる場合について説明する。
CSV形式(図2)テキストファイルとして書き出す場合
上のデータXをCSV形式のファイルとして保存するときは、データ値ごとにコンマ,で区切って書き出せばよい。ファイル名の拡張子は「.csv」とする。
まず、項目名は以下のコードで書き出せる。
f = open('data_text.csv', 'w')
for j in range(len(X[0])):
if j > 0:
f.write(',')
f.write(f'{X[0][j]}')
f.write('\n')
次に項目の値を次のコードで書き出す。
for i in range(len(X[0]) - 1):
for j in range(len(X[0])):
if j
> 0:
f.write(',')
f.write(f'{X[i + 1][j]}')
f.write('\n')
プログラムの実行後、出力ファイル(data_text.csv)をExcelで開くと図A.1のようになっている。
図A.1
上のコードを1つのスクリプトとしてまとめたものをリストA.1として示す。
リストA.1 テキストファイル出力でCSV形式のファイルを保存
X = [['CaseID', '変数ー1', '変数ー2', '変数ー3'],
[10, 'A', 100, 0.1],
[20, 'B', 200, 0.2],
[30, 'C', 300, 0.3],
[40, 'D', 400, 0.4],
[60, 'E', 500, 0.5]]
f = open('data_text.csv', 'w')
for j in range(len(X[0])):
if j > 0:
f.write(',')
f.write(f'{X[0][j]}')
f.write('\n')
for i in range(len(X[0]) - 1):
for j in range(len(X[0])):
if j
> 0:
f.write(',')
f.write(f'{X[i + 1][j]}')
f.write('\n')
f.close()
print('CSVファイルが保存されました。')
モジュールcsvを利用するときは、次のコードでCSVファイルとして出力できる。
f = open('data_csv.csv', 'w', newline
= '\n')
wt = csv.writer(f)
wt.writerows(X)
f.close()
関数openのパラメータに「newline = ‘\n’」とあるのは、行末の処理法の指定である。この指定がないとき、出力ファイルをWindowsにおいてExcelで開くと、1行跳びの表示になる。
実行後、保存したCSVファイルをExcelで開くと図A.2のようになっている。
図A.2
上のコードを1つのプログラムとしてまとめたものをリストA.2に示す。
リストA.2 モジュールcsvによるCSVファイルの保存
import csv
X = [['CaseID', '変数ー1', '変数ー2', '変数ー3'],
[10, 'A', 100, 0.1],
[20, 'B', 200, 0.2],
[30, 'C', 300, 0.3],
[40, 'D', 400, 0.4],
[60, 'E', 500, 0.5]]
f = open('data_csv.csv', 'w', newline
= '\n')
wt = csv.writer(f)
wt.writerows(X)
f.close()
print('CSVファイルが保存されました。')
モジュールpandasを用いる場合は、まずデータXをpandasのDataFrame型のオブジェクトに変換する。この変換は次のコードで行える。
X_pd = pd.DataFrame(X)
print(X_pd)
上のコードの関数printによる出力は、以下のようである。
0 1 2 3
0
CaseID 変数ー1 変数ー2 変数ー3
1 10 A 100 0.1
2 20 B 200 0.2
3 30 C 300 0.3
4 40 D 400 0.4
5 60 E 500 0.5
pandasのDataFrame型のオブジェクトとして表されていることがわかる。
このオブジェクトX_pdをメソッドto_csvで出力するとCSVファイルが得られる。
X_pd.to_csv('data_pandas.csv',
header = False, index = False, encoding = 's-jis')
パラメータ「header = False, index = False」の指定により、ヘッダーとインデックスは出力されない。
パラメータ「encoding = ‘s-jis’」は、データに日本語が含まれている場合、出力ファイルをWindowsのExcelで開いたときに文字化けを避けるためのものである。
プログラムの実行後、保存したCSVファイルをExcelで開くと図A.3のようになっている。
図A.3
上のコードを1つのスクリプトファイルとしてリストA.3にまとめた。
リストA.3 モジュールpandasによるCSVファイルの保存
import pandas as pd
X = [['CaseID', '変数ー1', '変数ー2', '変数ー3'],
[10, 'A', 100, 0.1],
[20, 'B', 200, 0.2],
[30, 'C', 300, 0.3],
[40, 'D', 400, 0.4],
[60, 'E', 500, 0.5]]
X_pd = pd.DataFrame(X)
print(X_pd)
X_pd.to_csv('data_pandas.csv', header
= False, index = False, encoding = 's-jis')
print('CSVファイルを保存しました。')