01.9.3
read_csvで列名がずれてValueErrorになる
ValueError: Length mismatch: Expected axis has 6 elements, new values have 5 elements は、読み込んだ DataFrame が 6 列あるのに df.columns = [...] で 5 個の名前を渡した、という報告で、原因は read_csv がファイルの構造を読み違えていることにあります。ヘッダーがないファイルを既定の header=0 で読むと 1 行目のデータが列名に化け、先頭に説明行があれば skiprows=2 で飛ばす必要があり、2 段ヘッダーは header=[0, 1]、左端の通し番号は index_col=0 で扱います。このページでは no_header.csv・report.csv・multi_header.csv・sales.csv の 4 パターンで、列数と列名の数が食い違う原因を 1 つずつ潰します。直感 #
read_csv の既定 header=0 は「1 行目は列名、2 行目からデータ」という前提です。1 行目が 2024-01-01,100,200 のようなデータなら、その値がそのまま列名になって最初の 1 行を失い、1 行目が「※この表は社内限り」のような説明文なら列名が 1 個だけになり、2 行目以降が全部 1 列に詰め込まれます。Length mismatch の 6 と 5 は「pandas が見た列数」と「あなたが渡した名前の数」なので、どちらが正しいかをファイルの先頭 3 行を見て決めます。
CSV を読み込むときに次のようなエラーが出ることがあります。
ValueError: Length mismatch: Expected axis has 6 elements, new values have 5 elements
あるいは
pandas.errors.ParserError: Expected 1 lines in header, saw 2
これは ヘッダー行の扱いが実際のファイル構造と一致していない 場合に発生します。前者は列数と列名の数のずれ、後者は header に指定した行数とファイルの見出し行数のずれで、どちらも header・skiprows・index_col の 3 つの引数で直ります。
✅ パターン 1: ヘッダーが存在しない CSV をデフォルト設定で読んでいる #
Excel の「テキスト(タブ区切り)」などで書き出すとヘッダーが省かれているケースが多いです。1 行目がデータなら header=None で「列名の行はない」と伝え、列名はあとから手で与えます。
| |
✅ パターン 2: ファイルの冒頭に説明行や空行が含まれている #
ヘッダーの前に「出力日: 2024-01-01」のような説明文が 2 行書かれている帳票では、skiprows=2 でその 2 行を読み飛ばし、3 行目を列名として扱います。
| |
✅ パターン 3: 2 行ヘッダーや複数ヘッダーを持つ #
金融機関や BI ツールから出力された CSV では、上段に「売上」「費用」のようなカテゴリ、下段に「2023」「2024」のような詳細名という 多段ヘッダー になっている場合があります。header=[0, 1] で 2 行とも列名として読み、MultiIndex を 売上_2023 のような 1 段の名前に平らにすると以降の操作が簡単になります。
| |
✅ パターン 4: インデックス列や日時列が勝手に列名扱いされている #
左端に通し番号や日付が入っている CSV は、index_col=0 でその列を行インデックスとして扱います。これを指定しないと列数の不一致や Unnamed: 0 のような余分な列が生まれます。
| |
使いどころと落とし穴 #
読み込み直後に df.shape と df.columns を表示し、列数がファイルの先頭行をカンマで割った数と一致するか、列名に数値や日付が混ざっていないかを確かめる習慣が、この種のエラーの最短の対処法です。先頭行が本当に列名かは head -n 3 report.csv で分かり、余計な説明行があれば skiprows、見出しが 2 段なら header=[0, 1]、左端が通し番号なら index_col=0 という対応になります。names で列名を与えるときは df.shape[1] と個数が合うことを先に確認し、足りないと左の列が無言でインデックスに回る挙動に注意してください。
参考 #
header・skiprows・index_col の詳細は Working with text data — pandas user guide に、header=[0, 1] で生まれる階層列名の扱いは MultiIndex / Advanced Indexing — pandas documentation にまとまっています。