memopy

pythonで作ってみました的なブログ

pythonで複数行のcsvファイルを1行にする(正規化)

pythonで複数行のcsvファイルを1行にする(正規化)

今回も前回に引き続き、pythoncsvファイルの編集を行う。
前回の記事はこち
pythonでcsvファイルの編集をする - memopy

今回は、複数行のレコードを1行にするいわゆる正規化の方法について紹介する。
下図のようなcsvファイルを想定する。
f:id:memopy:20170608153634p:plain
このように必要な情報が1行にまとまっていない、情報の繰り返しがあるデータはデータベースでは非常に扱いづらい。
これを1行にし、繰り返しをなくすことを正規化という。

スクリプト全文

※python3で作成したが、python2でも動くはず。

# -*- coding:utf-8 -*-

# 編集したいファイル(元ファイル)を開く
file = open("顧客データ.csv","r")
# 書き出し用のファイルを開く
out_file = open("出力データ.csv","w")

# 書き出し用ファイルのヘッダーを記述
out_file.write("ID,氏名,都道府県,電話番号\n")

# 元ファイルのヘッダーをreadlineメソッドで1行飛ばす
file.readline()
# 元ファイルのレコード部分をreadlinesメソッドで全行を読み取る
lines = file.readlines()

# for文で1行ずつ取得
for line in lines:
    # 改行コードをブランクに置換
    line = line.replace("\n","")
    # カンマ区切りでリストに変換する
    line = line.split(",")

    # もし取得した行の先頭が#だったら、都道府県名を取得する。
    if line[0][0] == "#":
        pref = line[0].replace("#","")

    # 取得した行が都道府県でなかったら、書き出しの処理
    else:
        # 変換後のカンマ区切りの雛形を作り、変換処理した値を入れ込む
        row = "{},{},{},{}\n".format(
            line[0],
            line[1],
            pref,
            line[2]
            )
        # 書き出し用のファイルに出力
        out_file.write(row)

# 2つのファイルを閉じる
file.close()
out_file.close()

正しく変換された。
f:id:memopy:20170608154811p:plain

細部補足説明

前回の記事から変更したロジックは次の部分のみ。

# もし取得した行の先頭が#だったら、都道府県名を取得する。
if line[0][0] == "#":
    pref = line[0].replace("#","")

# 取得した行が都道府県でなかったら、書き出しの処理
else:
    # 変換後のカンマ区切りの雛形を作り、変換処理した値を入れ込む
    row = "{},{},{},{}\n".format(
        line[0],
        line[1],
        pref,
        line[2]
        )
    # 書き出し用のファイルに出力
    out_file.write(row)

このcsvファイルは、都道府県情報が入っている行の1文字目は#となっている。
そのため、1文字目が#のときは、変数に都道府県を格納だけし、
1文字目が#でない行(=繰り返し部分)で、格納した変数(都道府県)も含めて、csvへ書き出しの処理をする。
都道府県の変数は、繰り返し部分を処理している間は、同じ値を持ち続けるという仕組みだ。


このように繰り返し部分とそうでない部分に規則性があれば、if-elif-else構文で正規化できる。
このように正規化されていないデータは結構世の中にあるので、意外と使う機会も多いであろう。

質問や記事の誤りがありましたらコメントお願いします。

【別の記事】tkinterで家計簿アプリを作りました。
memopy.hatenadiary.jp