python - لماذا هي وظائف numpy بطيئة جدا على سلسلة الباندا / dataframes؟




2 Answers

مجرد قراءة التعليمات البرمجية المصدر ، من الواضح.

def clip(a, a_min, a_max, out=None):
    """a : array_like Array containing elements to clip."""
    return _wrapfunc(a, 'clip', a_min, a_max, out=out)

def _wrapfunc(obj, method, *args, **kwds):
    try:
        return getattr(obj, method)(*args, **kwds)
    #This situation has occurred in the case of
    # a downstream library like 'pandas'.
    except (AttributeError, TypeError):
        return _wrapit(obj, method, *args, **kwds)

def _wrapit(obj, method, *args, **kwds):
    try:
        wrap = obj.__array_wrap__
    except AttributeError:
        wrap = None
    result = getattr(asarray(obj), method)(*args, **kwds)
    if wrap:
        if not isinstance(result, mu.ndarray):
            result = asarray(result)
        result = wrap(result)
    return result

تصحيح:

بعد الباندا v0.13.0_ahl1 ، الباندا لديها التطبيق الخاص بها من clip .

python performance pandas numpy

النظر في MWE الصغيرة ، مأخوذة من سؤال آخر :

DateTime                Data
2017-11-21 18:54:31     1
2017-11-22 02:26:48     2
2017-11-22 10:19:44     3
2017-11-22 15:11:28     6
2017-11-22 23:21:58     7
2017-11-28 14:28:28    28
2017-11-28 14:36:40     0
2017-11-28 14:59:48     1

الهدف هو قص كل القيم ذات الحد الأعلى من 1. يستخدم np.clip ، والتي تعمل بشكل جيد.

np.clip(df.Data, a_min=None, a_max=1)
array([1, 1, 1, 1, 1, 1, 0, 1])

أو،

np.clip(df.Data.values, a_min=None, a_max=1)
array([1, 1, 1, 1, 1, 1, 0, 1])

كلاهما يعيدان نفس الجواب. سؤالي هو حول الأداء النسبي لهاتين الطريقتين. يعتبر -

df = pd.concat([df]*1000).reset_index(drop=True)

%timeit np.clip(df.Data, a_min=None, a_max=1)
1000 loops, best of 3: 270 µs per loop

%timeit np.clip(df.Data.values, a_min=None, a_max=1)
10000 loops, best of 3: 23.4 µs per loop

لماذا يوجد مثل هذا الفرق الهائل بين الاثنين ، فقط من خلال استدعاء values على هذا الأخير؟ بعبارات أخرى...

لماذا هي وظائف numpy بطيئة جدا على كائنات الباندا؟




السبب في اختلاف الأداء هو أن numpy يميل أولاً إلى البحث عن تنفيذ getattr باستخدام getattr بدلاً من فعل الشيء نفسه في الدالات الباهتة عند تمرير كائن الباندا.

انها ليست numpy على كائن الباندا الذي هو بطيء ، في إصدار الباندا.

عندما تفعل

np.clip(pd.Series([1,2,3,4,5]),a_min=None,amax=1)  

يتم استدعاء _wrapfunc :

# Code from source 
def _wrapfunc(obj, method, *args, **kwds):
    try:
        return getattr(obj, method)(*args, **kwds)

بسبب طريقة _wrapfunc ل getattr :

getattr(pd.Series([1,2,3,4,5]),'clip')(None, 1)
# Equivalent to `pd.Series([1,2,3,4,5]).clip(lower=None,upper=1)`
# 0    1
# 1    1
# 2    1
# 3    1
# 4    1
# dtype: int64

إذا ذهبت من خلال تنفيذ الباندا هناك الكثير من العمل قبل الفحص الذي يتم. هذا هو السبب في أن الوظائف التي لديها تنفيذ الباندا من خلال حذر له مثل هذا الاختلاف في السرعة.

ليس فقط كليب ، وظائف مثل cumsum ، cumprod ، reshape ، searchsorted ، transpose وأكثر من ذلك بكثير يستخدم إصدار الباندا منها من numpy عند تمريرها على كائن الباندا.

قد يبدو أن العقدي يقوم بالعمل على تلك الأشياء لكن تحت غطاء محرك السيارة وظيفة الباندا.




Related