K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

read_csvで空白や桁ズレが原因で数値変換できない

01.9.4

read_csvで空白や桁ズレが原因で数値変換できない

最終更新 2025-11-04 読了時間 3 分
まとめ
ValueError: could not convert string to float: ' 1,234 ' は、数値のつもりの列に半角スペースと桁区切りのカンマが入っていて、float() が文字列として解釈できなかった、という報告です。区切り文字の直後の半角スペースだけなら skipinitialspace=True で読み込み時に消え、カンマや全角スペース(\u3000)が混ざるなら dtype=str で一度文字列として読み、str.replace(r"[\s,]", "", regex=True) で掃除してから astype("Int64") にします。読み込み段階で直したいなら converters={"amount": clean_amount} に自前の関数を渡し、帳票が固定長なら read_fwf に切り替えます。このページでは sales.csv の amount 列を例に、4 つの直し方と最後の受け皿 pd.to_numeric(errors="coerce") を示します。

直感 #

read_csv は各列の値が全部数値に見えるときだけ int64 や float64 に変換し、1 つでも変換できない値があれば列全体を object(文字列)のまま残します。' 1,234 ' は人間には 1234 ですが、Python の float() にとっては空白もカンマも「数字ではない文字」なので失敗します。つまりエラーの ' 1,234 ' の部分を見れば、消すべき文字(前後の空白、カンマ)が特定でき、その文字を読み込み時か読み込み後に取り除くのが対処の全体像です。

pandas.read_csv() で読み込んだ列を数値に変換しようとすると

ValueError: could not convert string to float: ' 1,234 '

や

ValueError: invalid literal for int() with base 10: '001 234'

といったエラーで処理が止まることがあります。前者は float() が、後者は int() が失敗したときのメッセージで、引用符の中に表示された文字列が「変換できなかった実際の値」です。どちらも 列の中に余計な空白・全角スペース・桁ズレが含まれている ことが原因で、' 1,234 ' なら前後の半角スペースとカンマ、'001 234' なら桁の間の空白が犯人です。


解決法 1: 読み込み時に空白を自動でトリムする #

1, 234, 567 のように区切り文字の直後にだけ空白があるファイルは、skipinitialspace=True を付けると読み込みの段階でその空白が消え、数値列として認識されます。

1
2
3
import pandas as pd

df = pd.read_csv("sales.csv", skipinitialspace=True)

解決法 2: 文字列を明示的にクレンジングしてから数値化する #

dtype=str で列を一度すべて文字列として読み込み、正規表現で空白とカンマを取り除いてから、欠損にも対応できる Int64 に変換します。桁ズレやタブが混ざる帳票でも、消したい文字を正規表現に足すだけで対応できます。

1
2
3
4
5
6
7
df = pd.read_csv("sales.csv", dtype=str)  # いったん文字列で統一

df["amount"] = (
    df["amount"]
    .str.replace(r"[\\s,]", "", regex=True)  # 空白とカンマを除去
    .astype("Int64")                         # 欠損にも対応できる pandas の Int64
)

解決法 3: 固定長レイアウトなら read_fwf を使う #

帳票によっては CSV ではなく 固定長(Fixed Width)のテキストが渡されることがあります。'001 234' のように桁の間に空白が入って見えるのは、区切り文字がなく「8 桁・12 桁・10 桁」のように位置で列が決まっているファイルを read_csv で読んだときの典型です。この場合は read_fwf に切り替えると列境界を幅で指定できます。

1
2
3
4
5
df = pd.read_fwf(
    "report.txt",
    widths=[8, 12, 10],
    names=["customer_id", "amount", "created_at"],
)

解決法 4: 列単位でクリーニング関数を適用する #

converters に関数を渡すと、read_csv が値を列に入れる前にその関数を通してくれます。全角スペース(\u3000)や制御文字のように正規表現で書きにくい掃除も、Python の関数として素直に書けます。

1
2
3
4
5
def clean_amount(value: str) -> float | None:
    value = value.replace("\u3000", "").replace(",", "").strip()  # 全角スペース対策
    return float(value) if value else None

df = pd.read_csv("sales.csv", converters={"amount": clean_amount})

使いどころと落とし穴 #

エラーメッセージの引用符の中を見て、半角スペースだけなら skipinitialspace、カンマや全角スペースも混ざるなら str.replace か converters、桁が縦に揃っている固定長なら read_fwf と選びます。どの方法でも最後に df.dtypes で amount が数値型になったことを確認し、object のまま残るなら変換できない値がまだあります。原因を 1 つずつ潰す時間がないときは、変換できない値を NaN に落として先へ進む pd.to_numeric(errors="coerce") を受け皿にし、df["amount"].isna().sum() で何件落としたかを把握します。

1
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")

参考 #

str.replace や str.strip などの文字列メソッドは Working with text data — pandas user guide に、固定長ファイルを読む widths・colspecs の指定は pandas.read_fwf — pandas documentation にまとまっています。