Pythonを使用してデータ分析やテキスト処理を行う際、文字列の中から特定の数字だけを抽出したいケースは非常に多く存在します。
例えば、ログファイルからエラーコードを取得したり、Webスクレイピングで取得した文章から価格情報のみを取り出したりする場合です。
このような文字列操作を効率化するために欠かせないのが、正規表現(Regular Expression)という仕組みです。
Pythonでは標準ライブラリのreモジュールを利用することで、複雑な条件に合致する数字を簡単に、かつ高速に抽出することが可能です。
本記事では、正規表現の基本から、実務で役立つ応用的な抽出テクニックまでを詳しく解説します。
Pythonの正規表現(reモジュール)とは
Pythonで正規表現を利用するためには、まずreモジュールをインポートする必要があります。
このモジュールは標準ライブラリとして提供されているため、追加のインストール作業なしですぐに利用を開始できます。
正規表現は特定の文字列パターンを数式のように表現する手法であり、特定のルールに基づいた検索や置換を可能にします。
プログラミング言語によって正規表現の細かな仕様は異なりますが、Pythonのreモジュールは非常に汎用的で強力な機能を備えています。
基本的な使い方をマスターするだけで、数百行におよぶテキスト処理コードをわずか数行に短縮できることも珍しくありません。
数字抽出のための基本パターン
数字を抽出するための最も基本的な正規表現パターンは、\dです。
この\dは「任意の数字1文字」を意味し、[0-9]と記述するのと同等の効果を持ちます。
ただし、Pythonにおいて\dはデフォルトでUnicodeの数字(全角数字など)にもマッチする場合がある点に注意が必要です。
以下に、数字抽出でよく使用されるメタ文字をまとめました。
| メタ文字 | 意味 |
|---|---|
\d | 任意の数字(0から9)にマッチします。 |
\D | 数字以外の文字にマッチします。 |
[0-9] | 0から9のいずれか1文字にマッチします。 |
+ | 直前の文字が1回以上繰り返される場合にマッチします。 |
* | 直前の文字が0回以上繰り返される場合にマッチします。 |
これらのパターンを組み合わせることで、単一の数字だけでなく「123」や「2026」といった連続した数値を取得できるようになります。
reモジュールの主要な関数とその使い分け
数字を抽出する際には、目的に応じて適切な関数を選択することが重要です。
re.search():最初に見つかった数字を取得する
文字列全体を走査し、最初に出現した数字のみを取得したい場合はre.search()を使用します。
この関数は、マッチした箇所の詳細情報を含む「マッチオブジェクト」を返します。
import re
text = "商品の価格は1280円で、送料は500円です。"
# 最初に見つかる数字の連続を検索
match = re.search(r'\d+', text)
if match:
# group()メソッドでマッチした文字列を取り出す
print(match.group())
1280
もし文字列内に該当するパターンが存在しない場合、re.search()はNoneを返します。
re.findall():すべての数字をリスト形式で取得する
文字列内に含まれるすべての数字を一度に抽出したい場合は、re.findall()が最適です。
実務で最も頻繁に利用される関数の一つであり、結果をリストとして得られるため後続の処理が容易です。
import re
text = "2025年度の予算は5000万円、2026年度は6000万円を予定しています。"
# すべての数字を抽出
numbers = re.findall(r'\d+', text)
print(numbers)
['2025', '5000', '2026', '6000']
抽出された結果は文字列のリストとして格納されるため、計算に使用する場合はint()やfloat()で型変換を行う必要があります。
re.finditer():詳細な位置情報を含めて取得する
数字そのものだけでなく、その数字が文字列の「何文字目から何文字目までにあるか」という情報が必要な場合は、re.finditer()を使います。
この関数はマッチオブジェクトを順番に返すイテレータを返却します。
import re
text = "ID: 456, code: 789"
matches = re.finditer(r'\d+', text)
for match in matches:
print(f"値: {match.group()}, 開始位置: {match.start()}, 終了位置: {match.end()}")
値: 456, 開始位置: 4, 終了位置: 7
値: 789, 開始位置: 15, 終了位置: 18
実践的な数値抽出パターン
現実のデータでは、整数だけでなく小数やマイナス記号を含む数値など、多様な形式が登場します。
マイナス記号と小数を考慮した抽出
\d+だけでは、マイナス記号や小数点を無視して数字だけを個別に取得してしまいます。
負の数や小数を含めて一つの数値として扱いたい場合は、以下のようなパターンを使用します。
import re
text = "本日の気温は-5.5度、明日の最低気温は-10度です。"
# マイナス記号(?)、数字(\d+)、小数点と数字の組み合わせ(\.\d+)?を許可する
pattern = r'-?\d+(?:\.\d+)?'
results = re.findall(pattern, text)
print(results)
['-5.5', '-10']
このパターンでは、-?によってマイナス記号がある場合とない場合の両方に対応させています。
また、(?:\.\d+)?の部分で、小数点以下が存在する場合のみマッチするようにグループ化しています。
カンマ区切りの数値を抽出する
金額の表記などで使われる「1,200,000」のようなカンマ区切りの数字を抽出するには、カンマをパターンに含める必要があります。
import re
text = "総計は1,500,000円、内訳は500,000円と1,000,000円です。"
# 数字とカンマが組み合わさったパターンを指定
pattern = r'\d{1,3}(?:,\d{3})+'
results = re.findall(pattern, text)
print(results)
['1,500,000', '500,000', '1,000,000']
このコードでは、「1〜3桁の数字の後に、カンマと3桁の数字が1回以上続く」というルールを定義しています。
特定の単位がつく数字だけを抽出する(先読み・後読み)
正規表現の「周辺の文字を条件にする」機能を使うと、より高度な抽出が可能です。
例えば、「円」という文字の直前にある数字だけを抜き出したい場合、「肯定先読み(Positive Lookahead)」を利用します。
import re
text = "りんごは150円、オレンジは3個で300円、重さは500gです。"
# 「円」が直後に続く数字だけを取得
pattern = r'\d+(?=円)'
results = re.findall(pattern, text)
print(results)
['150', '300']
出力結果を見ると、単位が「g」である「500」や、個数を表す「3」は抽出されず、金額のみが取得できていることがわかります。
正規表現のパフォーマンスを最適化する方法
大量のテキストデータに対して繰り返し同じパターンで検索を行う場合、パターンの「コンパイル」を行うことが推奨されます。
re.compile()を使用すると、正規表現パターンを内部的なオブジェクトにあらかじめ変換しておくことができます。
これにより、ループ処理内などで関数を呼び出す際のオーバーヘッドを削減でき、処理速度の向上が期待できます。
import re
# パターンを事前にコンパイル
pattern_obj = re.compile(r'\d+')
data_list = ["item1: 100", "item2: 200", "item3: 300"]
results = []
for item in data_list:
# コンパイル済みオブジェクトのfindallメソッドを使用
match = pattern_obj.findall(item)
results.extend(match)
print(results)
['100', '200', '300']
コードの可読性も向上するため、複数の箇所で同じ正規表現を利用する場合は積極的にコンパイルを行いましょう。
注意点:全角数字の扱い
Python 3のreモジュールでは、デフォルト設定で\dが全角数字(123など)にもマッチすることがあります。
もし、「半角の0-9のみ」を厳密に抽出したい場合は、フラグにre.ASCIIを指定するか、[0-9]と記述するのが安全です。
import re
text = "半角123と全角456"
# ASCIIモードを指定
numbers = re.findall(r'\d+', text, flags=re.ASCII)
print(numbers)
['123']
データの入力元が信頼できない場合や、多言語が混在する環境では、この違いがバグの原因となる可能性があるため注意してください。
まとめ
Pythonの正規表現を使った数字の抽出は、基礎的な\d+から始まり、条件付きの複雑なパターンまで多岐にわたります。
re.search()、re.findall()、re.finditer()といった主要な関数の特性を理解することで、状況に応じた最適な実装が可能になります。
特に小数や負の数、単位を伴う数値の抽出は実務での頻出パターンであるため、今回紹介したコード例を参考に活用してみてください。
正規表現は一見難解に見えますが、一つひとつの記号の意味を整理して組み合わせることで、非常に強力な武器となります。
日々のデータクレンジングやテキスト解析の効率化に、ぜひPythonの正規表現を取り入れてみてください。
