はじめに
小さな恋のうた♪ ならぬ小さな気づきの記事、nikkieです。
Pythonのcsvモジュールに関する小さな気づき(ただしここ最近のエントリをつなぐもの)の共有です。
目次
結論
以下のようなTSVファイルが手元にあるとします。
2005 名詞 数 * * * * * B-DAT 年 名詞 接尾 助数詞 * * * 年 ネン ネン I-DAT 7 名詞 数 * * * * * I-DAT た 助動詞 * * * 特殊・タ 基本形 た タ タ O 。 記号 句点 * * * * 。 。 。 O また 接続詞 * * * * * また マタ マタ O
- 空行を含む
- フィールドの数がまちまち
- 1行目は9個
- 2行目は11個
きれいなTSVではないから1行ずつ処理が必要と思われるかもしれませんが、なんと以下のコードで読み込めます!
動作環境:Python 3.10.9
>>> with open("example.tsv", encoding="utf8", newline="") as f: ... reader = csv.reader(f, "excel-tab") ... for row in reader: ... print(len(row), row) ... 9 ['2005', '名詞', '数', '*', '*', '*', '*', '*', 'B-DAT'] 11 ['年', '名詞', '接尾', '助数詞', '*', '*', '*', '年', 'ネン', 'ネン', 'I-DAT'] 9 ['7', '名詞', '数', '*', '*', '*', '*', '*', 'I-DAT'] 11 ['た', '助動詞', '*', '*', '*', '特殊・タ', '基本形', 'た', 'タ', 'タ', 'O'] 11 ['。', '記号', '句点', '*', '*', '*', '*', '。', '。', '。', 'O'] 0 [] 11 ['また', '接続詞', '*', '*', '*', '*', '*', 'また', 'マタ', 'マタ', 'O']
空行は空のリストなので、if not row:
のような形で検出できますね。
解説パート:過去エントリとのつながりを明かすんだよ
例にしたTSVファイルは、最近素振りした固有表現抽出のチュートリアルより。
https://github.com/Hironsan/IOB2Corpus/blob/master/hironsan.txt
csv.reader(f, "excel-tab")
の第2引数はdialect
引数を指定。
delimiter="\t"
と同じです。
以下の記事でソースコードを眺めて得た知見です(「TSVファイル用のDialectの存在を知る」の部分)。
組み込み関数open
の呼び出しのnewline=""
はCSVモジュールのドキュメントでもオススメの指定ですね。
csv.DictReader
のソースコードを読んだときに、ヘッダーと1行の長さが合わない場合の処理がありましたが(restkey
引数)、こういうケースに対応するためのものだったのか!
裏話:ChatGPTとおしゃべりしていて気付く
ChatGPTさん、CSVファイルにカンマ区切りの金額を載せてくるお茶目さん
— nikkie にっきー (@ftnext) 2023年4月26日
従業員番号,氏名,部署,給与
001,山田太郎,経理部,350,000円
Pythonのcsvで読み込んだら
['従業員番号', '氏名', '部署', '給与']
['001', '山田太郎', '経理部', '350', '000円'] pic.twitter.com/ugLkk9VFAA
クォートで囲まずカンマ区切りの金額を載せてくるというドジっ子アピール1ですが、これ、ヘッダーとそれ以外の行でフィールド数違うけど読めてんじゃん!!
- ヘッダーは4フィールド
- ヘッダー以外は5フィールド(金額中のカンマで分割されちゃう)
このときはopen
のnewline
引数の挙動を理解したいという裏目的があり、この後は空行を含むCSVの生成もお願いしましたが、空行があっても全然読み込めます。
これが固有表現抽出チュートリアルで扱ったTSVにも適用できることに気づきました!
本エントリ、爆誕す!
固有表現抽出チュートリアル素振りコードのTSV読み込みの書き換えはこちら:
https://github.com/ftnext/ml-playground/commit/fb2055d5c0a16ff03c5742c674c1ef97ebbd5375
終わりに
フィールドの数がまちまちだったり空行を含んだりしていても、Pythonのcsvモジュールで読み込めるという気づきをアウトプットしました。
フィールドの数が揃ったきれいめなCSVをふだん扱っている2ので見えていませんでしたが、きれいじゃないCSVも扱えるようにcsvモジュールはできていたんですね。
以前取り上げたこちらのツイートに、今の私は別の見方ができそうです。
Pythonってlistとtuple区別されてるの? やったー!と思って組み込みのcsvモジュールを使ってみたら行がlistで返ってきたときの顔 https://t.co/zCLaCddYVX
— にゃんだーすわん (@tadsan) 2023年4月18日
csv ファイルから読み込まれた各行は、文字列のリストとして返されます。
とあります。
また、デザインと歴史 FAQにリストは、
全て同じ型の可変数のオブジェクトを持ち
とあります。
CSVファイルの1行を表すのはいくつか(可変数個)の文字列なので、文字列のリストになっているのかもと思いました。
さらに詳しくはPEPや開発者メーリスを掘り下げることになりそうです。