Pythonでcsvファイルを取り扱う方法を解説します。csvはただのテキストデータですがスプレッドシートのように取り扱うことができるため、便利で軽量な処理が可能となる形式のファイルです。
目次
Pythonでcsvファイルを取り扱う方法
csvに親しむ
聞いたことはあるけど自分から作成したことはない、エクセルブックに保存し直してから使っている、という人も多いのではないかと思います。まずはcsvに慣れ親しんでからcsvの取り扱いを見ていきましょう。
csvファイルとは
csvとは、Comma Separated Valuesの略です。単なるテキストデータです。値はカンマ(,)で区切られた文字列で、カンマで区切られたところを列の境、改行を行に見立ててスプレッドシートのように取り扱うことができる形式のファイルです。エクセルで開いて使う人も多いのではないかと思います。
csvファイルを自分で作ってみる
csvファイルに慣れ親しむためにcsvファイルを自作してみます。まずはメモ帳を開いて、改行を行の区切り(横の線)、カンマを表の列の区切り(縦線)だと思って表を作ります。サンプルでは下のようなデータを作成しました。
データが完成したら、次にデータをcsvファイルとして保存します。csvファイルとして保存するには、ファイルの種類を「すべてのファイル」に変更し、文字コードにUTFを選択します。ファイル名の拡張子部分を自分で「.csv」と手で入力してください。すると下の絵のようになります。
このようにして保存したファイルをエクセルで開くと、無事にスプレッドシートとして使うことができることがわかります。
これで、自作のcsvファイルを作成することができました。ぐっと親近感がわいてきましたね。
csvファイルの特徴
「ただのテキストファイルがスプレッドシートとして利用できる」という意味が分かったところで、メリットを確認します。エクセルブックは機能満載です。一方で、csvファイルはただのテキストファイルなので、データそのもの以上の機能が存在しません。よって、ファイルのOpen、Closeの動作が軽量です。これがメリットです。
一方、セルの幅を変えたり(=変えて維持したり)、セルの色を変更したりすることはできません。エクセルで開いたときはエクセルブックがその機能を持っているので可能でした。しかし、それはcsvファイルをエクセルブックで開いているというだけで、csvファイルの正体はエクセルブックではなく、あくまでcsvファイルです。ただのテキストファイルであることに変わりはありません。
よってcsvファイルは色を付けたりセルの幅を変えたりといった見た目に関する機能は捨て、その代わりに軽量さを得ているといえます。データ分析やデータの対を保持する目的だと割り切ればエクセルよりも取り扱いがしやすい場面も多いことが特徴です。
csvファイルを取り扱う基本的な流れ
それではcsvファイルを取り扱いについて見ていきますが、ここで私のオススメの処理フローを提示します。下記の通りです。
- csvファイルを読み取って変数に格納する
- 配列の中で必要な加工を行う
- 出力物をcsvファイルで作成する
もちろん求められる動作をすれば良いのですが、元データであるcsvファイルを加工して出力結果とすることはあまりオススメしません。バックアップも兼ねて、元データは変更せず、読み取るに留め、求められているデータは新たに生成するのがオススメです。以下、上記の3ステップに沿って解説を進めていきます。
今回はCドライブ直下にsampleフォルダを作ってその中に、先ほど作成した「sample_greeting.csv」のcsvファイルを保存します。このデータを読み取って加工する手順を追っていきます。
csvファイルを取り扱うにはcsvモジュールを利用します。csvファイルはPythonに付属しているモジュールなので、そのままインポートして使うことが可能です。
import csv
csvデータを読み込んでReaderオブジェクトを生成する
まずはcsvファイルを読み取る部分です。csvファイルを読み取るにはReaderオブジェクトを生成します。Readerオブジェクトとは、読み取りたいcsvファイルを格納したファイルをcsvモジュールのreader関数に渡すと、戻り値として返るオブジェクトです。
import csv with open(r'C:\sample\sample_greeting.csv', 'r', encoding = 'utf-8') as greeting_csv: sample_reader = csv.reader(greeting_csv) #ここでReaderオブジェクトの生成 greeting_data = list(sample_reader) print(greeting_data)
with ~ as greeting_csvのところで、sample_greeting.csvを開いてgreeting_csvという変数に格納しています。この部分は下記の様に書いても構いません。
#上のサンプルと同様の結果となる import csv greeting_csv = open(r'C:\sample\sample_greeting.csv', 'r', encoding = 'utf-8') sample_reader = csv.reader(greeting_csv) #ここでReaderオブジェクトの生成 greeting_data = list(sample_reader) print(greeting_data)
いずれも出力結果は同じで、下記の通りです。
#出力結果 [['\ufeff', '朝', '昼', '夜'], ['あいさつ1', 'おはよう', 'こんにちは', 'こんばんは'], ['あいさつ2', 'Good Morning', 'Good Afternoon', ' Good Evening']]
出力結果を確認すると、エクセルで開いたときのデータと見比べてみると行と列がうまく2次元リストで格納できていることが分かります。
細かいですが重要な点として、2点解説します。
◆第2引数について
第2引数としてcsv.readerに’r’を渡しています。これは明示的に読み取り専用として開いているからです。要らないですが、読み取ったデータを元に、別の場所で加工して、新たに書き込むという方針を明確にするために読み取り専用を明示しました。
◆第3引数について
greeting_csvと言う変数にcsvファイルを格納する際、引数として「encoding = 'utf-8'」を渡しています。日本語のような2バイト文字を含むデータを取り扱う場合には必須となります。このブログを読んでいる方は、encoding = 'utf-8'はおまじないだと思って書いておくようにしましょう。*1
また、2つのサンプルコードは全く同じ内容ですが、個人的な感想としては、csvを読み取る部分が一つのインデントに収まって見やすい気がするので、サンプルプログラムとしてはwithを用いた前者の方が良いように思います。
リスト内で必要な作業を行う
前項でlist関数にReaderオブジェクトを渡すことでリストが生成できました。このリストに必要な加工を行います。今回は、スプレッドシートで言う1行目の5列目に「備考」、2行目の5列目に「日本語」、3行目の5列目に英語と書き込みます。
リストはインデックス番号が0から始まるため、リストにした瞬間に行番号と列番号とリストのインデックスがずれていることに注意して下さい。
import csv with open(r'C:\sample\sample_greeting.csv', 'r', encoding = 'utf-8') as greeting_csv: sample_reader = csv.reader(greeting_csv) #ここでReaderオブジェクトの生成 greeting_data = list(sample_reader) print(greeting_data) #ここから先を追加 greeting_data[0][3] = '備考' greeting_data[1][3] = '日本語' greeting_data[2][3] = '英語' print(greeting_data)
出力結果は下記の通りです。2つ目のprint文で出力された結果を見ると、無事に要素が追加されていることが分かります。
[['\ufeff', '朝', '昼', '夜'], ['あいさつ1', 'おはよう', 'こんにちは', 'こんばんは'], ['あいさつ2', 'Good Morning', 'Good Afternoon', ' Good Evening']] [['\ufeff', '朝', '昼', '備考'], ['あいさつ1', 'おはよう', 'こんにちは', '日本語'], ['あいさつ2', 'Good Morning', 'Good Afternoon', '英語']]
Writerオブジェクトで新規作成したcsvファイルにデータを書き込む
csvファイルからのデータの読み込みと加工が終わったのでついに新たなcsvを生成して保存する最終段階です。新たにcsvファイルを生成して、書き込み、保存します。
新しいファイルを生成するためには次の二つのことを行います。
- Open()関数で存在しないファイル名を指定する
- 書き込みモードで開く(第2引数を'w'にする。追記モードrでもOK)
この点を踏まえて、新たなファイルを作成します。更新済みである事が分かる様にファイル名は「revised_sample_greeting.csv」としました。
#(略) with open(r'C:\sample\revised_sample_greeting.csv', 'w', newline='', encoding = 'utf-8') as output_file:
ここでnewline=''が必要となります。また、Readerオブジェクトを生成したときと同様にWithを使わない方法でも記述可能です。
output_file = open(r'C:\sample\revised_sample_greeting.csv', 'w', newline='', encoding = 'utf-8')
Writerオブジェクトを生成して書き込みます。その後、for文で2次元リストの要素を順にcsvファイルに書き込んでいきます。
#(略) with open(r'C:\sample\revised_sample_greeting.csv', 'w', newline='', encoding = 'utf-8') as output_file: sample_writer = csv.writer(output_file) #ここでWriterオブジェクトの生成 for i in range(0, 3): sample_writer.writerow(greeting_data[i]) output_file.close()
最後に.close()を忘れないようにしましょう。これでできあがりです。for文の繰り返しは今回は3とベタ打ちしましたが、必要に応じてlen(greeting_data)など、リストのサイズに応じた対応をして下さい。
実務的な一連のサンプルコード
省略せずに始めのデータの読み込みから加工、別ファイルを生成して保存して閉じるところまでを全て記述すると下記の通りです。
import csv with open(r'C:\sample\sample_greeting.csv', 'r', encoding = 'utf-8') as greeting_csv: sample_reader = csv.reader(greeting_csv) #ここでReaderオブジェクトの生成 greeting_data = list(sample_reader) greeting_data[0][3] = '備考' greeting_data[1][3] = '日本語' greeting_data[2][3] = '英語' with open(r'C:\sample\revised_sample_greeting.csv', 'w', newline='', encoding = 'utf-8') as output_file: sample_writer = csv.writer(output_file) #ここでWriterオブジェクトの生成 for i in range(0, 3): sample_writer.writerow(greeting_data[i]) output_file.close()
Pythonでcsvファイルを取り扱う方法まとめ
以上のcsvファイルを取り扱う手順をまとめると下記の通りです。
- csvファイルを使うにはcsvモジュールを使う
- csvファイルを読み込むにはReaderオブジェクトを使う
- csvファイルを読み込むにはWriterオブジェクトを使う
- csvファイルは既存のデータに書き込むのではなく、新たにcsvファイルを生成して書き込むのがオススメ
- open関数の第二引数の「r」は省略可能だが明示した方が良い
- open関数の第二引数の「w」は省略できない
- open関数の2つの引数、newline=''とencoding = 'utf-8'はおまじない。忘れない
csvファイルを使いこなしてエクセルに頼らない大量データの扱いができるようにしましょう!
*1:「'cp932' codec can't decode byte 0xef in position 0: illegal multibyte sequence」というエラーが出ます。文字には背番号が振ってあるのですが、全世界共通の背番号を振る決まりがUTF-8です。cp932というのは日本語用の背番号です。UTF-8は日本語を含めあらゆる文字が全世界で使えるので、文字化けが起きたらUTF-8にしておけば大体OKです。と、私は理解しています。