Pandasの皮を被ったリストの操作

Filter Pandas Dataframe that is an array – StackOverflow

import pandas as pd

df = pd.DataFrame({'a': [1,2,3,4,5], 'b': [['true','false'],['false'],['false','false','false'],['false','false','true'],[]]})
df
    a   b
0   1   [true, false]
1   2   [false]
2   3   [false, false, false]
3   4   [false, false, true]
4   5   []

bool型等では無く、「dtype:object」なので、
これはPandasの皮を被ったただのリスト(PyObject)。

こういう場合は(実際には大体どの様な場合でもだけど)Pandasで処理しようと思うより、
内包表記なりピュアな関数に放り込んで処理した方がリーズナブル。

Pandasで処理する場合は、リストを列方向に展開する。
(Pandas.DataFrame内のリストの列方向への展開はapply(pd.Series))
(Pandas.DataFrame内のリストの行方向への展開はstack().reset_index())

df[df['b'].apply(pd.Series).eq('true').any(1)]
    a   b
0   1   [true, false]
3   4   [false, false, true]
df[['true' in x for x in df['b']]]
    a   b
0   1   [true, false]
3   4   [false, false, true]

元々、中身がリストなので.tolist()する必要はない。

%timeit df[df['b'].apply(pd.Series).eq('true').any(1)]
%timeit df[['true' in x for x in df['b']]]
%timeit df[['true' in x for x in df['b'].tolist()]]

100 loops, best of 3: 2.59 ms per loop
1000 loops, best of 3: 257 µs per loop
1000 loops, best of 3: 264 µs per loop

カテゴリー: 未分類 パーマリンク