01.9.1
pandas.read_csvで日本語を含んだCSVを読み込めない
pd.read_csv("filename.csv") が UnicodeDecodeError: 'utf-8' codec can't decode byte 0x92 で止まるのは、ファイルが Shift_JIS 系(Windows では cp932)で保存されているのに、pandas が既定の utf-8 で解読しようとしたからです。直し方は encoding="cp932" または encoding="shift-jis" を付けて、ファイル側の文字コードに合わせるだけです。読めたあとは df.to_csv(..., encoding="utf-8-sig") で BOM 付き UTF-8 に書き直しておくと、Excel で開いても文字化けせず、次回からは引数なしで読めます。このページでは Windows で作られた CSV を例に、エラーの読み方と 2 行の修正を示します。直感 #
CSV の中身はバイトの列で、「このバイト列をどの文字に対応させるか」の表が文字コードです。Windows の Excel やメモ帳が日本語を保存すると、1 文字を 2 バイトで表す cp932(Microsoft が拡張した Shift_JIS)になることが多く、一方 pandas の read_csv は何も言わなければ utf-8 の表で読みます。0x92 のようなバイトは utf-8 の表では「文字の先頭に来てはいけない値」なので、pandas は解読をあきらめて invalid start byte と報告します。
Python の pandas.read_csv() を使って日本語を含む CSV ファイルを読み込もうとすると、次のような UnicodeDecodeError が発生することがあります。たとえば
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x92 in position 0: invalid start byte
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x95 in position 0: invalid start byte
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
といった内容です。メッセージの 'utf-8' codec が「pandas が使った表」、byte 0x92 が「その表に載っていなかったバイト」、position 0 が「ファイルの何バイト目で失敗したか」です。0x92 や 0x95 は cp932 の 2 バイト文字の先頭に頻出する値で、Windows で作成された CSV ファイルでほぼ確実に出会います。0xff で始まるときは UTF-16 の BOM の可能性があり、encoding="utf-16" を試します。
解決法:正しいエンコーディングを指定して読み込む #
Shift-JIS の場合 #
encoding="shift-jis" は JIS 規格の範囲(JIS X 0208)だけを解読する指定で、Mac や Linux のツールが Shift_JIS で書き出したファイルに合います。
| |
CP932(Windows環境で一般的)の場合 #
cp932 は Shift_JIS に Microsoft の拡張文字を足したもので、Excel やメモ帳が保存した CSV はこちらで読むのが確実です。
| |
保存時の推奨設定 #
将来的に文字化けや読み込みエラーを避けるため、保存時は UTF-8-SIG(BOM 付き UTF-8)で出力しておくと安全です。一度 cp932 で読み込めた DataFrame をこの形式で書き直せば、次回からは encoding なしの pd.read_csv で読めます。
| |
⚠️
utf-8でも問題ありませんが、WindowsのExcelで開くと文字化けすることがあります。utf-8-sigはその対策になります。
🔠 よく使う文字コード一覧 #
| 文字コード | 用途・説明 |
|---|---|
utf-8 | 最も一般的なUnicodeエンコーディング |
utf-8-sig | BOM付きUTF-8(Excel互換性が高い) |
shift-jis | 日本語Windowsでよく使用される文字コード |
cp932 | Microsoft拡張Shift-JIS(ExcelやNotepadで作成される) |
euc_jp | UNIX系環境で使用される日本語文字コード |
iso2022_jp | 古いメールシステムなどで使用されることが多い |
使いどころと落とし穴 #
encoding を総当たりする前に、open(path, "rb").read(2) で先頭バイトを見るか、chardet.detect で推定すると 1 回で当たります。shift-jis で読めたファイルでも ㈱ のような拡張文字で 0x87 のエラーが出たら cp932 に替え、逆に cp932 で読んで 縺ア のような文字が並ぶなら中身は UTF-8 です。読み込みに成功したら to_csv(encoding="utf-8-sig", index=False) で書き直し、以後のパイプラインから encoding 引数を消すのが最も再発の少ない対処です。
📚 関連ページ #
encoding に渡せる名前の一覧は codecs — Codec registry and base classes — Python documentation の標準エンコーディング表に、encoding_errors など read_csv の関連引数は pandas.read_csv — pandas documentation にまとまっています。