read_csvで「Usecols do not match columns, columns expected but not found」と表示されたら、使いたい列の名前と、CSVから実際に読めた見出しを比べます。空白だけが原因とは限りません。区切り文字や見出し行が違えば、列全体を一つの名前として読んでいる場合もあります。
対象は、pandasでCSVを開いたことがあり、必要な列だけ読みたい人です。本稿では架空の研修一覧を8パターンに変え、3パターンを採用、5パターンを理由付きで保留します。正規化による列名の衝突や、エラーが出ずに必須列を落とす例まで、自分の環境で確かめられます。
確認日:2026年10月14日。pandasのread_csv仕様は3.0.6表示を確認しました。掲載教材の参照実行はPython 3.12.14・pandas 2.2.3です。仕様の確認と、この実行環境での結果を分けて記載します。PythonのCSV仕様とUnicode正規化の資料も参照しています。
usecolsエラーを、列名・区切り・見出し行から切り分ける
エラーの列名と、実際に読めたcolumnsを見比べる
usecolsは、読み込みたい列を指定する引数です。本稿で必要なのはmember_idとamountの二列です。しかし、CSVの見出しが「 amount」のように先頭空白付きなら、amountという名前とは一致しません。目で表を眺めるだけでなく、読み込まれた列名を確認します。
診断をするときは、元のファイルを上書きせず、usecolsを一度外した小さい読み込みでcolumnsを調べます。大量のデータ本体を表示する必要はありません。通常の一段の見出しなら、nrows=0で見出しだけを確認する方法があります。そのときも、sepやheaderは現在の設定を控えておきます。
列名の前後が見えにくい場合、各名前をreprで表示すると空白や改行の位置を追いやすくなります。例えばamountとamountの後ろに全角空白がある名前は、通常の表示では似て見えます。名前をコピーして見比べるだけでなく、どの文字が異なるかを確認してください。
エラーに挙がった列を、元のCSVへ無条件に追加するのは避けます。amountが本当にないファイルなのか、別名で入っているのか、読み取りの区切りが違うのかを先に調べます。欠けた金額列を0で作れば読み込めても、「金額が未記録」と「0円」を混ぜてしまいます。
列名は、表を使う人との約束でもあります。入力元がfeeという名前で受講料を渡しているなら、amountへ変更してよいかは意味の確認が必要です。税込金額と税抜金額、請求額と支払額まで、見た目が近いからという理由で一つへまとめないでください。
本稿の確認表には、元の列名、採用する名前、変更の理由を残します。後から入力側へ質問するときに、「読み込めません」だけでは原因を伝えにくいためです。データ本文を共有せずとも、架空の二行と見出しの差だけで説明できる場合があります。
読み込み自体をまだ練習中なら、社会人向けのPython CSV分析の学習手順から、列と行の見方を確認できます。本稿は、分析前に必要な列を正しく受け取る段階に絞った練習です。
区切り文字が違うと、正しい列名も見つからなくなる
見出しがmember_id;amount;noteなのに、カンマ区切りで読み込むとどうなるでしょうか。本稿のH03では、この見出しが一つの列として扱われ、必要なmember_idとamountが見つかりません。名前を手入力し直す前に、ファイルの区切りを確認する場面です。
同じセミコロン区切りの教材でも、sepをセミコロンと明示したH08は採用できます。H03とH08のデータ内容は同じです。入力の値を変えたから直ったのではなく、読み取り条件を入力の形式に合わせたため、二つの必須列を別々に受け取れます。
CSVという拡張子だけで、カンマ区切りと断定しないでください。入力元の出力設定や仕様書を確認します。タブ区切りのファイルも、表計算ソフトでは似た表として見える場合があります。画面の見え方と、保存されたテキストの区切りは別の確認事項です。
また、引用符で囲まれた項目の中にカンマが含まれることもあります。本稿では標準のcsv.readerを使い、見出しを区切り文字ごとに単純なsplitで割る方法は使いません。名前に区切り文字が含まれる場合の読み取りを、CSVのルールに任せるためです。
自動検出へ任せる設計もありますが、今回は区切りを明示します。複数種類のファイルを扱うなら、出力元ごとの形式を記録して、どの条件で読んだかを残す方が、保留になったファイルを調べやすくなります。試す区切りを増やして偶然通った表を採用しないことが大切です。
区切りが合っているかは、読めた列の数と名前を一緒に見て判断します。予定が三列なのに一列しかない、列名にセミコロンが残っている、という観測結果を手掛かりにします。列数だけが合っても、項目の中のカンマを誤って割っていれば別の表になります。
文字化けが併発している場合は、CSVの文字コードと先頭ゼロを分けて調べる手順も確認してください。本稿のStringIO教材は既にPythonの文字列なので、ファイルの文字コードを判別する検証ではありません。
見出し行の位置と、names・headerの役割を分ける
CSVの最初の行が「研修一覧」で、二行目に列名があるファイルもあります。本稿のH06はこの状態を作り、見出しを一行目とする現在の読み取りでは保留にします。研修一覧という名前の一列から、member_idとamountを探しても見つかりません。
このファイルを扱うなら、データ本体の前に何行の説明があるか、どの行が列名かを確認します。何行か飛ばせば通るという理由だけで、skiprowsを増やすことはしません。先頭の説明が可変なら、固定行数の設定が次のファイルで誤る可能性があります。
本稿の採用コードは、見出しが最初のCSVレコードにある形式だけを対象にしています。H06を自動修正しないのは、その対象範囲を明確にするためです。入力元の仕様で二行目が見出しと確認できたら、別の読み取り条件と期待値を用意して検証します。
namesは、採用する列名を指定するための設定です。既に見出しがあるファイルで名前を置き換えるときは、header=0を明示します。本稿は元の見出しを読み取って確認した後、その全列分の名前を修正して渡します。欲しい二列だけの名前を、三列の見出しへ割り当てる方法は使いません。
列名を与えたつもりが、元の見出しまでデータ行として残っていたら、件数や値の型にも影響します。IDの先頭がmember_idになっていないか、金額にamountという文字列が入っていないかなど、採用後にも見出しとデータが混ざっていないことを確かめます。
複数段の見出しを持つ表は、本稿の一段の見出しと同じ処理にしません。表の段数と各段の意味が異なるためです。教材のコードをコピーするときは、一行目を列名にする形式か、説明行や二段見出しがないかを先に確認してください。
| 見えた状態 | 最初の確認 | この教材での扱い |
|---|---|---|
| amountの前後に空白 | reprで元の列名を確認 | 修正前後を残し、衝突がなければ続行 |
| 列名にセミコロンが残る | ファイルの区切りとsep | カンマ設定のH03は保留、明示したH08は採用 |
| 列名が研修一覧だけ | 説明行と見出しの位置 | H06は対象外として保留 |
| amount自体がない | 入力元に必要な項目があるか | H04は保留。0円列を作らない |
stripとNFKCを使う前に、変えてよい文字を決める
空白を直す処理と、全角文字などを正規化する処理は別です。stripは文字列の両端の空白を除きます。一方、NFKCは互換性を考慮したUnicode正規化です。本稿では列名だけにNFKCとstripを順に適用する、という教材上の方針を決めています。
この方針なら「 amount 」はamountへ、「 amount 」もamountへ変わります。実際の入力に対して同じ変更が適切かは、列の命名規則で判断します。見た目の違いを区別する必要がある管理番号や、本文の固有名詞まで、同じ処理を一括でかけないでください。
変更対象を列名に限定するため、会員IDの0012や備考の文章は正規化関数へ渡しません。列名を揃える作業と、データ値を掃除する作業が混ざると、何を変更したために結果が変わったのか追いにくくなります。今回は名前の対応表を先に作ります。
skipinitialspaceも、すべての空白を取り除く設定と考えないでください。公式の説明は区切りの後の空白を飛ばすものです。参照実行では、member_id, amountの末尾に全角空白を置いた見出しは、その末尾空白が残りました。前後の空白を確認する作業は別に必要です。
列の途中の空白を削る処理も、本稿には含めません。例えば「支払 金額」という正式な列名と「支払金額」という列を同じにしてよいかは、入力の約束次第です。すべてのスペースを消す短い処理より、変更理由を説明できる対応表を優先してください。
見えない文字が残る場合、stripを繰り返すだけでは解決しないことがあります。どのコードポイントが含まれるかを調べ、入力元の仕様を確認してから対応を決めます。本稿の8パターンは一般的な空白と全角英字を扱い、すべての不可視文字を修復する道具ではありません。
列名を揃えた後の衝突を、usecolsより先に止める
修正前に別名だった二列が、修正後に同じamountになることがあります。本稿のH05はamountと「 amount 」を並べた例です。どちらを使うか決めずに名前だけ揃えると、必要な金額がどの列にあるのか分からなくなります。
H05は列名の衝突として保留します。値が100と200だから、合計して300にするわけではありません。二列が税込と税抜なのか、予定と実績なのか、単純な重複なのかは、この見出しだけでは確認できないためです。列を落とす前に入力元へ戻る理由を残します。
元から二つのamountがあるH07も保留します。pandasは重複した見出しをamountとamount.1のように区別して読む場合があります。本稿の参照実行でもその結果になりました。suffix付きになったことは、二列の意味が確認できたこととは異なります。
そのため教材では、pandasが重複名を区別する前に、csv.readerで生の見出しを取り出します。修正後のリストと、その集合の長さが異なるなら重複があると判定します。amount.1を見つけて後から消す方法では、元の見出しの重複を見失いかねません。
衝突した列名だけでなく、元の位置も記録すると入力元へ質問しやすくなります。第二列と第三列が同名だった、と分かれば、見出しを書き直すべきなのか、どちらかが不要なのかを相談できます。本稿の対応表は順番を持つため、元の並びも追えます。
同じ考え方は、Excelの複数シートを結合するときにも役立ちます。ただし、シート名や元の行を残す追加の確認が必要です。その用途なら、複数シートを列名と元シートで確認する練習へ進んでください。
必須列を確認し、読み込み後の表を8パターンで検収する
usecolsのlambdaで、必須列が黙って消える例を確かめる
存在する列だけを選ぶlambdaを使えば、欠けた列で止まらない場合があります。便利に見えても、amountが必要な仕事でamountが消えていたら、そのまま集計には進めません。処理が止まらないことと、要求された二列が揃っていることを分けて確認します。
本稿ではmember_idとnoteだけのCSVを、usecols=lambda c: c in expectedで読みました。エラーは出ず、member_idだけの表になりました。amountのない状態を、検証済みの入力として採用できるわけではありません。必須列は読み込み前に別途確認します。
列が任意なら、欠けた場合の扱いを設計できます。しかし、本稿の金額は必須項目です。任意と必須を区別せず、欠けた列をNaNや0で補うことはしません。必要な列のリストを、読み取り条件とは別に書いておくと、何が欠けたら止めるかを説明できます。
dtypeへ列名を書いたことも、列の存在検査とは分けます。本稿ではmember_idを文字列として読む設定を使いますが、この設定の目的はIDの型です。必須列が揃うかは見出しとの照合で確認し、型の指定だけへ任せません。
エラー文に出る列名の順番を、そのまま列の優先順位と考える必要もありません。missingのリストをexpectedの順に作れば、教材ではmember_id、amountの順に不足を報告できます。何を採用したいかが、結果の表示でも一貫します。
CSVの欠損・重複を残して調べる練習は、列を受け取った後の行の品質を扱います。本稿で必須列を確保してから、空欄やID重複を調べると、列の欠落と行の欠損を混同せずに進められます。
元の列名を残し、採用条件を明示したコードを実行する
次のコードは、自分で作った短い文字列だけを読みます。外部のファイル、業務データ、APIは使いません。まずcleanを実行し、二列・二行、IDが0012と0013、金額が100と0であることを確認します。元の三列目noteは、今回の出力には選びません。
関数は、一段の見出しが最初のCSVレコードにある形式を対象にしています。区切りを明示し、名前の衝突と必須列の欠落があればValueErrorで保留します。成功した場合に、選択した表と、元の列名から採用名への対応表を返します。
from io import StringIO
import csv
import unicodedata
import pandas as pd
expected = ["member_id", "amount"]
def read_checked(text, sep=","):
raw = next(csv.reader(StringIO(text), delimiter=sep))
names = [unicodedata.normalize("NFKC", s).strip() for s in raw]
if len(names) != len(set(names)):
raise ValueError("列名の衝突")
missing = [s for s in expected if s not in names]
if missing:
raise ValueError("必須列なし: " + ",".join(missing))
df = pd.read_csv(
StringIO(text), sep=sep, header=0, names=names,
usecols=expected, dtype={"member_id": "string"}
)
return df.loc[:, expected], list(zip(raw, names))
clean = "member_id,amount,note\n0012,100,入門\n0013,0,継続\n"
df, header_map = read_checked(clean)
print(df.to_dict("records"))
print(header_map)
assert list(df.columns) == expected
assert df["member_id"].tolist() == ["0012", "0013"]
assert df["amount"].tolist() == [100, 0]
header_mapには、元の名前と変更後の名前が同じものも残ります。変更した列だけを保存するより、全体の並びを追いやすくするためです。入力に合わせて関数を変えるなら、対応表と期待値を先に書き換え、その後に処理結果を照合してください。
この関数は、空ファイル、壊れた引用符、多段見出し、途中で変わる区切りを自動修復しません。そうした入力が必要なら、別の確認と例外処理を設計します。本稿の採用条件を満たした後でも、金額の意味や、全行の品質を確認したわけではありません。
Pythonの練習では、関数が返す二つの値も説明してみてください。一つは後工程へ渡す表、もう一つは見出しの変更履歴です。表だけを受け取って成功とするより、何を直したかを自分の言葉で確認する練習になります。
8パターンの採用・保留を、理由と期待値で比べる
次の8入力は、列名や読み取り条件の問題を一つずつ変えた教材です。実在のデータの成功率を測った数値ではありません。各ケースで何を確かめるかを決め、採用してよいケースだけ二行のIDと金額を照合します。
cases = [
("H01", clean, ",", True),
("H02", " member_id , amount ,note\n0012,100,入門\n0013,0,継続\n", ",", True),
("H03", clean.replace(",", ";"), ",", False),
("H04", "member_id,note\n0012,入門\n", ",", False),
("H05", "member_id,amount, amount \n0012,100,200\n", ",", False),
("H06", "研修一覧\n" + clean, ",", False),
("H07", "member_id,amount,amount\n0012,100,200\n", ",", False),
("H08", clean.replace(",", ";"), ";", True),
]
for ident, text, sep, should_pass in cases:
try:
result, changes = read_checked(text, sep)
assert should_pass
assert result["member_id"].tolist() == ["0012", "0013"]
assert result["amount"].tolist() == [100, 0]
print(ident, "採用", changes)
except ValueError as error:
assert not should_pass
print(ident, "保留", str(error))
| 入力 | 結果 | 判断の理由 |
|---|---|---|
| H01 通常の三列 | 採用 | 必須二列があり、IDと金額が一致 |
| H02 名前の前後に空白 | 採用 | 名前の修正後も衝突せず、二行の値が一致 |
| H03 ;区切りを,で読む | 保留 | 二つの必須列を読めていない |
| H04 amountがない | 保留 | 必須列amountが欠けている |
| H05 正規化で同名になる | 保留 | amount二列の意味を区別できない |
| H06 最初に説明行 | 保留 | 見出し位置が対象形式と違う |
| H07 元から同名の二列 | 保留 | 生の見出しで重複を検出 |
| H08 ;区切りを明示 | 採用 | 区切りと列名が合い、二行の値が一致 |
採用はH01・H02・H08の3パターンです。保留5パターンは、同じ対処をすればよいわけではありません。H03は読み取り条件、H04は入力の不足、H05とH07は列の意味、H06は見出し位置の確認へ戻ります。保留の理由が次の作業を示します。
H02が通ることだけでは、正規化の関数が安全だと確認できません。H05を止める負例まで実行することで、「名前が揃った後に同名になるケース」を取り逃さないか確認できます。正常な入力だけを試すより、変更の境界が見えます。
結果を記録する際は、採用の件数だけでなく、ケース名と理由を残します。修正して再実行したら、H03のsepを変更した、と分かるようにしてください。元データを変更したのか、読み取り設定を変更したのかを区別できる記録が必要です。
usecolsの指定順と、読み込み後に欲しい列順を揃える
usecolsへmember_id、amountの順で書いても、その順に出力されるとは考えません。公式資料でも、要素の順序がそのまま列順になるものではないと説明されています。欲しい順序があるなら、読み込み後にその順で選び直します。
参照実行では、amount、member_idの順で保存したCSVを読み、usecolsにはmember_id、amountの順で渡しました。読み込み直後の列順はamount、member_idでした。本稿の関数は最後にdf.loc[:, expected]を適用し、ID、金額の順へ揃えます。
列の位置で後工程を作っている場合、この違いを見落とすと、IDと金額の取り違えにつながります。名前で参照する設計でも、出力先の表の順序は読みやすさに関わります。読み込みの選択と、表示・出力の順序をそれぞれ明示してください。
同時に、IDが0012から12へ変わっていないかも確認します。本稿はmember_idをstringで読むため、先頭ゼロを残します。これは列名の修正とは別の条件です。列名が正しくても、IDの型が期待と違えば、元の行へ戻る照合が難しくなります。
金額の100と0も、IDと組にして確認します。値の合計が同じでも、別のIDへ金額を割り当てていれば正しい表ではありません。少数の教材では、二行のIDと金額の組をそのまま照合する方が、何が変わったかを追いやすくなります。
実際の業務へ広げる前には、行数、空欄、重複、値の型、元ファイル名などの確認を追加します。名前が揃った後の結合で行が増えるなら、pandasのmergeと行数の検証を参照してください。列名エラーの解決は、入力確認の一段階です。
FAQと、学習を続ける前に残す確認票
保存する確認票は、対象ファイル、必要な二列、元の見出し、採用する見出し、sep、header、採用結果、保留理由を一組にします。これに二行の期待値があれば、別の日に同じ教材を実行したときも、何を確認していたかを思い出せます。
練習を続けるときは、まず見出しだけを一箇所変え、予想した理由で止まるか確認してください。その後にIDや金額を変えます。一度に列名、区切り、見出し位置を変えると、どの条件が結果に影響したか分かりにくくなります。
独学で進めやすい人は、表の列と型を読み、自分で小さい負例を作れる人です。質問先を比較したい人は、元の見出しとエラーの差を説明する段階で止まる人、毎回違う設定を試して理由が残らない人です。講座名だけで判断せず、質問できる範囲や前提知識を確認します。
スクールを探す場合は、目的と経験別のスクール一覧で、Python・データ分析を学ぶ入口を確認できます。この教材のコードを添削してもらえるか、業務の実データを持ち込めるかは、各サービスへ別途確認が必要です。学習の結果や転職を約束するものではありません。
2026年10月14日に確認したPython Winnerの公式講座一覧には、Pythonの基礎・応用と、目的別のデータ分析講座が案内されています。列の読込条件や型を、基礎から順に理解したい人が比較しやすい学習先です。この8パターンの教材の添削が受講内容に含まれるとは確認していません。相談では、元の見出し・期待する二列・保留理由を示し、必要な前提知識、質問範囲、希望する演習、期間、受講総額を確認してください。
一つのCSVの不具合と、Python全体の学び直しでは必要な支援が違います。まずH03とH05を別の理由で説明できるかを確かめ、独学を続けるか、指導を受けるかを考えます。
無料カウンセリング・受講相談への参加と、有料講座への申込みは別です。個人情報や業務ファイルを持ち込まず、架空のCSVと確認票で質問したい内容を整理してください。
CSV列名とusecolsのよくある質問
Q. 列名をstripすれば、usecolsエラーは直りますか?
前後の空白が原因なら改善する場合があります。ただし区切り・見出し位置・必須列の欠落は別の問題です。修正後に同名の列ができていないかも確認してください。
Q. skipinitialspaceは末尾や全角の空白もすべて消しますか?
全空白を消す設定として扱いません。公式は区切りの後の空白を飛ばすものと説明しています。本稿の参照実行では見出し末尾の全角空白が残り、別の確認が必要でした。
Q. 存在する列だけをlambdaで選べばよいですか?
任意の列を選ぶ用途と、必須列を受け取る用途を分けます。本稿ではamountがない入力でもlambda選択はエラーにならず、member_idだけになりました。必須列の存在を先に照合します。
Q. namesを使うときにheader=0が必要ですか?
本稿のように既存の一段の見出しを置き換える教材では、header=0を明示します。見出しのないファイルや説明行のあるファイルは異なる条件なので、元の構造を確認してから設定してください。
Q. usecolsへ書いた順に列を並べられますか?
指定リストの順序だけに任せず、読み込み後にdf.loc[:, expected]のように必要な順で選びます。列の順序と同時に、IDの先頭ゼロや金額との組も照合してください。