pandas の str アクセサで文字列を一括処理する

pandas で文字列データを扱うとき、str アクセサを使うと列全体に文字列メソッドを一括適用できます。ループを書かずに済むので、コードが簡潔になり、処理も高速です。

基本的な使い方

df['列名'].str.メソッド名() の形式で、文字列メソッドを適用します。

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice Smith', 'Bob Jones', 'Charlie Brown']
})

# 大文字に変換
df['upper'] = df['name'].str.upper()

# 小文字に変換
df['lower'] = df['name'].str.lower()

# 先頭だけ大文字
df['title'] = df['name'].str.title()

よく使うメソッド

文字列操作でよく使うメソッドを紹介します。

メソッド説明
str.upper()大文字に変換
str.lower()小文字に変換
str.strip()前後の空白を削除
str.replace()文字列を置換
str.split()分割してリストに
str.len()文字数を取得
str.contains()パターンを含むか
str.startswith()指定文字で始まるか
str.endswith()指定文字で終わるか

文字列の置換

str.replace で文字列を置換できます。

df = pd.DataFrame({
    'text': ['hello-world', 'foo-bar', 'test-data']
})

# ハイフンをアンダースコアに
df['text'] = df['text'].str.replace('-', '_')

# 正規表現で置換
df['text'] = df['text'].str.replace(r'\d+', '', regex=True)

文字列の分割

str.split で文字列を分割し、特定の部分を取り出せます。

df = pd.DataFrame({
    'email': ['alice@example.com', 'bob@test.org']
})

# @ で分割してユーザー名を取得
df['user'] = df['email'].str.split('@').str[0]

# ドメインを取得
df['domain'] = df['email'].str.split('@').str[1]

expand=True を指定すると、分割結果を複数列に展開できます。

df[['user', 'domain']] = df['email'].str.split('@', expand=True)

部分文字列の抽出

str.extract で正規表現を使ってパターンを抽出できます。

df = pd.DataFrame({
    'text': ['Price: $100', 'Cost: $250', 'Fee: $50']
})

# 数字を抽出
df['price'] = df['text'].str.extract(r'(\d+)')

グループを複数使うと、複数列を一度に抽出できます。

df = pd.DataFrame({
    'info': ['Alice:25', 'Bob:30', 'Charlie:35']
})

df[['name', 'age']] = df['info'].str.extract(r'(\w+):(\d+)')

条件フィルタリング

str.contains でパターンマッチングによるフィルタリングができます。

df = pd.DataFrame({
    'product': ['Apple iPhone', 'Samsung Galaxy', 'Apple iPad', 'Google Pixel']
})

# Apple を含む行だけ抽出
apple_products = df[df['product'].str.contains('Apple')]

# 正規表現で検索
phones = df[df['product'].str.contains(r'Phone|Galaxy|Pixel', regex=True)]

str.startswithstr.endswith も便利です。

# .com で終わるメールアドレス
df[df['email'].str.endswith('.com')]

# http で始まる URL
df[df['url'].str.startswith('http')]

NaN の扱い

str アクセサは NaN を自動的にスキップします。結果も NaN になります。

df = pd.DataFrame({
    'name': ['Alice', None, 'Charlie']
})

df['upper'] = df['name'].str.upper()
# None の行は NaN になる

na パラメータでデフォルト値を指定できるメソッドもあります。

# NaN は False として扱う
df[df['name'].str.contains('li', na=False)]

str アクセサを使いこなすと、文字列データの前処理が格段に楽になります。ループで 1 つずつ処理するよりも、コードが読みやすく、実行も高速です。