pandasの要素としてリストを格納し処理

pandas.DataFrame, Seriesの要素としてPythonの組み込み型であるリストlistを格納できます。 例えば区切り文字(デリミタ)で区切られた文字列などは、文字列メソッドで処理するよりもリスト化したほうが便利な場合があります。 以下のpandas.DataFrameを例とします。

import pandas as pd

df = pd.DataFrame({'s': ['X,Y,Z', 'X', 'XY,Y', 'Y,Z,XY']},
                  index=['a', 'b', 'c', 'd'])

print(df)
#         s
# a   X,Y,Z
# b       X
# c    XY,Y
# d  Y,Z,XY

以下の内容について説明します。

pandas.DataFrameの文字列の列からリストの列を生成 リストの列に関数・メソッドを適用 リストの要素数を取得 リストをソート リストを文字列に連結 リストから要素を追加・削除

リストに対する条件で行を抽出

pandas.DataFrameの文字列の列からリストの列を生成

文字列メソッドstr.split()を使います。引数expand=Trueとすると複数の列に分割されるが、デフォルト(expand=Flase)の場合はリストとなります。

df['l'] = df['s'].str.split(',')
print(df)
#         s           l
# a   X,Y,Z   [X, Y, Z]
# b       X         [X]
# c    XY,Y     [XY, Y]
# d  Y,Z,XY  [Y, Z, XY]

列のデータ型dtypeは文字列の列もリストの列もobjectだが、各要素はそれぞれの型typeになっています。

print(df.dtypes)
# s    object
# l    object
# dtype: object

print(type(df.at['a', 's']))
# <class 'str'>

print(type(df.at['a', 'l']))
# <class 'list'>

なお、X,Y,ZではなくX, Y, Zのように区切り文字のあとにスペースがある場合はstrip()で除外します。この例の場合は変化なし。 無名関数で処理を定義して、apply()で各要素に適用しています。map()でも問題ありません。

print(df['s'].apply(lambda x: [s.strip() for s in x.split(',')]))
# a     [X, Y, Z]
# b           [X]
# c       [XY, Y]
# d    [Y, Z, XY]
# Name: s, dtype: object

スペースの数が同じ場合はstr.split(', ')のように区切り文字を指定しても問題ない。

リストの列に関数・メソッドを適用

Pythonのリストlist型に対する関数およびメソッドをpandas.DataFrameの列(= pandas.Series)のapply()またはmap()で適用します。 要素を引数としないメソッド(リスト自体のメソッドなど)は無名関数(ラムダ式)を使います。

リストの要素数を取得

組み込み関数len()を適用。

print(df['l'].apply(len))
# a    3
# b    1
# c    2
# d    3
# Name: l, dtype: int64

リストをソート

組み込み関数sorted()を適用。

print(df['l'].apply(sorted))
# a     [X, Y, Z]
# b           [X]
# c       [XY, Y]
# d    [XY, Y, Z]
# Name: l, dtype: object

リストを文字列に連結

文字列メソッドjoin()を適用。

print(df['l'].apply(','.join))
# a     X,Y,Z
# b         X
# c      XY,Y
# d    Y,Z,XY
# Name: l, dtype: object

ソートしてから文字列に連結。

print(df['l'].apply(lambda x: ','.join(sorted(x))))
# a     X,Y,Z
# b         X
# c      XY,Y
# d    XY,Y,Z
# Name: l, dtype: object

リストから要素を追加・削除

リストのメソッドappend()で要素を追加。もとのリストに新たな要素が追加される。

df['l'].apply(lambda x: x.append('A'))
print(df)
#         s              l
# a   X,Y,Z   [X, Y, Z, A]
# b       X         [X, A]
# c    XY,Y     [XY, Y, A]
# d  Y,Z,XY  [Y, Z, XY, A]

リストのメソッドremove()で要素を削除。remove()は存在しない要素を指定するとエラーになるので、三項演算子を使って対象の要素が存在する場合のみremove()を適用しています。

df['l'].apply(lambda x: x.remove('Z') if 'Z' in x else x)
print(df)
#         s           l
# a   X,Y,Z   [X, Y, A]
# b       X      [X, A]
# c    XY,Y  [XY, Y, A]
# d  Y,Z,XY  [Y, XY, A]

リストに対する条件で行を抽出

リストに対してbool値(True, False)を返す関数などを適用し取得したbool型のpandas.Seriesをもとのpandas.DataFrameに渡す。 特定の要素が存在する場合に抽出。inを使います。

print(df['l'].apply(lambda x: 'X' in x))
# a     True
# b     True
# c    False
# d    False
# Name: l, dtype: bool

print(df[df['l'].apply(lambda x: 'X' in x)])
#        s          l
# a  X,Y,Z  [X, Y, A]
# b      X     [X, A]

常にリスト化したほうが良いわけではなく、条件によってはもとの文字列に対して文字列メソッドstr.contains()を使うだけでOKな場合もあります。

print(df['s'].str.contains('Z'))
# a     True
# b    False
# c    False
# d     True
# Name: s, dtype: bool

print(df[df['s'].str.contains('Z')])
#         s           l
# a   X,Y,Z   [X, Y, A]
# d  Y,Z,XY  [Y, XY, A]

XとXZのように区切り文字で区切られた要素の一部分が重複していたりするとstr.contains()だと面倒。

シェア

関連カテゴリー

Python pandas

Pythonのリストと配列とnumpy.ndarrayの違いと使い分け pandasからNumPyの関数などを使う方法(pd.np) pandas.DataFrameの列をインデックス(行名)に割り当てるset_index pandasで条件に応じて値を代入(where, mask) pandasで最大値・最小値の行名・列名を取得するidxmax, idxmin pandasの時系列データにおける頻度(引数freq)の指定方法 Pythonで正規化・標準化(リスト、NumPy配列、pandas.DataFrame) pandasで欠損値NaNが含まれているか判定、個数をカウント pandasでJSON文字列・ファイルを読み込み(read_json) pandas.DataFrameの行番号、列番号を取得 pandas.DataFrameの行・列を指定して削除するdrop pandasで特定の文字列を含む行を抽出(完全一致、部分一致) pandasのcrosstabでクロス集計(カテゴリ毎の出現回数・頻度を算出) pandasでカテゴリ変数をダミー変数に変換(get_dummies) pandasで分位数・パーセンタイルを取得するquantile

Last Updated: 6/26/2019, 10:34:03 PM