「読み込んでから直す」じゃなく「読み込む瞬間に直す」
Excelの生データって、だいたいこういう“ちょっとイヤな感じ”が混ざっています。
- 前後にスペースが付いた文字列(
" A001 ") - 全角・半角が混ざったコード
- 数字っぽいけど文字列として入っている値
- 「はい/いいえ」を
Y/Nにしたい、などの表記ゆれ
普通は「読み込んだあとに df["col"].str.strip() で直す」ことが多いですが、converters={'col': 関数} を使うと、読み込みの瞬間に変換してから DataFrame に入れることができます。
converters={'col': lambda x: x.strip()} は、
「col 列に入ってくる値は、全部 strip() してから保存してね」という指定です。
基本形:converters={‘col’: lambda x: x.strip()} の挙動
最小コードとイメージ
import pandas as pd
df = pd.read_excel(
"data.xlsx",
converters={
"code": lambda x: x.strip()
}
)
print(df["code"].head())
Pythonここで起きていることは、こうです。
- Excelから1セルずつ値を読む
code列に入る値は、いったんlambda x: x.strip()に通す- その戻り値を DataFrame に入れる
つまり、「生の値 → 変換関数 → DataFrame」という流れになります。strip() は文字列の前後の空白を削る関数なので、" A001 " → "A001" のように、きれいな形で入ってきます。
converters と dtype の違いをはっきりさせる
dtype は「型を決める」、converters は「値を加工する」
dtype={"col": str} は、「この列は文字列型として扱ってね」という“型の指定”です。
一方、converters={"col": 関数} は、「この列の値はこう変換してから入れてね」という“変換ロジック”です。
例えば、こういう組み合わせもできます。
df = pd.read_excel(
"data.xlsx",
dtype={"code": "string"},
converters={"code": lambda x: x.strip()}
)
Pythonこの場合、
- まずセルの値が
lambda x: x.strip()に通される - その結果が「文字列型」として DataFrame に入る
というイメージです。
「型を揃えるだけなら dtype」「中身をいじりたいなら converters」と覚えておくと整理しやすいです。
よくある実務パターンで考える
パターン1:前後のスペースを全部消したい(ID・コード系)
Excelの「顧客ID」「商品コード」などに、なぜかスペースが混ざっているパターン。
import pandas as pd
df = pd.read_excel(
"customers.xlsx",
converters={
"CustomerID": lambda x: str(x).strip()
}
)
print(df["CustomerID"].head())
Pythonここでは、str(x).strip() としているのがポイントです。
空欄や数値が混ざっていても、とりあえず文字列にしてから strip() することで、" 001 " → "001" のようにきれいに揃えられます。
パターン2:「はい/いいえ」を True/False に変換したい
Excel側では「はい」「いいえ」と書いてあるけれど、
Python側ではブール値(True/False)で扱いたい場合。
import pandas as pd
def yes_no_to_bool(x):
if x in ("はい", "YES", "Yes", "yes"):
return True
if x in ("いいえ", "NO", "No", "no"):
return False
return None # よくわからないものは欠損扱い
df = pd.read_excel(
"survey.xlsx",
converters={
"同意": yes_no_to_bool
}
)
print(df["同意"].head())
print(df["同意"].dtype)
Pythonこうしておくと、読み込んだ瞬間から True/False/None の列として扱えます。
後から replace するより、入口で変換してしまった方がスッキリです。
パターン3:数字っぽい文字列を、きれいな数値にしておきたい
「1,234」「 500 」のような文字列を、ちゃんと数値にしておきたい場合。
import pandas as pd
def to_int_or_nan(x):
if x is None:
return None
s = str(x).replace(",", "").strip()
return int(s) if s.isdigit() else None
df = pd.read_excel(
"sales.xlsx",
converters={
"数量": to_int_or_nan
}
)
print(df["数量"].head())
print(df["数量"].dtype)
Pythonここでは、"1,234" → "1234" → 1234 のように変換しています。converters を使うと、「Excelの変な書き方」を読み込み時に正規化できるのが強みです。
converters を複数列に使う
複数列を同時に指定する
import pandas as pd
df = pd.read_excel(
"sales.xlsx",
converters={
"CustomerID": lambda x: str(x).strip(),
"ProductCode": lambda x: str(x).strip(),
"数量": lambda x: int(str(x).strip()) if str(x).strip().isdigit() else None
}
)
print(df.head())
Python列ごとに違う変換ロジックを持たせられるので、
「IDはスペース除去」「数量は数値化」「フラグは True/False」など、
列の性質に合わせた前処理を、読み込み時に埋め込めます。
converters と他の引数の組み合わせ
usecols と一緒に使う
import pandas as pd
df = pd.read_excel(
"sales.xlsx",
usecols=["日付", "顧客ID", "数量"],
converters={
"顧客ID": lambda x: str(x).strip(),
"数量": lambda x: int(str(x).strip()) if str(x).strip().isdigit() else None
}
)
print(df.head())
Pythonusecols で列を絞りつつ、残した列にだけ変換関数を適用する、という形です。
parse_dates と一緒に使う
日付列は parse_dates に任せることが多いですが、
「変なフォーマットが混ざっている」場合は、あえて converters で自分で処理することもあります。
import pandas as pd
from datetime import datetime
def parse_weird_date(x):
try:
return pd.to_datetime(x, errors="coerce")
except Exception:
return None
df = pd.read_excel(
"weird_dates.xlsx",
converters={
"日付": parse_weird_date
}
)
print(df["日付"].head())
Pythonparse_dates でうまくいかないときの“最後の手段”として、
自作パーサーを converters に渡す、というイメージです。
実践テンプレート
テンプレ1:顧客IDのスペースを削り、数量を数値化してから集計
import pandas as pd
def clean_id(x):
return str(x).strip()
def to_int_or_nan(x):
s = str(x).replace(",", "").strip()
return int(s) if s.isdigit() else None
df = pd.read_excel(
"sales.xlsx",
usecols=["顧客ID", "数量"],
converters={
"顧客ID": clean_id,
"数量": to_int_or_nan
}
)
summary = df.groupby("顧客ID", as_index=False)["数量"].sum()
print(summary.head())
Python読み込み時に「IDのスペース除去」と「数量の数値化」を済ませているので、
後続の集計コードがとても素直になります。
テンプレ2:アンケートの「はい/いいえ」を True/False にしてから集計
import pandas as pd
def yes_no_to_bool(x):
if x in ("はい", "YES", "Yes", "yes"):
return True
if x in ("いいえ", "NO", "No", "no"):
return False
return None
df = pd.read_excel(
"survey.xlsx",
converters={
"同意": yes_no_to_bool
}
)
print(df["同意"].value_counts(dropna=False))
Pythonここでは、読み込み時に「文字列 → ブール値」への変換を済ませているので、value_counts でそのまま集計できます。
つまずきやすいポイントと注意点
converters の関数には「生の値」がそのまま来る
converters に渡される x は、Excelから読んだ“そのままの値”です。
空欄なら nan(float)、数値なら float や int、文字列なら str が来ます。
そのため、x.strip() とだけ書くと、x が文字列でないときにエラーになります。
安全に書くなら、まず文字列に変換してから処理するのがおすすめです。
lambda x: str(x).strip()
Pythonこうしておけば、nan や数値が混ざっていても、とりあえず文字列として扱えます。
変換関数の中で例外が出ると、そのセルで止まる
converters の関数内でエラーが出ると、そのセルの読み込みで例外が発生します。
実務では、できるだけ try/except や条件分岐で「変換できないものは None にする」など、
壊れにくい関数を書くのが大事です。
小さな練習問題
練習1:customers.xlsx の「CustomerID」列の前後スペースを削って読み込む
条件は次の通りです。
converters={"CustomerID": lambda x: str(x).strip()}を使う- 読み込み後に
df["CustomerID"].head()を表示して、スペースが消えているか確認する
練習2:survey.xlsx の「同意」列を True/False に変換して読み込み、集計する
条件は次の通りです。
- 「はい/YES/Yes/yes」を True、「いいえ/NO/No/no」を False、それ以外は None にする関数を書く
- それを
convertersに渡して読み込む value_counts(dropna=False)で分布を確認する
最後に
converters={'col': lambda x: x.strip()} は、
「この列は、こういうルールで“きれいにしてから”受け取りたい」という意思表示です。
これをうまく使うと、
読み込み後の前処理コードが減る
Excel側の“ゆるい書き方”を、Python側で一気に正規化できる
集計・結合・分析の前提が安定する
という、かなり大きなメリットが手に入ります。
あなたのExcelに、「毎回読み込んだあとに同じクリーニングを書いている列」があるなら、
その処理を converters に移してみてください。
入口を整えると、その先のコードが一気に軽くなります。

