前置き
普段データの前処理などをやってます。
たいていのデータはpandasで読めればなんとかなるけど、読めないデータに遭遇することもあるので奴らとの格闘の記録を残しておきます。
どんなデータか
- 区切り文字はカンマ「,」で各データはダブルクォート「"」で囲まれている。
- データ中("と"の間)に改行コードが含まれている。
- データ中にカンマが含まれている。
- データ中にダブルクォートが含まれている。
↓例えるならこんな感じ
"a","b"
"1","ほ\nけ""
"2","ふ,か'"
※オマケにシングルクォートも足しました。
目指すもの
- Pythonのライブラリであるpandasのread.csv()で読み込めるcsvファイルを作成する。
- あくまで前処理の前段部分なのでこの後の処理のためにもDataFrameにしたい。
- カンマやクォートは意味がある可能性を考慮してそのままデータの一部として扱う。
- データ中の改行コードは悪さしかしないので取り除く。
↓つまりこういうDataFrameにしたい。
a | b |
---|---|
1 | ほけ" |
2 | ふ,'か' |
失敗例
pandasでそのまま読もうとする
import pandas as pd
df = pd.read_csv('hoge.csv')
print(df)
結果
a | b | |
---|---|---|
1 | ほ\nけ"\n2" | ふ,か' |
成功したやり方
スクリプト
- Pythonのバージョンは3.7
import re
import pandas as pd
# テキストとして読み込む
with open('hoge.csv', 'r') as f:
text = f.read()
tmp_text = re.sub('([^"])\n([^"])', r'\1\2', text) # データ途中の改行コード(\n)を取り除く
tmp_text = re.sub('","', '\t', tmp_text) # 区切り文字をタブに変換
tmp_text = re.sub('(^"|"$)', '', tmp_text) # ファイルの最初と最後のクォートを外す
tmp_text = re.sub('"\n"', '\n', tmp_text) # 途中のクォートを外す
# いったんファイルに吐き出す
with open('data.csv', 'w') as f:
f.write(tmp_text)
# 確認する
df = pd.read_csv('data.csv', sep='\t')
print(df)
出力
a b
0 1 ほけ"
1 2 ふ,か'
読めた。
ファイル
ファイルの中身はこんな感じ
data.csv
a b
1 ほけ"
2 ふ,か'
懸念事項
データに\tが含まれていた場合、今回のコードでは当然うまくいかない。
改行コードが違った場合も同様。
どの文字が含まれていて、どう置き換えればうまくいくかチェックする必要がある。
→チェック用のメソッド作成と、区切り文字のパラメータ化?
気が向いたらやる。
jupyter上で処理すればデータの確認もソースの変更も楽なので必要ないかも…?
結論
pandasで読めてしまえばもうこっちのもの。
pandasだけでなく、BIツールに食わせる前にも使えるはず。
正規表現って便利!!