今まで動いていたコードが動かなくなったことありますよね。
read_csvでウェブ上のテキストファイルを読み込んでいたのですが、なぜかUnicodeDecodeErrorというエラーが出るようになってしまいました。今回解決できたので、ブログ記事にしておきます。
read_csvのエラーを確認
import pandas as pd
df = pd.read_csv("http://lib.stat.cmu.edu/datasets/boston_corrected.txt",skiprows=9,sep="\t")
--------------------------------------------------------------------------- UnicodeDecodeError Traceback (most recent call last) ・・・省略・・・ UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 in position 382: invalid start byte
ボストンの住宅価格データセットを読み込む時にエラーが出ました。
今までは正常動作していましたが、久しぶりに動かしてみるとUnicodeDecodeErrorになりました。
ボストンの住宅価格のデータセットとは何?という方は下記記事をご覧ください。
(ヒノマルクのデータ分析ブログの旧ブログになります。)
UnicodeDecodeErrorとは
文字列のデコード時に発生するエラーのようです。今回の例だとutf8でエンコードされている文字列のつもりでデコードしたら、utf8ではない文字コードでエンコードされていたのでエラーになってしまったようです。
The UnicodeDecodeError normally happens when decoding an str string from a certain coding. Since codings map only a limited number of str strings to unicode characters, an illegal sequence of str characters will cause the coding-specific decode() to fail. 引用:https://wiki.python.org/moin/UnicodeDecodeError
これを解決するためにはファイルのエンコード方式(UTF-8、Shift-JISなど)を特定する必要があります。
調べてみるとchardetというライブラリで特定可能なようなので確認してみました。
chardetでボストンの住宅価格データセットのエンコード方式を特定してみる
$ /Users/hinomaruc/Desktop/notebooks/my-venv/bin/python3 -m pip install chardet
Collecting chardet Downloading chardet-4.0.0-py2.py3-none-any.whl (178 kB) |████████████████████████████████| 178 kB 19.5 MB/s Installing collected packages: chardet Successfully installed chardet-4.0.0
import urllib.request
rawdata = urllib.request.urlopen('http://lib.stat.cmu.edu/datasets/boston_corrected.txt').read()
import chardet
chardet.detect(rawdata)
{'encoding': 'Windows-1252', 'confidence': 0.73, 'language': ''}
どうやらWindows-1252という文字エンコードのようです。
confidenceは0から1の間を取る「確信度」のようです。
0.6くらいを超えていればそれなりに信頼できるスコアなのではないでしょうか?(個人的主観)
ちなみにWindows-1252はラテン文字の文字コードのようです。
Windows-1252またはコードページ1252 (Code Page 1252, CP1252) は、Microsoft Windowsの英語版および他の数種の西欧言語版で従来のコンポーネントが既定で使用するラテン文字の文字コードである。引用:https://ja.wikipedia.org/wiki/Windows-1252
Windows-1252をエンコードに指定してread_csvを再実行してみる
import pandas as pd
df = pd.read_csv("http://lib.stat.cmu.edu/datasets/boston_corrected.txt", encoding='Windows-1252',skiprows=9,sep="\t")
df.head()
OBS. TOWN TOWN# TRACT LON LAT MEDV CMEDV CRIM ZN ... CHAS NOX RM AGE DIS RAD TAX PTRATIO B LSTAT 0 1 Nahant 0 2011 -70.955 42.2550 24.0 24.0 0.00632 18.0 ... 0 0.538 6.575 65.2 4.0900 1 296 15.3 396.90 4.98 1 2 Swampscott 1 2021 -70.950 42.2875 21.6 21.6 0.02731 0.0 ... 0 0.469 6.421 78.9 4.9671 2 242 17.8 396.90 9.14 2 3 Swampscott 1 2022 -70.936 42.2830 34.7 34.7 0.02729 0.0 ... 0 0.469 7.185 61.1 4.9671 2 242 17.8 392.83 4.03 3 4 Marblehead 2 2031 -70.928 42.2930 33.4 33.4 0.03237 0.0 ... 0 0.458 6.998 45.8 6.0622 3 222 18.7 394.63 2.94 4 5 Marblehead 2 2032 -70.922 42.2980 36.2 36.2 0.06905 0.0 ... 0 0.458 7.147 54.2 6.0622 3 222 18.7 396.90 5.33 5 rows × 21 columns
無事読み込むことが出来ました。
旧ブログを参照している方はpandasのバージョンアップなどでいつの間にかread_csvが上手く動かなくなっていたかも知れません。
旧ブログ側でボストンの住宅価格データセットを参照している記事には、赤文字でコメントを残しておきました。
参照
https://chardet.readthedocs.io/en/latest/usage.html#basic-usage
https://wiki.python.org/moin/UnicodeDecodeError