CSVで要素内にカンマが入っている場合の前処理

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+新規作成エラーにならないが
うまく読み込めず
追記
https://neko-py.com/python-open-mode

置換処理

売上データの出力システムによって、列の並びは常に固定されているので前後の文字列ルールを利用した(桁数が固定されている)正規表現決め打ちで対応する。もっといい方法がある気もする。今回の場合は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

それっぽくできた。

このサイトの主
投稿を作成しました 98

関連投稿

検索語を上に入力し、 Enter キーを押して検索します。キャンセルするには ESC を押してください。

トップに戻る