[解決済み】pandasのDataFrameやSeriesに複数のフィルタを適用する効率的な方法
質問
PandasのDataFrameやSeriesオブジェクトに複数のフィルタを適用したいシナリオがあります。 基本的には、ユーザーが実行時に指定したフィルタリング(比較演算)を効率的に連鎖させたいのです。
フィルタは加算式でなければならない(つまり、適用するごとに結果が狭くなるようにしなければならない)。
現在、私は
reindex()
しかし、これは毎回新しいオブジェクトを作成し、基礎となるデータをコピーします (私がドキュメントを正しく理解していれば)。 そのため、大きなSeriesやDataFrameをフィルタリングする際に、非常に非効率的な場合があります。
私が考えているのは
apply()
,
map()
などの方がいいかもしれません。 私はパンダの初心者なので、まだすべてを理解しようとしています。
TL;DR
以下の形式の辞書を取得し、与えられたSeriesオブジェクトに各操作を適用して、「フィルタリングされた」Seriesオブジェクトを返したい。
relops = {'>=': [1], '<=': [1]}
長い例
まずは現在持っているもので、Seriesオブジェクトを1つだけフィルタリングする例から紹介します。 以下は、私が現在使用している関数である。
def apply_relops(series, relops):
"""
Pass dictionary of relational operators to perform on given series object
"""
for op, vals in relops.iteritems():
op_func = ops[op]
for val in vals:
filtered = op_func(series, val)
series = series.reindex(series[filtered])
return series
ユーザーは、実行したい操作を辞書で指定する。
>>> df = pandas.DataFrame({'col1': [0, 1, 2], 'col2': [10, 11, 12]})
>>> print df
>>> print df
col1 col2
0 0 10
1 1 11
2 2 12
>>> from operator import le, ge
>>> ops ={'>=': ge, '<=': le}
>>> apply_relops(df['col1'], {'>=': [1]})
col1
1 1
2 2
Name: col1
>>> apply_relops(df['col1'], relops = {'>=': [1], '<=': [1]})
col1
1 1
Name: col1
繰り返しになりますが、上記の方法の「問題点」は、その間のステップで不必要なデータのコピーが多く発生する可能性があるということです。
また、これを発展させて、渡された辞書に演算対象となる列を含め、入力された辞書を元にDataFrame全体をフィルタリングできるようにしたいと思います。 しかし、Seriesで動作するものは、DataFrameに簡単に拡張できるものと思っています。
どのように解決するのですか?
Pandas(とnumpy)では、以下のようなことが可能です。 ブーリアンインデックス より効率的になります。
In [11]: df.loc[df['col1'] >= 1, 'col1']
Out[11]:
1 1
2 2
Name: col1
In [12]: df[df['col1'] >= 1]
Out[12]:
col1 col2
1 1 11
2 2 12
In [13]: df[(df['col1'] >= 1) & (df['col1'] <=1 )]
Out[13]:
col1 col2
1 1 11
もし、このためのヘルパー関数を書きたいのであれば、以下のようなものを考えてみてください。
In [14]: def b(x, col, op, n):
return op(x[col],n)
In [15]: def f(x, *b):
return x[(np.logical_and(*b))]
In [16]: b1 = b(df, 'col1', ge, 1)
In [17]: b2 = b(df, 'col1', le, 1)
In [18]: f(df, b1, b2)
Out[18]:
col1 col2
1 1 11
更新してください。 pandas 0.13 では、クエリメソッドである このような場合、カラム名が有効な識別子であると仮定すると、以下のように動作します(大きなフレームでは numexpr を使用します。)
In [21]: df.query('col1 <= 1 & 1 <= col1')
Out[21]:
col1 col2
1 1 11
関連
-
[解決済み] PandasでDataFrameの行を反復処理する方法
-
[解決済み] Pandas DataFrameからカラムを削除する
-
[解決済み] Pandasのデータフレームで複数の列を選択する
-
[解決済み] Pandas DataFrameの行数を取得する方法は?
-
[解決済み] 既存のDataFrameに新しい列を追加する方法は?
-
[解決済み] 一行ずつ追加してPandas Dataframeを作成する
-
[解決済み] pandasを使った "大量データ "ワークフロー【終了しました
-
[解決済み] Pandasシリーズ/DataFrame全体をプリティプリントする
-
[解決済み] Pythonのdictをdataframeに変換する
-
[解決済み】Pandas DataFrameのカラムヘッダからリストを取得する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Python関数の高度な応用を解説
-
Python Decorator 練習問題
-
Evidentlyを用いたPythonデータマイニングによる機械学習モデルダッシュボードの作成
-
[解決済み] データ型が理解できない
-
[解決済み】"No JSON object could be decoded "よりも良いエラーメッセージを表示する。
-
[解決済み】 AttributeError("'str' object has no attribute 'read'")
-
[解決済み】SyntaxError: デフォルト以外の引数がデフォルトの引数に続く
-
[解決済み】ValueError: pickleプロトコルがサポートされていません。3、python2 pickleはpython3 pickleでダンプしたファイルを読み込むことができない?
-
[解決済み】pandas DataFrameから条件式に基づき行を削除する方法【重複あり
-
[解決済み】pandas.DataFrameから複雑な条件での選択