2012-11-19 6 views
1

팬더에서 SQL select-statement-like 동작을 복제하는 것에 대해 this question을보고 난 후에 에이 질문에 the accepted answer에 주어진 자세한 구문을 단축 할 수있는 두 가지 방법을 보여주었습니다.Python Pandas : 다른 열 선택 방법에서 속도 저하의 원인은 무엇입니까?

그들과 함께 장난 후, 나의이 짧은 구문 방법은 상당히 느리다, 나는

당신은 팬더, IPython에서, 또는 the question and answers linked above에서 중입니다 아래에 사용 된 모든 기능을 가정 할 수있는 이유를 누군가가 설명 할 수 기대하고있다.

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) 

내가 얻을 출력은 다음과 같습니다 내 pandas_select 기능에서 reduce, operator 기능의 사용자, 그냥 함수의 오버 헤드가 느려질 수 있음을 구입하실 수 있습니다

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 

. 그러나 과도한 것처럼 보입니다. 내 함수의 내부에서 동일한 구문 인 df[key] logical_op value을 사용하고 있지만 훨씬 느립니다.

에있는 apply 버전이 너무 느린 이유가 궁금합니다. 말 그대로 구문의 단축 일뿐입니다.

답변

5

df[df.apply(lambda x: (x[1]==3) & (x[2]==2) & (x[4]==5), axis=1)]을 쓸 때, 데이터 프레임의 100000 행마다 람다를 호출합니다. 각 행에 대해 Python 메서드 호출을 실행해야하므로 상당한 오버 헤드가 발생합니다.

df[(df[1]==3) & (df[2]==2) & (df[4]==5)]을 쓸 때 오버 헤드가 없습니다. 그 대신, 연산은 단일 연산으로 각 열에 적용되며, 루프는 벡터화 가능성 (예 : SSE)을 가진 원시 코드로 실행됩니다.

이것은 팬더 만의 것이 아닙니다. 일반적으로 개별 항목에 파이썬 함수 나 내부 루프를 호출하는 대신 집계에서 배열과 행렬을 처리하면 numpy 연산이 훨씬 빨라집니다.

+0

또한 데이터는 각 행에 하나씩 '시리즈'개체로 묶어야합니다. –

관련 문제