Pythonデータ分析 Pandas Series 文字列長を効率的に取得する方法

2025-05-27

基本的な使い方

まず、pandas ライブラリをインポートし、文字列を含む Series オブジェクトを作成します。

import pandas as pd

data = pd.Series(['apple', 'banana', 'cherry', 'date'])

この data という Series オブジェクトに対して、.str.len() メソッドを適用すると、各文字列の長さが計算された新しい Series オブジェクトが返されます。

string_lengths = data.str.len()
print(string_lengths)

出力例

0    5
1    6
2    6
3    4
dtype: int64

上記の出力例からわかるように、元の Series の各文字列 ('apple', 'banana', 'cherry', 'date') の長さ (それぞれ 5, 6, 6, 4) が、新しい Series オブジェクトとして返されています。データ型は整数の int64 となります。

NaN 値の扱い

もし Series オブジェクトに NaN (Not a Number) 値が含まれている場合、.str.len() はその要素に対して NaN を返します。

data_with_nan = pd.Series(['apple', None, 'cherry'])
lengths_with_nan = data_with_nan.str.len()
print(lengths_with_nan)

出力例

0    5.0
1    NaN
2    6.0
dtype: float64

この例では、インデックス 1 の要素が None (pandas では NaN として扱われます) であるため、対応する長さも NaN となっています。データ型は浮動小数点数の float64 になります。



よくあるエラーとトラブルシューティング

  1. AttributeError: Can only use .str accessor with string values!

    • エラー内容
      このエラーは、.str アクセサを文字列型 (string) ではないデータ型の Series オブジェクトに対して使用しようとした場合に発生します。例えば、整数の Series や浮動小数点数の Series に対して .str.len() を実行するとこのエラーが出ます。
    • トラブルシューティング
      • データ型の確認
        問題の Series のデータ型を確認してください。df['列名'].dtype で確認できます。
      • データ型の変換
        もしデータ型が文字列型でない場合は、.astype(str) メソッドを使用して文字列型に変換してください。ただし、数値型を文字列に変換すると、数値としての扱いはできなくなることに注意が必要です。
      • 意図しない型の混在
        Series 内に文字列と数値などが混在している場合もこのエラーが出ることがあります。データの整合性を確認し、必要に応じてデータをクリーニングしてください。
    import pandas as pd
    data_int = pd.Series([1, 2, 3])
    # data_int.str.len()  # これはエラーになります
    
    data_str = data_int.astype(str)
    lengths = data_str.str.len()
    print(lengths)
    
  2. TypeError: object of type 'float' has no len() (または類似の TypeError)

    • エラー内容
      このエラーは、Series の要素が文字列型ではない場合に、.str.len() の内部処理で len() 関数が文字列でないオブジェクトに適用されようとして発生します。None (pandas では NaN として扱われることがあります) が含まれている場合にも起こりえます。
    • トラブルシューティング
      • NaN 値の処理
        SeriesNaN 値が含まれている可能性があります。.isna() メソッドなどで NaN 値の存在を確認し、必要に応じて .dropna() で削除したり、.fillna('') などで空文字列に置換したりするなどの前処理を行ってください。
      • データ型の確認
        前述のエラーと同様に、データ型が意図した文字列型になっているか確認してください。


    import pandas as pd
    data_mixed = pd.Series(['apple', 123, 'cherry', None])
    # data_mixed.str.len()  # これはエラーになります
    
    # NaN 値を空文字列で置換する例
    data_fixed = data_mixed.fillna('')
    lengths = data_fixed.str.len()
    print(lengths)
    
    # 文字列型に変換する例 (数値は文字列になります)
    data_str = data_mixed.astype(str)
    lengths = data_str.str.len()
    print(lengths)
    
  3. IndexError (まれなケース)

    • エラー内容
      非常にまれなケースですが、pandas の内部的な処理でインデックスに関するエラーが発生することがあります。
    • トラブルシューティング
      • pandas のバージョン確認とアップデート
        使用している pandas のバージョンが古い場合、既知のバグが存在する可能性があります。最新バージョンにアップデートしてみることを推奨します (pip install --upgrade pandas)。
      • 再現性の確認
        他のデータや簡単な Series で同様のエラーが再現するかどうかを確認し、問題が特定のデータに依存するのか、pandas 自体の問題なのかを切り分けます。
      • エラーレポート
        もし pandas 自体の問題である可能性が高い場合は、具体的なエラーメッセージと再現コードを添えて、pandas のIssue Tracker (GitHub など) に報告することを検討してください。

トラブルシューティングの一般的なアプローチ

  • 類似の事例を検索する
    エラーメッセージや行っている処理に関するキーワードでインターネット検索すると、同じ問題に遭遇した人の解決策が見つかることがあります。
  • ステップごとに実行する
    複雑な処理を行っている場合は、処理を छोटे ステップに分け、各ステップの結果を確認しながら進めます。
  • データ型を確認する
    dtype 属性を使って、Series のデータ型を確認します。
  • データの中身を確認する
    問題が発生している Series の一部を表示 (head(), tail(), sample()) して、データの状態を把握します。
  • エラーメッセージをよく読む
    エラーメッセージは問題の原因を示唆する重要な情報を含んでいます。


基本的な文字列長の取得

import pandas as pd

# 文字列の Series を作成
data = pd.Series(['apple', 'banana', 'cherry', 'date'])

# 各文字列の長さを取得
string_lengths = data.str.len()

# 結果を表示
print(string_lengths)

この例では、data という文字列の Series の各要素 ('apple', 'banana', 'cherry', 'date') の長さを .str.len() を使って計算し、その結果を string_lengths に格納して表示しています。出力は以下のようになります。

0    5
1    6
2    6
3    4
dtype: int64

欠損値 (NaN) を含む場合の処理

import pandas as pd
import numpy as np

# 欠損値を含む文字列の Series を作成
data_with_nan = pd.Series(['apple', np.nan, 'cherry', ''])

# 各文字列の長さを取得
lengths_with_nan = data_with_nan.str.len()

# 結果を表示
print(lengths_with_nan)

この例では、data_with_nannp.nan (Not a Number) と空文字列 '' を含んでいます。.str.len()NaN に対しては NaN を返し、空文字列に対しては 0 を返します。

0    5.0
1    NaN
2    6.0
3    0.0
dtype: float64

DataFrame の特定の列に対して適用

import pandas as pd

# DataFrame を作成
df = pd.DataFrame({'name': ['Alice', 'Bob', 'Charlie', 'David'],
                   'city': ['New York', 'London', 'Paris', 'Tokyo']})

# 'name' 列の文字列の長さを取得
name_lengths = df['name'].str.len()

# 結果を表示
print(name_lengths)

# 'city' 列の文字列の長さを取得
city_lengths = df['city'].str.len()

# 結果を表示
print(city_lengths)

この例では、DataFrame df の 'name' 列と 'city' 列に対してそれぞれ .str.len() を適用し、各列の文字列の長さを計算しています。

0    5
1    3
2    7
3    5
Name: name, dtype: int64
0    8
1    6
2    5
3    5
Name: city, dtype: int64

条件に基づいたフィルタリング

import pandas as pd

# 文字列の Series を作成
data = pd.Series(['apple', 'banana', 'cherry', 'date', 'grape'])

# 長さが 5 より大きい文字列をフィルタリング
long_strings = data[data.str.len() > 5]

# 結果を表示
print(long_strings)

ここでは、.str.len() を使って各文字列の長さを取得し、その結果を使って長さが 5 より大きい文字列のみをフィルタリングしています。

1    banana
2    cherry
4     grape
dtype: object

新しい列として長さ情報を追加

import pandas as pd

# DataFrame を作成
df = pd.DataFrame({'item': ['pen', 'notebook', 'pencil', 'eraser']})

# 'item' 列の文字列長を新しい 'length' 列として追加
df['length'] = df['item'].str.len()

# 結果を表示
print(df)

この例では、DataFrame df の 'item' 列の文字列長を計算し、その結果を新しい 'length' 列として DataFrame に追加しています。

       item  length
0       pen       3
1  notebook       8
2    pencil       6
3    eraser       6


apply() メソッドと len() 関数を使用する

Series オブジェクトの各要素に関数を適用する apply() メソッドと、Python の組み込み関数である len() を組み合わせることで、文字列の長さを計算できます。

import pandas as pd

data = pd.Series(['apple', 'banana', 'cherry', 'date'])

# apply() と len() を使用して文字列長を取得
string_lengths_apply = data.apply(len)

print(string_lengths_apply)

このコードは、data Series の各要素に対して len() 関数を適用し、その結果を新しい Series として string_lengths_apply に格納します。出力は .str.len() と同じになります。

0    5
1    6
2    6
3    4
dtype: int64

欠損値 (NaN) の扱い

apply(len) は、NaN 値に対して float 型のオブジェクトとして len() を適用しようとするため、TypeError が発生する可能性があります。そのため、欠損値を含む場合は注意が必要です。

import pandas as pd
import numpy as np

data_with_nan = pd.Series(['apple', np.nan, 'cherry'])

# NaN を含むとエラーになる可能性
# lengths_with_nan_apply = data_with_nan.apply(len) # TypeError

# NaN を文字列に変換してから長さを計算するなどの工夫が必要
lengths_with_nan_handled = data_with_nan.fillna('').apply(len)
print(lengths_with_nan_handled)

出力:

0    5
1    0
2    6
dtype: int64

リスト内包表記 (List Comprehension) を使用する

Series オブジェクトをリストに変換し、リスト内包表記を使って各文字列の長さを計算する方法です。その後、結果を再び Series オブジェクトに変換できます。

import pandas as pd

data = pd.Series(['apple', 'banana', 'cherry', 'date'])

# リスト内包表記で文字列長を取得
string_lengths_listcomp = pd.Series([len(s) for s in data])

print(string_lengths_listcomp)

この方法は、.str アクセサを使用するよりも冗長になる可能性がありますが、基本的な Python の構文で実現できます。出力は以下の通りです。

0    5
1    6
2    6
3    4
dtype: int64

欠損値 (NaN) の扱い

リスト内包表記でも、NaN 値に対して len() を適用しようとすると TypeError が発生します。そのため、事前に NaN 値を処理する必要があります。

import pandas as pd
import numpy as np

data_with_nan = pd.Series(['apple', np.nan, 'cherry'])

# NaN を処理してからリスト内包表記を使用
string_lengths_listcomp_handled = pd.Series([len(str(s)) if pd.notna(s) else np.nan for s in data_with_nan])
print(string_lengths_listcomp_handled)
0    5.0
1    NaN
2    6.0
dtype: float64

ループ処理 (推奨されません)

Series オブジェクトをイテレートして各要素の長さを計算する方法ですが、pandas のベクトル化された操作の利点を活かせないため、大規模なデータセットでは非常に非効率です。

import pandas as pd

data = pd.Series(['apple', 'banana', 'cherry', 'date'])
string_lengths_loop = pd.Series([0] * len(data)) # 結果を格納する空の Series を初期化

for i, s in data.items():
    string_lengths_loop[i] = len(s)

print(string_lengths_loop)

この方法は理解しやすいかもしれませんが、パフォーマンスの観点からは避けるべきです。

pandas.Series.str.len() は、文字列の長さを効率的かつ簡潔に計算するための推奨される方法です。apply(len) やリスト内包表記も同様の処理を実現できますが、欠損値の扱いなどで追加の考慮が必要になる場合があります。ループ処理は、パフォーマンス上の理由から大規模データセットでは避けるべきです。