0Pricing
Pandas & NumPy Academy · レッスン

テキスト列の結合とクリーニング

複数の列を1つの文字列に連結し、空白を削除して、不統一なカテゴリラベルを正規化します。

「テキスト列の結合とクリーニング」はCoddyKit上の無料Pandas & NumPy Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPandas & NumPy Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

テキスト列を連結する

複数の列の値を組み合わせて1つの文字列を作ることは、データ準備でよく行う作業です。たとえば、姓と名からフルネームを作成したり、番地、市区町村、国から住所を作成したりします。Pandasでは、数値列を.astype(str)で文字列に変換した後、2つのSeries(またはSeriesと文字列リテラル)に対して+演算子を使い、文字列列を連結します。

import pandas as pd

df = pd.DataFrame({
    'first_name': ['Alice', 'Bob', 'Carol'],
    'last_name': ['Smith', 'Jones', 'White']
})

df['full_name'] = df['first_name'] + ' ' + df['last_name']
print(df['full_name'].tolist())
# ['Alice Smith', 'Bob Jones', 'Carol White']

文字列以外の列と連結する

数値列と文字列列を結合する場合は、まず数値列を.astype(str)で文字列に変換する必要があります。文字列のSeriesと整数のSeriesを加算しようとすると、Pythonの+演算子はTypeErrorを発生させます。これは、型が混在する列から複合キーやラベルを作成する際によくある混乱の原因です。

import pandas as pd

df = pd.DataFrame({
    'product': ['Widget', 'Gadget'],
    'version': [3, 5]
})

# Must convert int to str before concatenating
df['label'] = df['product'] + ' v' + df['version'].astype(str)
print(df['label'].tolist())
# ['Widget v3', 'Gadget v5']

.str.cat()で区切り文字を使って結合する

Series.str.cat(others, sep=)は、区切り文字を使って複数のSeriesを結合するPandas標準の方法で、NaN値も適切に処理できます。デフォルトでは、いずれかの列にNaNがあると、その行の結果もNaNになります。na_rep='?'(または任意の文字列)を渡すと、NaNをそのまま伝播させず、プレースホルダーに置き換えられます。

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'city': ['NYC', 'LA', None],
    'state': ['NY', None, 'TX'],
    'country': ['USA', 'USA', 'USA']
})

# Join with ', ' — NaN rows produce NaN by default
df['location'] = df['city'].str.cat(
    [df['state'], df['country']],
    sep=', ',
    na_rep='N/A'
)
print(df['location'].tolist())
# ['NYC, NY, USA', 'LA, N/A, USA', 'N/A, TX, USA']

一貫性のないカテゴリラベルを正規化する

実際のデータのカテゴリ列には、タイプミス、大文字と小文字の違い、異なる略語(例: 'US'、'USA'、'United States')が原因で、一貫性のないラベルが含まれていることがよくあります。標準的な対処方法は、すべての表記揺れを正規形に対応付けるマッピング辞書を作成し、.map()または.replace()で適用することです。

import pandas as pd

df = pd.DataFrame({
    'country': ['US', 'USA', 'United States', 'uk', 'UK', 'United Kingdom']
})

canonical = {
    'US': 'United States', 'USA': 'United States', 'United States': 'United States',
    'uk': 'United Kingdom', 'UK': 'United Kingdom', 'United Kingdom': 'United Kingdom'
}

df['country_clean'] = df['country'].map(canonical)
print(df['country_clean'].tolist())
# ['United States', 'United States', 'United States',
#  'United Kingdom', 'United Kingdom', 'United Kingdom']

空白の除去と大文字・小文字の標準化

テキスト列を比較またはグループ化する前に、最初のクリーニング手順として必ず空白を除去し、大文字と小文字を正規化してください。人間には同じに見える2つの値(' Active'と'active')も、先頭の空白と大文字・小文字の違いがあるため、Pandasでは異なる値として扱われます。stripしてからlowerする2段階のチェーンで、両方の問題に対処できます。

import pandas as pd

df = pd.DataFrame({
    'status': ['  Active', 'INACTIVE', 'active ', ' Pending  ', 'ACTIVE']
})

df['status_clean'] = df['status'].str.strip().str.lower()
print(df['status_clean'].value_counts())
# active      3
# inactive    1
# pending     1

タイプミスを修正するファジーマッチング

タイプミスによって完全一致ができない場合、ファジーマッチングで文字列間の類似度スコアを計算します。rapidfuzzライブラリ(または従来のfuzzywuzzy)を使うと、ベクトル化されたファジーマッチングを利用できます。一般的な手順は、汚れた値ごとに最も近い正規値を探し、類似度のしきい値を上回るものを採用して、修正用のマップを作成することです。

# Conceptual example (requires: pip install rapidfuzz)
from rapidfuzz import process

canonical_cities = ['New York', 'Los Angeles', 'Chicago', 'Houston']
dirty_values = ['New Yrok', 'Los Angelas', 'Chicagoo']

for dirty in dirty_values:
    best, score, _ = process.extractOne(dirty, canonical_cities)
    print(f'{dirty!r} -> {best!r} (score={score:.0f}%)')
# 'New Yrok'   -> 'New York'    (score=91%)
# 'Los Angelas'-> 'Los Angeles' (score=96%)
# 'Chicagoo'   -> 'Chicago'     (score=94%)

explode()で複数値セルを分割する

1つのセルに区切り文字で複数の値が含まれていることがあります(例: 'python,sql,pandas')。列を分割してリストにした後、.explode()を呼び出すと、値ごとに1行を作成できます。これにより、値が詰め込まれた横長のセルが整然とした縦長形式に変換され、各行に必ず1つの値だけが含まれるようになります。この形式は、それらの値を使ったgroupbyやjoinの操作に必要です。

import pandas as pd

df = pd.DataFrame({
    'user_id': [1, 2, 3],
    'skills': ['python,sql', 'java,kotlin,sql', 'python']
})

df['skills'] = df['skills'].str.split(',')
exploded = df.explode('skills')
print(exploded)
#    user_id   skills
# 0        1   python
# 0        1      sql
# 1        2     java
# 1        2   kotlin
# 1        2      sql
# 2        3   python

テキストの異なるエンコーディングに対処する

異なるソースから取得したテキストデータには、エンコーディングの問題が含まれていることがあります。たとえば、\xa0(ノーブレークスペース)、\u2019(曲がったアポストロフィ)、文字化けしたアクセント付き文字などです。手早くASCIIのみの文字列にクリーニングするには.str.encode('ascii', errors='replace').str.decode('ascii')を使い、アクセントを除去する前に分解するには.str.normalize('NFKD')を使います。

import pandas as pd
import unicodedata

df = pd.DataFrame({'name': ['Caf\u00e9', 'na\u00efve', 'r\u00e9sum\u00e9']})

# Normalize and strip accents (NFKD decomposition + ascii encoding)
df['name_ascii'] = (
    df['name']
    .str.normalize('NFKD')
    .str.encode('ascii', errors='ignore')
    .str.decode('ascii')
)
print(df)
#       name name_ascii
# 0     Cafe       Cafe
# 1    naive      naive
# 2   resume     resume

複合キーを作成する

多くのデータセットでは、結合や重複排除のために、複数の列から行を一意に識別する複合キーを作成する必要があります。クリーニング済みの文字列列(空白除去、大文字・小文字の統一、正規化済み)を1つのキー文字列に結合すると、同じエンティティの表記がデータソースごとに少し異なる場合でも、一貫して照合できます。

import pandas as pd

df = pd.DataFrame({
    'first': ['  Alice', 'BOB', ' Carol'],
    'last': ['Smith ', 'JONES', 'White  '],
    'dob': ['1990-01-15', '1985-07-22', '1992-11-30']
})

df['match_key'] = (
    df['first'].str.strip().str.lower() + '|' +
    df['last'].str.strip().str.lower() + '|' +
    df['dob']
)
print(df['match_key'].tolist())
# ['alice|smith|1990-01-15', 'bob|jones|1985-07-22', 'carol|white|1992-11-30']

正規カテゴリリストを適用する

クリーニング後、カテゴリ型のテキスト列に含まれるすべての値が既知の正規集合に属していることを検証します。集合に含まれない値は、新たに追加された正当なカテゴリ、またはデータエラーの可能性があります。未知の値を黙って削除するのではなく、手動確認のために記録またはフラグ付けしてください。そうすれば、問題を見落とさずに済みます。

import pandas as pd

df = pd.DataFrame({
    'status': ['active', 'inactive', 'active', 'archived', 'unknown_status']
})

canonical = {'active', 'inactive', 'archived'}

unknown = df[~df['status'].isin(canonical)]['status'].unique()
print('Unknown statuses:', unknown.tolist())
# ['unknown_status']

# Flag unknown rows
df['status_valid'] = df['status'].isin(canonical)
print(df)

完全なテキストクリーニングパイプライン

ここでは、このレッスンで扱ったすべての手法を適用する、完全なテキストクリーニングパイプラインを紹介します。空白の除去、大文字・小文字の正規化、略語の修正、特殊文字の除去、正規リストとの照合を行います。このような再利用可能な関数は、どのデータ取り込みモジュールにも追加できます。

import pandas as pd

def clean_category_column(series, canonical_map, canonical_set):
    cleaned = (
        series
        .str.strip()
        .str.lower()
        .map(lambda x: canonical_map.get(x, x))  # fix known variants
    )
    unknown = cleaned[~cleaned.isin(canonical_set)]
    if not unknown.empty:
        print('Warning: unknown values:', unknown.unique().tolist())
    return cleaned

cmap = {'eng': 'engineering', 'hr': 'human_resources', 'mktg': 'marketing'}
cset = {'engineering', 'human_resources', 'marketing', 'finance'}

df = pd.DataFrame({'dept': ['Eng', 'HR', 'Marketing', 'MKTG', 'Legal']})
df['dept_clean'] = clean_category_column(df['dept'], cmap, cset)
print(df)

理解度チェック

テキスト列の結合とクリーニングについて理解度を確認しましょう。

レッスンのまとめ

このレッスンでは、数値を文字列に変換してから+演算子で列を結合する方法、str.cat(sep=)で区切り文字を使って結合しNaNを処理する方法、正規マップを.map()で適用して一貫性のないラベルを正規化する方法、explode()でリスト値を持つセルを行に展開する方法を学びました。正規集合を適用して、データ品質の問題を早期に検出しましょう。次は、列の値でDataFrameを並べ替えます。

よくある質問

「テキスト列の結合とクリーニング」レッスンは無料ですか?

はい。「テキスト列の結合とクリーニング」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Pandas & NumPy Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

「テキスト列の結合とクリーニング」で何を学びますか?

複数の列を1つの文字列に連結し、空白を削除して、不統一なカテゴリラベルを正規化します。 ブラウザで直接実行するハンズオンコードでPandas & NumPy Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Pandas & NumPy Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPandas & NumPy Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「テキスト列の結合とクリーニング」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPandas & NumPy Academyレッスンでコードを書いて実行できますか?

はい。すべてのPandas & NumPy Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. .strアクセサー
  2. 文字列の分割と置換
  3. 正規表現によるパターンマッチング
  4. テキスト列の結合とクリーニング
← Pandas & NumPy Academyに戻る