ECのトランザクションを読み込む際に、氏名にカンマを使用しているケースがあった。
そのままread_csvしてしまうと、読み込みエラーとなってしまうために前処理が必要。ただいつものように処理しようにもread_csvがエラーによって使用できないのでちょっと困った。
システム側でユーザ登録時にカンマを使用できなくする、ということがコスト的に難しいため分析時に対応することとなる。
read_csvのエラー
サンプルのCSV。アイアンマン部分にカンマが使用されている。
id,name,itemid
000,tony stark,0000000000000
001,Iron,Man,0000000000001
read_csvする。
import pandas as pd
df = pd.read_csv("sample.csv")
ParserError: Error tokenizing data. C error: Expected 3 fields in line 3, saw 4
フィールドは3つだと想定されるが、3行目が4つあるっぽいからエラーとす。
全体の流れ
まずファイルを読み込むところから。with openでclose処理を省略することができる。ポイントとなるのは、読み込みモードでopenし、処理を終えた後に上書きモードで再度同名のファイルをopenして上書きをかけるところ。
読込モードではファイルへの上書きができず、上書きモードではreadが使えない。そのため、 rとwでwith openでファイルを2回開く必要がある。なかなかその方法が見つからなかった。
open mode | 対象が存在しない場合 | 読み込み | 読み込み方法 | 書き込み | 書き込み方法 |
r | エラー | 〇 | × | – | |
r+ | エラー | 〇 | 〇 | 追記 | |
w | 新規作成 | × | – | 〇 | 上書き |
w+ | 新規作成 | △ | エラーにならないが うまく読み込めず | 〇 | 上書き |
a | 新規作成 | × | – | 〇 | 追記 |
a+ | 新規作成 | △ | エラーにならないが うまく読み込めず | 〇 | 追記 |
置換処理
売上データの出力システムによって、列の並びは常に固定されているので前後の文字列ルールを利用した(桁数が固定されている)正規表現決め打ちで対応する。もっといい方法がある気もする。今回の場合は3桁の数字IDと13桁の商品IDに囲まれた部分を対象とし、maskedという文字列に置換する。
抽出部分はとりあえず分析では使用しないので、カンマが混在していない要素についてもひとまずマスクしておくことにする。
正規表現での置換なので、reモジュールのsub関数で対応。標準機能なのでインストール不要。
import re
with open('sample.csv', 'r', encoding="cp932") as f: # 読み込み用
data_lines = f.read()
print(data_lines)
after = re.sub('([0-9]{3},).*(,[0-9]{13})', r'\1masked\2', data_lines)
print(after)
with open('sample.csv', "w", encoding="cp932") as f: #書き込み用
f.write(after)
id,name,itemid
000,masked,0000000000000
001,masked,0000000000001
それっぽくできた。