2015-11-26 5 views
10

मैं एक पांडा डेटा फ्रेम निम्नलिखित तरीके से बनाई गई है:फास्ट विकल्प पांडा DataFrame में सभी पंक्तियों के ऊपर एक numpy आधारित समारोह को चलाने के लिए

import pandas as pd 
def create(n): 
    df = pd.DataFrame({ 'gene':["foo", 
          "bar", 
          "qux", 
          "woz"], 
          'cell1':[433.96,735.62,483.42,10.33], 
          'cell2':[94.93,2214.38,97.93,1205.30], 
          'cell3':[1500,90,100,80]}) 
    df = df[["gene","cell1","cell2","cell3"]] 
    df = pd.concat([df]*n) 
    df = df.reset_index(drop=True) 
    return df 

यह इस तरह दिखता है: तो फिर

In [108]: create(1) 
Out[108]: 
    gene cell1 cell2 cell3 
0 foo 433.96 94.93 1500 
1 bar 735.62 2214.38  90 
2 qux 483.42 97.93 100 
3 woz 10.33 1205.30  80 

मैं

enter image description here

: एक समारोह है कि एक निश्चित स्कोर की गणना करने के लिए प्रत्येक जीन (पंक्ति) के मूल्यों लेता है 210
import numpy as np 
def sparseness(xvec): 
    n = len(xvec) 
    xvec_sum = np.sum(np.abs(xvec)) 
    xvecsq_sum = np.sum(np.square(xvec)) 

    denom = np.sqrt(n) - (xvec_sum/np.sqrt(xvecsq_sum)) 
    enum = np.sqrt(n) - 1 
    sparseness_x = denom/enum 

    return sparseness_x 

असल में मुझे इस समारोह को पंक्तियों पर 40K पर लागू करने की आवश्यकता है।

In [109]: df = create(10000) 
In [110]: express_df = df.ix[:,1:] 
In [111]: %timeit express_df.apply(sparseness, axis=1) 
1 loops, best of 3: 8.32 s per loop 

कि लागू करने के लिए तेजी से विकल्प क्या है: और वर्तमान में यह बहुत धीमी गति से उपयोग करते हुए पांडा 'लागू करें' चलाता है?

उत्तर

12

फ़ंक्शन के वेक्टरीकृत संस्करण को कार्यान्वित करने का एक तेज़ तरीका है, जो कि दो आयामी एनन्ड्रे पर सीधे चल रहा है। यह बहुत ही कामयाब है क्योंकि numpy में कई फ़ंक्शन दो आयामी ndarray पर संचालित हो सकते हैं, axis पैरामीटर का उपयोग करके नियंत्रित किया जाता है। एक संभव कार्यान्वयन:

def sparseness2(xs): 
    nr = np.sqrt(xs.shape[1]) 
    a = np.sum(np.abs(xs), axis=1) 
    b = np.sqrt(np.sum(np.square(xs), axis=1)) 
    sparseness = (nr - a/b)/(nr - 1) 
    return sparseness 

res_arr = sparseness2(express_df.values) 
res2 = pd.Series(res_arr, index=express_df.index) 

कुछ परीक्षण:

from pandas.util.testing import assert_series_equal 
res1 = express_df.apply(sparseness, axis=1) 
assert_series_equal(res1, res2) #OK 
%timeit sparseness2(express_df.values) 
# 1000 loops, best of 3: 655 µs per loop 
8

यहाँ एक vectorized np.einsum का उपयोग कर पूरे dataframe भर में एक ही बार में उन सभी कार्रवाई करने तरीका है। अब, np.einsum इस तरह के गुणा और संक्षेप उद्देश्यों के लिए माना जाता है। हमारे मामले में, हम xvec_sum मामले और xvecsq_sum मामले के लिए स्क्वायरिंग और सारांश के लिए एक आयाम के साथ संक्षेप में प्रदर्शन करने के लिए इसका उपयोग कर सकते हैं। implmentation इस प्रकार दिखाई देगा -

def sparseness_vectorized(A): 
    nsqrt = np.sqrt(A.shape[1]) 
    B = np.einsum('ij->i',np.abs(A))/np.sqrt(np.einsum('ij,ij->i',A,A))  
    denom = nsqrt - B 
    enum = nsqrt - 1 
    return denom/enum 

रनटाइम परीक्षण -

यह खंड सभी प्रश्न में एक सहित समस्या को हल करने अब तक सूचीबद्ध दृष्टिकोण है।

In [235]: df = create(1000) 
    ...: express_df = df.ix[:,1:] 
    ...: 

In [236]: %timeit express_df.apply(sparseness, axis=1) 
1 loops, best of 3: 1.36 s per loop 

In [237]: %timeit sparseness2(express_df.values) 
1000 loops, best of 3: 247 µs per loop 

In [238]: %timeit sparseness_vectorized(express_df.values) 
1000 loops, best of 3: 231 µs per loop 



In [239]: df = create(5000) 
    ...: express_df = df.ix[:,1:] 
    ...: 

In [240]: %timeit express_df.apply(sparseness, axis=1) 
1 loops, best of 3: 6.66 s per loop 

In [241]: %timeit sparseness2(express_df.values) 
1000 loops, best of 3: 1.14 ms per loop 

In [242]: %timeit sparseness_vectorized(express_df.values) 
1000 loops, best of 3: 1.06 ms per loop 
संबंधित मुद्दे