CSV ファイルが見た目よりも難しい理由
新しい学生に CSV ファイルで何がうまくいかない可能性があるかを尋ねると、たいてい「特に何も—ただのテキストだから」と答える。そこで私は彼らに実際の CSV の悪夢のコレクションを見せると、彼らの自信が一瞬で消え去る。 CSV は「カンマ区切りの値」を意味するが、その名前は誤解を招く。実際には、CSV ファイルはカンマ、セミコロン、タブ、パイプ、またはデータをエクスポートした人がその日に使いたかった任意の文字で区切られている。ヘッダーがあるかもしれないし、ないかもしれない。テキストフィールドの周りに引用符を使うかもしれないし、使わないかもしれない。そして、日付を「MM/DD/YYYY」や「DD-MM-YYYY」、「YYYY/MM/DD」としてエンコードするか、Unix タイムスタンプや Excel シリアル番号(本当に)としてエンコードするかもしれない。 CSV の「標準」(RFC 4180)は、ほとんどのソフトウェアが陽気に無視する提案のようなものである。Microsoft Excel は地域設定に応じて異なる方法で CSV をエクスポートする。Google Sheets は独自のフォーマットに関する考え方がある。データベースのエクスポートも別の一連の規則に従う。そして、複数のソースからデータを引き出すとき—これが基本的にすべての現実世界のプロジェクトである—矛盾に直面することが保証されている。 ここで特に危険なのは、Pandas は助けになろうとすることだ。データ型、区切り文字、エンコーディング、および欠損値に関して仮定を立てる。そして、その仮定が正しい場合もあれば、壊滅的に間違っている場合もある。そして時には—サラのケースのように—エラーを投げずに、ただ静かにデータを壊してしまうことがある。 私は学生が Pandas が 30% の日付を誤って解析したデータセットで高度な機械学習モデルを構築するのに何日も費やすのを見た。Pandas が通貨記号をテキストとして解釈し、すべてを文字列に変換した収益データに基づいてビジネスの提案を行うアナリストを見てきた。Pandas が「N/A」をある列では欠損データとして読み込んでいたが、別の列では文字列「N/A」として処理している状況をデバッグしてきたのである。なぜなら、データ型が異なるからだ。 解決策は CSV ファイルを避けることではない―それらは普遍的でしばしば避け難い。ただし、Pandas が CSV を読み込むときに何をしているかを正確に理解し、Pandas が行うすべての仮定を明示的に制御することが解決策である。それこそがこのチュートリアルの目的である: 「うまくいくといいな」から「私のデータで何が起こっているかを正確に把握している」に進むことだ。Pandas CSV 読み込みパイプライン: 実際に何が起こるか
コードに入る前に、`pd.read_csv()` を呼び出したときに裏で何が起こるのかを理解する必要がある。これは学問的な知識ではない。これを理解することが、CSV ファイルに苦しむ学生と自信を持って扱う学生を分けるものだ。 Pandas が CSV ファイルを読むとき、いくつかの異なるフェーズを経て進む: フェーズ 1: ファイルアクセスとエンコーディング検出 Pandas はファイルを開き、バイトをテキストにデコードしようとする。デフォルトでは、UTF-8 エンコーディングを仮定しており、これは多くの現代のファイルに適しているが、古いデータには壮大に失敗することもある。エンコーディングが間違っていると、Pandas はエラーを投げるか、問題のある文字を静かに疑問符または Unicode 置換文字に置き換えるかする。 フェーズ 2: 区切り文字の検出 Pandas は最初の数行を見て、どのキャラクターが列を区切っているかを推測する。この点に関しては通常かなり良いが、「かなり良い」は「常に正しい」とは異なる。最初の 100 行がカンマを使用しているファイルを見たことがあるが、101 行目でセミコロンに切り替わることもあった。なぜなら誰かがファイルを手動で編集したからだ。 フェーズ 3: ヘッダー検出 Pandas は最初の行に列名が含まれていると仮定する。CSV にヘッダーがない場合、Pandas は最初のデータ行を列名として扱い、これが混乱を招く。CSV に複数のヘッダー行(Excel エクスポートでよく見られる)がある場合、Pandas は最初の行しか使用しない。 フェーズ 4: データ型推論 ここが本当に興味深いところだ。Pandas は各列の最初の数行を調べてデータ型を推測する。数字は整数または浮動小数点になる。テキストは文字列になる(または Pandas の用語では「オブジェクト」 dtype)。日付は... 日付は複雑だ。日付のように見えれば、Pandas はそれを解析しようとするが、「日付のように見える」という定義はあなたのデータとは一致しないかもしれない。 フェーズ 5: 欠損値処理 Pandas には欠損値と見なす文字列の組み込みリストがある: "NA", "N/A", "NULL", "NaN", 空文字列、およびいくつかの他のもの。データが別の慣例を使用している場合(「MISSING」や "---"、または "9999" など)、Pandas はそれを欠損値として認識しない。 これらの各フェーズには仮定が含まれている。そして、すべての仮定は静かなデータ破損の機会である。信頼性の高い CSV インポートの鍵は、これらの仮定をパラメータを通じて明示的にすることである。見えない小数点の物語
2023 年春のコホートからのマーカスについてお話ししよう。彼はヨーロッパの e コマース会社の売上データを分析しており、分析結果によれば Q3 で平均注文額が謎の 90% 減少したと示された。彼のマネージャーはパニックになり、重大なビジネス上の問題があると考えた。 マーカスは 2 日をかけて調査した。彼はデータベースのクエリをチェックし、エクスポートプロセスを確認し、生の CSV ファイルをテキストエディタで調べた—すべてが問題なさそうに見えた。CSV 内の数字は正しかった: 1,234 ユーロ 56 セントのための「1.234,56」、ヨーロッパの慣例に従って小数点のためにカンマを、千の区切りのためにピリオドを使用している。 しかし、データを Pandas にロードしたとき、これらの数字は 1.234(1.2.3.4 という意味)になった。Pandas はピリオドを小数点と解釈し、なぜならそれがアメリカの慣例だからだ。カンマ? Pandas はそれを千の区切りと誤解して無視した。そのため「1.234,56」は 1.234 になり、「5.678,90」は 5.678 になった。データセット内のすべての金額が 100 倍以上も間違っていた。 問題を特定したときの修正は簡単だった: `pd.read_csv()` で `decimal` と `thousands` のパラメータを指定することだ。しかし、問題を見つけるのに数日かかった。データは一見合理的に見えたからだ。数字は数値であり、正しい列に存在し、ただ単に完全に間違っていただけだった。 CSV インポートが危険だと言ったのはこのためだ。エラーは必ずしも明らかではない。必ずしも例外が発生するわけではない。時には、データが静かに不正確になり、すでにそれに基づいて決定を下すまで気付かないことがある。 マーカスの話にはハッピーエンドがある—実際の被害が出る前にエラーを発見できた。しかし、業界の同僚からは、データが誤っていることに誰かが気づくまでエグゼクティブのプレゼンテーションまで進んでしまった分析の恐ろしい話を聞いたことがある。ある企業は、破損した CSV インポートに基づいて数百万ドルの投資決定を下しそうになった。データ型の理解: 正しいインポートの基礎
実践的に行こう。こちらが学生プロジェクトでよく見られるデータ型の問題とその対処方法を示した表である:| データ型 | 一般的な問題 | Pandas のデフォルトの動作 | 正しいアプローチ |
|---|---|---|---|
| 整数 | 先頭のゼロ(郵便番号)、テキストとして保存された大きな数字 | int64 に変換し、先頭のゼロを削除する | コードには dtype='str' を、nullable integer には dtype='Int64' を使用 |
| 浮動小数点 | 通貨記号、千の区切り、ヨーロッパの小数点 | 非数値文字が存在する場合はオブジェクト(文字列)に変換 | 最初にデータをクリーンアップするか、converters パラメータを使用 |
| 日付 | 複数のフォーマット、タイムゾーンの問題、Excel シリアル日付 | フォーマットが明白でない限り、文字列のままにする | 明示的なフォーマット文字列を使用した parse_dates を使用 |
| ブーリアン | Yes/No、True/False、1/0、Y/N のバリエーション | 文字列のままにする | インポート後に converters を使用するか、マッピングする |
| カテゴリ | 繰り返される文字列値(州、国、製品タイプ) | オブジェクトとして保存し、メモリを浪費する | 効率のために dtype='category' を使用 |
| 欠損値 | 空の文字列、"N/A"、"NULL"、"---"、9999 など | 標準の NA 値のみを認識する | na_values パラメータを使用してカスタム欠損指標を指定 |
エンコーディングの問題: なぜあなたの国際データが壊れるのか
学生の大半を驚かせることをお話ししましょう: テキストをバイトにエンコードする方法は数十通りあり、CSV ファイルには使用されているエンコーディングについてのメタデータが含まれていない。あなたはただ推測する必要があり、間違った推測をすればデータが壊れることになる。「顧客フィードバックデータを分析するのに 6 か月かかりましたが、インポート中にすべてのアクセントマーク、すべての絵文字、すべての非英語文字が壊れていたことに気づくまでかかりました。私たちの感情分析モデルはゴミデータでトレーニングされており、英語のレビューが良好に見えたため、誰も気づきませんでした。」 — 元学生、現在はフォーチュン 500 企業の機械学習エンジニアUTF-8 は現代の標準であり、最初の推測とすべきである。しかし、古いシステムはしばしば Latin-1(ISO-8859-1 とも呼ばれる)を使用し、Windows システムは CP1252 を使用するかもしれない。もし東アジアのデータを扱っているなら 、Shift-JIS、GB2312、または Big5 に直面するかもしれない。 どのエンコーディングを使用すればよいのかはどうすれば分かるのか?時々、ファイルを提供した人に尋ねることができる。時々、あなたはそれを調べなければならない。