pandas dataframeを.to_csvした際に、文字化け/encording errorが出た際の対処法


はじめに

dataframeを.to_csvでcsvにし、そのデータをエクセルで開いた際に、
データの日本語部分が文字化け&enconding errorが出てしてしまったので、
その際の対処法備忘録として書いておきたいと思います。

環境: MacOS Catalina

通常のcsv書き出し(データに日本語が入っていない場合)

import pandas as pd

df = pd.DataFrame([
  ["1", "taro"],
  ["2", "hanako"]],
  columns=['id', 'name'])

# test.csvとして出力
df.to_csv("test.csv")

もちろん出力されたファイルをエクセルで開いても文字化けしない。

文字化けしてしまう(データに日本語が入っている場合)

import pandas as pd

df = pd.DataFrame([
  ["1", "太郎"],
  ["2", "花子"]],
  columns=['id', '名前'])

# test.csvとして出力
df.to_csv("test.csv")

日本語のところのみ文字化け

文字化けした際の対策

import pandas as pd

df = pd.DataFrame([
  ["1", "太郎"],
  ["2", "花子"]],
  columns=['id', '名前'])

# test.csvとして出力 encodingに"shift-jis"を指定。
df.to_csv("test.csv",encoding="shift-jis")

encodingを何も設定しない場合は、自動的に "utf-8" という文字コードが設定されてしまうそう。
それをshift-jisにすることで文字化けが解消される!

文字化けは解消されたが、enconding errorが出てしまった・・・

他のデータフレーム(Windowsで作成したエクセルを取り込んだもの)も同じように、取り込んで、色々処理をした後、
.to_csvを使って、csvにしてみたところ、以下のエラーが。

import pandas as pd

# エクセルが置いてあるファイルパスを指定
filepaths = glob('./*.xlsx')
# 読み込んだエクセルを読み込む。読み込んだエクセルには、\n、¥n、\u0020などエスケープシーケンスが入った文字が多く入っている。
df = pd.read_excel(filepaths[0],engine='openpyxl')

...dfに対しての色々な処理(省略)....

# test.csvとして出力 encodingに"shift-jis"を指定。上と同じ。
df.to_csv("test.csv",encoding="shift-jis")

発生したエラー

File "pandas/_libs/writers.pyx", line 49, in pandas._libs.writers.write_csv_rows
UnicodeEncodeError: 'shift_jis' codec can't encode character '\u2161' in position 54: illegal multibyte sequence

\u2161という文字が、encodingで指定した文字コード、今回はshift-jisでは
割り当てていない文字とのことで、エラーが出てしまいました。

その場合は、以下のように書くと解消されました。

    # 一度ファイルオブジェクトをエラー無視して、書き込みで開くようにする
    with open("./output/test.csv", mode="w", encoding="shift-jis", errors="ignore") as f:
        # ここでデータフレームを開いたファイルにcsvで書き込む
        df.to_csv(f)

errors="ignore"で無効なバイト列を無視するを指定。
mode="w"で書き込む(write)という指定をしています。
errorsのオプションはreplace(無効なバイト列を?に置き換える)
backslashreplace(無効なバイト列にバックスラッシュを添える)
surrogateescape(サロゲート領域の代理バイト列に置き換える)などあるそうです。