Pythonでデータファイルを1行ずつ読み込む方法

Pythonでデータファイルを1行ずつ読み込む方法

データの解析時に.csvや.datのファイルを1行ずつ読み込みたいってことありますよね。この記事では、Pythonを使ってファイルを1行ずつ読み込む方法を具体的に解説していきます。

動作検証済み環境
macOS Catalina(10.15.7), python3.7.6, Atomエディタ1.44.0

ファイルを読み込むまでの流れ

ファイルを読み込む手順は次のようになります。
1. ファイルを用意する
2. 読む込むためのコードをかく
3. プログラムを実行する

datファイルやcsvファイルなどのファイルの種類が変わっても基本的にやることは同じですが、書くコードが少しだけ異なります。
まずはdatファイルのデータを読み込む方法を見ていきましょう。

datファイルを1行ずつ読み込む方法

datファイルを準備しよう

average_temperature_kyoto_2018.dat という2018年の京都市における各月の平均気温のデータが格納されたデータファイルを用意しました。

# averaged temperature in 2018 @ Kyoto city
# 01: month 02: averaged temperature in the daytime
1 3.9
2 4.4
3 10.9
4 16.4
5 20.0
6 23.4
7 29.8
8 29.5
9 23.6
10 18.7
11 13.5
12 8.2

一列目には月、二列目に日中の平均気温が並んでいます。
一列目と二列目は (半角スペース)で区切られています。
また、# で始まる行はコメント部分を意味します。
.dat という拡張子はデータが格納されたファイルを意味しており、ただのテキストファイルと同じだと思ってください。

Desktop/LabCode/python/data-analysis/inputfile_eachrow というディレクトリにこのaverage_temperature_kyoto_2018.dat を保存しておきます。

datファイルを1行ずつ読み込むためのコード

average_temperature_kyoto_2018.datと同じ階層にinputfile.py と名付けたファイルを保存します。
いきなり結論から入りますが、ファイルを読み込むためのコードは次のように書きます。

input_data = open('average_temperature_kyoto_2018.dat', 'r')

# 一行ずつ読み込んでは表示する
for rows in input_data:
    # コメントアウト部分を省く処理
    if rows[0]=='#':
        continue
    
    # 値を変数に格納する
    row = rows.rstrip('\n').split(' ')
    month = row[0]
    ave_temperature = row[1]
    
    # 各行の内容を確認
    print(month, ave_temperature)

# ファイルを閉じる
input_data.close()

プログラムを実行しよう

上記のプログラムを実行してみましょう。
ターミナルを開いて、cwdをDesktop/LabCode/python/data-analysis/inputfile_eachrow にして、実行します。
(→やり方がわからない方はプログラムを実行する方法を参考にしてください。)

python inputfile.py

# (実行結果)
# 1 3.9
# 2 4.4
# 3 10.9
# 4 16.4
# 5 20.0
# 6 23.4
# 7 29.8
# 8 29.5
# 9 23.6
# 10 18.7
# 11 13.5
# 12 8.2

うまくいけば上のように実行結果が表示されると思います。
なんの説明もなかったので、次はそれぞれの行が何を意味するかを説明します。

コードの解説

data = open(‘average_temperature_kyoto_2018.dat’, ‘r’)

open(filename)でファイルを開きます。data = open(filename)としているので、そのファイルに格納されているデータをdataという引数に入れています。r は読み込みmodeを意味します。open()はデフォルトで読み込みmodeなので、今回の場合は rの部分を省略して、open('average_temperature_kyoto_2018.dat')と書いても問題ありません。

for rows in input_data:

for xxx in ooo:というforループの構文です。
xxxの部分にrowsと記述していますが、好きな文字でいいです。
この構文の処理内容ですが、
1. ooo のデータを1行取り出して、xxxに格納
2. for 以下に記述してる処理を実行する
1 → 2の処理を繰り返し、oooに格納されているデータの最後の行まで処理を行ったら終了

if row[0]==’#’:

rowには各行の情報が格納されています。
row[0]rowというリストの一番最初のデータを意味します。
例えば、rowの中にこんにちはという文字列が格納されていたなら、
row[0]row[1]row[2] 、、、ということです。
なので、この行の意味はもしrow[0]が#なら~を実行するとなります。

row = rows.rstrip(‘\n’).split(‘ ‘)

rows.rstrip('\n')'\n'(改行)をrowsの末尾から削除するという処理です。
print(rows)を実行してみるとわかるのですが、
例えば1 3.9\nとなっています。3.9のすぐ後に改行が入っています。この改行を削除しています。
次に.split(' ')ですが、' '(スペース) で文字列を分割するという処理です。分割された文字列は今回ならrowという引数に格納されます。
こんな感じで ['1', '3.9']
これらはrow[0] row[1]で取り出せます。

input_data.close()

openしたらならcloseしましょう。お作法です。

(応用) コメント部分の除外方法

上ではコメント部分を除外するためにif rows[0]=='#': continueと記述しましたが、python標準搭載のre.matchモジュールを使えば少しだけシンプルに記述できます(pythonにこなれてる感が出せるぞ)。
モジュールを使った場合のコード全体は次のようになります。

import re

input_data = open('average_temperature_kyoto_2018.dat', 'r')

for rows in input_data:
    if not re.match('#', rows):
        # 区切り
        row = rows.rstrip('\n').split(' ')
        month = row[0]
        ave_temperature = row[1]
        
        # 各行の内容を確認
        print(month, ave_temperature)

input_data.close()
MEMO
re.matchモジュールを使う場合は上部でimport reと記述しましょう
if not re.match(‘#’, rows):

もしrowsの先頭が#でないなら、以下の処理を実行する。という処理になります。これにより、#が先頭についた行を除外できます。

csvファイルを1行ずつ読み込む方法

csvファイルが何かを知っていれば、上記のコードを少し変更するだけで読み込めます。csvファイルとは Comma-Separated Valuesファイルの略で、コンマ区切りされたファイルのことです。よって、スペース区切りだったところをコンマ区切りに変更すれば良いのです。

csvファイルを準備しよう

average_temperature_kyoto_2018.csv というファイルを用意しました。
上と同じく、Desktop/LabCode/python/data-analysis/inputfile_eachrow に置きます。
中身は以下のようになっています。

# averaged temperature in 2018 @ Kyoto city
# 01: month  02: averaged temperature in the daytime
1,3.9
2,4.4
3,10.9
4,16.4
5,20.0
6,23.4
7,29.8
8,29.5
9,23.6
10,18.7
11,13.5
12,8.2

なお、Atomエディターでcsvを開く場合はtablrというプラグインをインストールしましょう。
pluginのinstall画面でtablrで検索すれば、インストールはすぐにできます。

csvファイルを1行ずつ読み込むためのコード

rows.rstrip('\n').split(' ')rows.rstrip('\n').split(',')に書き換えればOKです!
全体のコードは次のようになります。
出力結果もdatファイルの時と同じになります。

import re

input_data = open('average_temperature_kyoto_2018.csv', 'r')

for rows in input_data:
    if not re.match('#', rows):
        row = rows.rstrip('\n').split(',')
        month = row[0]
        ave_temperature = row[1]
        print(month, ave_temperature)

input_data.close()

(ちょっと応用)with構文を使ったファイルを1行ずつ読み込むためのコード

with構文with ~ as ~:を使うと、close()を書く必要がなくなるので、もうちょっとだけシンプルにコードを書くことができます。
以下の例えばcsvファイルの読み込みなら以下のようなコードになります。

import re

input_file = 'average_temperature_kyoto_2018.csv'

with open(input_file) as input_data:
    # 一行ずつ読み込んでは表示する
    for rows in input_data:
        # コメントアウト部分を省く処理
        if not re.match('#', rows):
            # 区切り
            row = rows.rstrip('\n').split(',')
            month = row[0]
            ave_temperature = row[1]

            # 各行の内容を確認
            print(month, ave_temperature)
with open(input_file) as input_data:

このように記述することで、input_fileのデータはinput_dataの中に入ります。
input_data という文言は自由に設定できます)
あとは、これまでと同じように下にfor文で1行ずつ読み込んでは表示する処理を行うだけです。

pythonに慣れてきたらぜひwith構文を使ってみましょう!