טיפ פנדס: איך להתעלם מטעויות Encoding בקובץ

11/09/2020

פוסט זה כולל טיפ קצר לעבודה יעילה עם Python. אם אתם רוצים ללמוד פייתון יותר לעומק אני ממליץ על קורס Python כאן באתר.
הקורס כולל עשרות שיעורי וידאו והמון תרגול מעשי וילמד אתכם Python בצורה מקצועית מההתחלה ועד הנושאים המתקדמים.

הפקודה read_csv של פנדס היא מופלאה. רוב קבצי ה CSV שאנחנו מוצאים בדוגמאות באינטרנט כתובים בקידוד UTF8 וזה בדיוק גם קידוד ברירת המחדל של read_csv.

אבל כשעוברים ממשחקים לעולם האמיתי אנחנו מוצאים קבצי CSV פחות נחמדים: החל מקבצים ישנים שמקודדים ב Extended ASCII או במקרה העוד יותר גרוע קבצים שמערבבים תווים בכל מיני קידודים.

כך קרה לי כשניסיתי לפתוח את מאגר המידע של כלי רכב בארץ. כן, מסתבר שיש דבר כזה (ובכלל אתר מאגרי המידע הממשלתי עליו גיליתי לא מזמן הוא ממש אוצר). בכל מקרה מסתבר שהממשלה שמחה לחלק לנו פרטים על כל רכב בארץ, אבל היא עושה את זה דרך קובץ CSV שרובו מקודד ב ISO8859-8 אבל לא כולו.

פנדס ממש לא אהב את זה וכשניסיתי לטעון את המאגר לפנדס קיבלתי את ההודעה הבאה:

>> pd.read_csv('053cea08-09bc-40ec-8f7a-156f0677aff3.csv', '|')

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xee in position 0: invalid continuation byte

עד לפה לא מבהיל מדי כי תמיד אפשר להעביר Encoding לפנדס. אבל הפעם גם זה לא עבד:

>> pd.read_csv('053cea08-09bc-40ec-8f7a-156f0677aff3.csv', encoding='iso8859-8')

UnicodeDecodeError: 'charmap' codec can't decode byte 0xd2 in position 127430: character maps to <undefined>

מה עושים? תשמחו לשמוע שיש פיתרון יחסית פשוט: נפתח את הקובץ עם הקידוד שאנחנו רוצים ונבקש מ open שתחליף תווים שלא תואמים לקידוד בסימני שאלה. את ה File Handle נעביר לפנדס שישמח לקבל את המידע אחרי פיענוח. הקוד כולו נראה כך:

>> fd = open('053cea08-09bc-40ec-8f7a-156f0677aff3.csv', encoding='iso8859-8', errors='replace')
>> df = pd.read_csv(fd, '|')

עכשיו אפשר להינות מהמידע שהצלחנו לקרוא למשל מי יצרנית הרכב הפופולרית בישראל:

df.groupby('tozeret_nm').size().sort_values(ascending=False)

tozeret_nm
מזדה יפן         299175
יונדאי קוריאה    228002
קיה קוריאה       205592
טויוטה יפן       189340
סקודה צ'כיה      173473