Pythonで文字列を数値に変換する方法!

python
PythonでCSVやAPI、画面からの入力を扱っていると、**「数字に見えるのに数値として使えない」**という場面によく出会います。

そんなときに困ることは、

・int()やfloat()でエラーが出て先に進めない
・”1,234″のようにカンマが入った金額を変換できない
・文字列か数値かの判定をどう書けばいいか分からない

ですね。

エラー文を読んでも「invalid literal for int()」としか出ないので、原因が分からず止まってしまう方も多いです。

そこで今回は、**文字列を数値に変換する基本から、エラーになる原因の見分け方、実務での対処法**までをまとめます。

・int()とfloat()の基本
・エラーになる6つの原因と対処法
・isdigit()が使えない理由
・金額を扱うときのDecimal
・実務パターン(CSVの合計)

今回は、これらについてまとめます!

POINT
・整数は int()、小数は float() を使う(迷ったら float() で確認)
・**全角数字「123」は int() でそのまま変換できる**(ただし全角の小数点「.」はエラー)
・変換できないときは ValueError、値が None のときは TypeError になる
・**isdigit() は判定に使えない**(True でも失敗する/False でも成功するケースがある)
・金額の計算は float ではなく **Decimal** を使う

完成イメージ

基本の変換と、つまずきやすいポイントをまとめた実行結果です。

Pythonで文字列を数値に変換した実行結果
「123」はそのまま、「1,234」はカンマを取ってから、というように**前処理を挟むのがポイント**です。

基本:int() と float() を使う

文字列を数値にするには、整数なら int()、小数なら float() を使います。

s = "123"
n = int(s)
print(n)          # 123
print(type(n))    # <class 'int'>

f = float("123.45")
print(f)          # 123.45
print(type(f))    # <class 'float'>

文字列を数値にすると、足し算や比較ができるようになります。

a = "10"
b = "20"

print(a + b)              # 1020(文字列の連結になってしまう)
print(int(a) + int(b))    # 30(数値の足し算)

「なぜか 1020 になった」というのは、変換を忘れたときに起きる定番のミスですね。

そのまま変換できる書き方(早見表)

文字列 int() float() ポイント
“123” 123 123.0 ふつうの数字
” 123 “ 123 123.0 前後の空白は自動で無視される
“+5” / “-5” 5 / -5 5.0 / -5.0 符号もOK
“1_000” 1000 1000.0 アンダースコア区切りもOK
“000123” 123 123.0 先頭の0は無視
“1e3” エラー 1000.0 指数表記はfloatのみ
“.5” / “5.” エラー 0.5 / 5.0 小数点の前後は省略可
“nan” / “inf” エラー nan / inf 特殊な値もfloatなら通る

基数を指定すると16進数・2進数も変換できる

第2引数に基数を渡すと、10進数以外も変換できます。

print(int("1A", 16))      # 26(16進数)
print(int("0x1A", 16))    # 26(0x が付いていてもOK)
print(int("1010", 2))     # 10(2進数)
print(int("77", 8))       # 63(8進数)

エラーになる6つの原因と対処法

まずは全体像です。

int()がエラーになる原因と対処

① 数字以外の文字が入っている

ValueError: invalid literal for int() with base 10: ‘abc’

「base 10」は「10進数として読めなかった」という意味です。

② 小数点が入っているのに int() を使った

print(int("1.0"))          # エラー
print(int(float("1.0")))   # 1(一度floatにしてからintへ)

「1.0」は整数に見えますが、int() は小数点を受け付けません。int(float(s)) の順で変換しましょう。

③ カンマや通貨記号が入っている

CSVやExcelから持ってきた金額は、この形になっていることが多いです。

s = "¥1,234"

s = s.replace("¥", "").replace(",", "")   # 記号とカンマを取る
print(int(s))                             # 1234

④ 全角数字・全角記号が混じっている

ここは誤解されやすいポイントです。全角数字「123」は int() でそのまま変換できます。

print(int("123"))          # 123(全角でも通る)
print(float("123"))        # 123.0
print(float("123.45"))   # 123.45(全角数字+半角の小数点)
print(float("123.45"))  # エラー(全角の小数点「.」)

数字は変換できても、全角の小数点「.」や全角カンマ「,」はエラーになります。

全角を半角にそろえたいときは、NFKC正規化が便利です。

import unicodedata

s = unicodedata.normalize("NFKC", "123.45")
print(s)            # 123.45(全角が半角になる)
print(float(s))     # 123.45

⑤ 空文字や空白だけ

print(int(""))       # エラー
print(int("   "))    # エラー
print(float(""))     # エラー

CSVの空欄はこれに当たります。strip() で空白を取ってから、空かどうかを判定しましょう。

⑥ 値が None(TypeError になる)

TypeError: int() argument must be a string, a bytes-like object or a real number, not ‘NoneType’

JSONやデータベースから来た値が None のときに起きます。ValueError ではなく TypeError なので、exceptの書き方に注意してください。

try:
    n = int(value)
except (ValueError, TypeError):     # 両方まとめて受ける
    n = 0
POINT
・エラーの種類で原因が分かる:ValueError=文字列の中身の問題/TypeError=そもそも文字列ではない
・「base 10」と出たら10進数として読めない文字が混じっている
・数値の前処理は「記号を取る→全角を半角にする→空白を取る」の順で

判定に使えるメソッドはある?(isdigit() は使えません)

「変換できるかどうかを先に判定したい」と考えて isdigit() を使う方が多いのですが、**これは危険です。**

isdigit()が判定に使えない理由
判定 isdigit() の結果 int() の結果 判定と一致する?
“123”.isdigit() True 成功 一致
“-5”.isdigit() False 成功 ズレる
” 12 “.isdigit() False 成功 ズレる
“²”.isdigit() True 失敗 ズレる
“½”.isdigit() True 失敗 ズレる
“1.5”.isdigit() False 失敗 一致

isdigit() が False でも変換できるものがあり、True でも失敗するものがあります。

理由は、isdigit() が「文字が数字かどうか」を見ているだけで、符号・空白・小数点・変換可否を見ていないからです。

3つのメソッドの違いは次のとおりです。

メソッド 判定するもの “²” “½” “一” int()の可否と一致する?
isdecimal() 10進数の数字 False False False いちばん近い
isdigit() 数字(上付き含む) True False False ズレる
isnumeric() 数値(漢数字含む) True True True ズレる

結論:判定せずに、try/except で書くのが正解です。

def to_int(s, default=0):
    """文字列を整数にする。変換できなければ default を返す。"""
    if s is None:
        return default                      # None は先に弾く
    try:
        return int(str(s).replace(",", "").strip())
    except ValueError:
        return default

この形なら、判定のズレを気にせず安全に変換できます。

金額を扱うときは Decimal を使う

小数を float で計算すると、**わずかな誤差**が残ります。

floatの誤差とDecimal
print(0.1 + 0.2)          # 0.30000000000000004

from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2"))    # 0.3

金額の合計が1円ずれる原因になるので、お金の計算はDecimalを使いましょう。

Decimal は「文字列」から作るのがポイントです。Decimal(0.1) と書くと、誤差を持ったまま取り込まれてしまいます。

from decimal import Decimal

print(Decimal(0.1))       # 0.1000000000000000055511151231257827021181583404541015625
print(Decimal("0.1"))     # 0.1

# 四捨五入も round() ではなく quantize を使う
print(round(1.005, 2))                          # 1.0(誤差の影響を受ける)
print(Decimal("1.005").quantize(Decimal("0.01")))   # 1.00

変換の流れ(図で確認)

文字列から数値への変換フロー
「変換してみる → ダメなら前処理」の順で考えると整理しやすいです。

実務パターン:CSVの金額を合計する

実務でいちばんよくある形をまとめました。

CSVの金額を合計する実務パターン
import csv
from decimal import Decimal, InvalidOperation

total = Decimal("0")
skipped = []

with open("uriage.csv", encoding="utf-8") as f:
    for row in csv.DictReader(f):
        raw = (row["金額"] or "").replace(",", "").strip()
        try:
            total += Decimal(raw)
        except InvalidOperation:
            skipped.append(row["商品"])      # どの行がダメかを記録

print(f"合計: {total:,} 円")
print(f"スキップ: {skipped}")
合計: 184,780 円
スキップ: ['合計なし']

ポイントは例外を握りつぶさないことです。どの行が変換できなかったかを記録しておくと、あとから確認できます。

よくある間違い

間違い 起きること 正しい書き方
int(s) をいきなり使う ValueErrorで止まる try/except か前処理を入れる
s.isdigit() で判定する 誤判定する try/except で判定する
except で全部受ける バグを見逃す ValueError, TypeError を指定する
金額を float で計算する 1円単位でずれる Decimal を使う
Decimal(0.1) と書く 誤差を引き継ぐ Decimal(“0.1”) と文字列で渡す
int(float(s)) を忘れる “1.0” でエラー 小数点があるなら int(float(s))

エク短流:ExcelのデータをPythonで読むときの注意

ExcelやCSVから取り込んだ値は、次のような状態になっていることがあります。

状態 例 対処
金額にカンマが入っている 1,234 replace(“,”, “”)
全角で入力されている 1234 NFKC正規化
単位が付いている 1,234円 数字以外を除去
空欄がある (空) strip() と空チェック
文字列として保存されている ‘123 頭のシングルクォートを除去
作業 Excel(VBA) Python
整数に変換 CLng(“123”) int(“123”)
小数に変換 CDbl(“123.45”) float(“123.45”)
変換できないとき IsNumeric() で判定 try/except で判定
全角数字 StrConv(s, vbNarrow) unicodedata.normalize(“NFKC”, s)

VBAの IsNumeric() は判定用に使えますが、Pythonの isdigit() は判定に使えないという違いがあります。

「判定してから変換」ではなく、「変換してみて、失敗したら対処」と考えるのがPython流です。

タカヒロ

タカヒロ
エラーが出る文字列は、たいてい「見た目は数字」です。記号・全角・空白の3つを疑うと、ほぼ解決しますよ。

さいごに

今回は、Pythonで文字列を数値に変換する方法をまとめました。

1. 整数は int()、小数は float() で変換する
2. エラーは「ValueError=中身の問題」「TypeError=型の問題」で切り分ける
3. カンマ・通貨記号・全角は前処理で取り除く
4. isdigit() での判定はやめて、try/except で書く
5. 金額の計算は Decimal を使う

変換できない文字列に出会ったときは、まずエラー文の種類を見てください。それだけで原因の見当がつきます。

ValueError と TypeError の違いさえ押さえておけば、切り分けはカンタンですね。

文字列から数値への変換は、データ処理のいちばん最初の関門です。ここでつまずかなくなると、CSVもAPIもぐっと扱いやすくなりますね。

「1,234」のような値が出てきたときは、この手順をぜひ試してみてください。

最後までお読みいただきありがとうございました。



この記事の関連キーワード

こちらの記事の関連キーワード一覧です。クリックするとキーワードに関連する記事一覧が閲覧できます。






コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

CAPTCHA ImageChange Image