PandasでSQLのselect-statementのような動作を複製することについてのこの質問を見た後、私はこの回答を追加して、その質問に対する受け入れられた回答で与えられた冗長な構文を短縮できる2つの方法を示しました。
それらをいじってみた後、私の2つの短い構文の方法は大幅に遅くなり、誰かがその理由を説明できることを望んでいます。
以下で使用される関数は、Pandas、IPython、または上記のリンクされた質問と回答のいずれかからのものであると想定できます。
import pandas
import numpy as np
N = 100000
df = pandas.DataFrame(np.round(np.random.rand(N,5)*10))
def pandas_select(dataframe, select_dict):
inds = dataframe.apply(lambda x: reduce(lambda v1,v2: v1 and v2,
[elem[0](x[key], elem[1])
for key,elem in select_dict.iteritems()]), axis=1)
return dataframe[inds]
%timeit _ = df[(df[1]==3) & (df[2]==2) & (df[4]==5)]
%timeit _ = df[df.apply(lambda x: (x[1]==3) & (x[2]==2) & (x[4]==5), axis=1)]
import operator
select_dict = {1:(operator.eq,3), 2:(operator.eq,2), 4:(operator.eq,5)}
%timeit _ = pandas_select(df, select_dict)
私が得る出力は次のとおりです。
In [6]: %timeit _ = df[(df[1]==3) & (df[2]==2) & (df[4]==5)]
100 loops, best of 3: 4.91 ms per loop
In [7]: %timeit _ = df[df.apply(lambda x: (x[1]==3) & (x[2]==2) & (x[4]==5), axis=1)]
1 loops, best of 3: 1.23 s per loop
In [10]: %timeit _ = pandas_select(df, select_dict)
1 loops, best of 3: 1.6 s per loop
reduce
、関数のユーザーoperator
、および関数からの関数オーバーヘッドだけでpandas_select
速度が低下する可能性があることを購入できます。しかし、それは過剰に思えます。関数内では、同じ構文を使用していますが、df[key] logical_op value
はるかに低速です。
apply
また、バージョンaxis=1
が非常に遅い理由にも戸惑っています。それは文字通り構文の短縮であるはずですよね?