2016-05-02 7 views
7

को अनदेखा कर दिया है मेरे पास एक पांडा डेटाफ्रेम है और मैं कॉलम के रोलिंग माध्य (ग्रुपबी क्लॉज के बाद) की गणना करना चाहता हूं। हालांकि, मैं NaN को बाहर करना चाहता हूं।पांडा ग्रुपबी और रोलिंग_प्ली ने नाएन

उदाहरण के लिए, यदि समूहबी [2, NaN, 1] लौटाता है, तो परिणाम 1.5 होना चाहिए जबकि वर्तमान में यह NaN लौटाता है।

मैं निम्नलिखित लेकिन यह काम करने के लिए प्रतीत नहीं होता है की कोशिश की है:

df.groupby(by=['var1'])['value'].apply(pd.rolling_apply, 3, lambda x: np.mean([i for i in x if i is not np.nan and i!='NaN'])) 

अगर मैं भी इस प्रयास करें:

df.groupby(by=['var1'])['value'].apply(pd.rolling_apply, 3, lambda x: 1) 

मैं उत्पादन में NaN हो रही है तो यह चाहिए पृष्ठभूमि में पांडा कैसे काम करता है इसके साथ कुछ करने के लिए हो।

कोई विचार?

संपादित करें:

: जब मैं निम्नलिखित करना चाहते थे

0 NaN 
1 NaN 
2 2.0 
3 NaN 
4 2.5 
5 NaN 
6 3.0 
7 2.0 

:

import pandas as pd 
import numpy as np 

df = pd.DataFrame({'var1' : ['a', 'b', 'a', 'b', 'a', 'b', 'a', 'b'], 'value' : [1, 2, 3, np.nan, 2, 3, 4, 1] }) 
print df.groupby(by=['var1'])['value'].apply(pd.rolling_apply, 2, lambda x: np.mean([i for i in x if i is not np.nan and i!='NaN'])) 

परिणाम है: यहाँ मैं क्या कर रहा हूँ के साथ एक कोड नमूना है

0 NaN 
1 NaN 
2 2.0 
3 2.0 
4 2.5 
5 3.0 
6 3.0 
7 2.0 
+1

कृपया कोड का एक छोटा पुन: उत्पादित सेट प्रदान करें, जैसे कि मैं इसे स्वयं बनाये बिना समान जानकारी के साथ खेल सकता हूं। – piRSquared

+0

@piRSquared मैंने अभी एक कोड नमूना जोड़ा है। धन्यवाद – Stergios

उत्तर

1

क्या यह परिणाम आपकी उम्मीदों से मेल खाता है? मैंने थोड़ा सा min_periods पैरामीटर के साथ अपना समाधान बदल दिया और नैन के लिए सही फ़िल्टर किया।

In [164]: df.groupby(by=['var1'])['value'].apply(pd.rolling_apply, 2, lambda x: np.mean([i for i in x if not np.isnan(i)]), min_periods=1) 
Out[164]: 
0 1.0 
1 2.0 
2 2.0 
3 2.0 
4 2.5 
5 3.0 
6 3.0 
7 2.0 
dtype: float64 
+0

यह 'min_period' का चालाक उपयोग है! – IanS

1

यहाँ सूची समझ के बिना एक विकल्प के कार्यान्वयन है, लेकिन यह भी (यानी apply परहेज vectorized तरीकों के लिए चिपके हुए पांडा में हमेशा की तरह np.nan

means = df.groupby('var1')['value'].apply(
    lambda gp: gp.rolling(2, min_periods=1).apply(np.nanmean)) 
8

साथ उत्पादन की पहली प्रविष्टि को भरने के लिए विफल रहता है,) प्रदर्शन और मापनीयता के लिए आवश्यक है।

ऑपरेशन जो आप करना चाहते हैं वह थोड़ा सा है क्योंकि ग्रुपबी ऑब्जेक्ट्स पर रोलिंग ऑपरेशंस वर्तमान में (संस्करण 0.18.1) नहीं हैं। जैसे, हम कोड के कुछ ही लाइनों की आवश्यकता होगी:

g1 = df.groupby(['var1'])['value']    # group values 
g2 = df.fillna(0).groupby(['var1'])['value'] # fillna, then group values 

s = g2.rolling(2).sum()/g1.rolling(2).count() # the actual computation 

s.reset_index(level=0, drop=True).sort_index() # drop/sort index 

विचार विंडो में मानों का योग करने (sum का प्रयोग करके), NaN मूल्यों (count का प्रयोग करके) गिनती और उसके बाद है खोजने के लिए विभाजित मतलब है। इस कोड को निम्नलिखित उत्पादन जो आपके इच्छित उत्पादन से मेल खाता है देता है:

0 NaN 
1 NaN 
2 2.0 
3 2.0 
4 2.5 
5 3.0 
6 3.0 
7 2.0 
Name: value, dtype: float64 

परीक्षण यह एक बड़ा DataFrame पर (100,000 पंक्तियों के आसपास), रन-टाइम 100ms के तहत तेजी से किसी भी लागू आधारित विधियों मैंने कोशिश की तुलना में था, काफी।

आपके वास्तविक डेटा पर विभिन्न दृष्टिकोणों का परीक्षण करने लायक हो सकता है क्योंकि समय अन्य कारकों जैसे समूहों की संख्या से प्रभावित हो सकता है। यह काफी निश्चित है कि वेक्टरकृत कंप्यूटेशंस जीतेंगे, यद्यपि।


ऊपर दिखाया गया दृष्टिकोण सरल गणनाओं के लिए अच्छी तरह से काम करता है, जैसे रोलिंग माध्य।यह अधिक जटिल गणनाओं (जैसे मानक विचलन रोलिंग) के लिए काम करेगा, हालांकि कार्यान्वयन अधिक शामिल है।

सामान्य विचार प्रत्येक सरल दिनचर्या को देखता है जो पांडा में तेज़ है (उदा। sum) और फिर किसी पहचान तत्व (उदा। 0) के साथ किसी भी शून्य मान को भरें। फिर आप groubpy का उपयोग कर सकते हैं और रोलिंग ऑपरेशन कर सकते हैं (उदा। .rolling(2).sum())। आउटपुट को फिर अन्य परिचालनों के आउटपुट (ओं) के साथ जोड़ा जाता है।

उदाहरण के लिए, GroupBy NaN अवगत रोलिंग विचरण (जो के मानक विचलन वर्ग जड़ है) को लागू करने की हम पाते हैं चाहिए "वर्ग शून्य से मतलब के वर्ग के मतलब है"।

def rolling_nanvar(df, window): 
    """ 
    Group df by 'var1' values and then calculate rolling variance, 
    adjusting for the number of NaN values in the window. 

    Note: user may wish to edit this function to control degrees of 
    freedom (n), depending on their overall aim. 
    """ 
    g1 = df.groupby(['var1'])['value'] 
    g2 = df.fillna(0).groupby(['var1'])['value'] 
    # fill missing values with 0, square values and groupby 
    g3 = df['value'].fillna(0).pow(2).groupby(df['var1']) 

    n = g1.rolling(window).count() 

    mean_of_squares = g3.rolling(window).sum()/n 
    square_of_mean = (g2.rolling(window).sum()/n)**2 
    variance = mean_of_squares - square_of_mean 
    return variance.reset_index(level=0, drop=True).sort_index() 

नोट (squaring अतिप्रवाह करने के लिए ले जा सकता है) है कि इस समारोह संख्यानुसार स्थिर नहीं हो सकता है: यहाँ क्या ऐसा दिखाई दे सकता का चित्र है। पांडा इस मुद्दे को कम करने के लिए आंतरिक रूप से Welford's algorithm का उपयोग करता है।

वैसे भी, यह फ़ंक्शन, हालांकि यह कई संचालन का उपयोग करता है, अभी भी बहुत तेज़ है। यहाँ अधिक संक्षिप्त लागू आधारित पद्धति Yakym Pirozhenko ने सुझाव दिया साथ तुलना की गई है:

>>> df2 = pd.concat([df]*10000, ignore_index=True) # 80000 rows 
>>> %timeit df2.groupby('var1')['value'].apply(\ 
     lambda gp: gp.rolling(7, min_periods=1).apply(np.nanvar)) 
1 loops, best of 3: 11 s per loop 

>>> %timeit rolling_nanvar(df2, 7) 
10 loops, best of 3: 110 ms per loop 

vectorization इस मामले में 100 गुना तेज है। बेशक, आपके पास कितना डेटा है, इस पर निर्भर करता है कि आप apply का उपयोग करने के लिए चिपकना चाहेंगे क्योंकि यह आपको प्रदर्शन की कीमत पर सामान्यता/अल्पसंख्यक की अनुमति देता है।

+0

ध्यान दें कि यह 'रोलिंग' विधि का उपयोग करता है, जो केवल पांडा 18 में उपलब्ध है, जबकि ओपी 'pd.rolling_apply' का उपयोग करता है, इसलिए संभवतः पांडा 17 या उससे कम स्थापित होता है। – IanS

+0

@ajcr यह मेरी वर्तमान समस्या हल करता है लेकिन अगर मैं माध्य के अलावा अन्य कार्यों को लागू करना चाहता हूं (उदाहरण के लिए रोलिंग मानक विचलन)। क्या यह अन्य कार्यों के लिए भी काम करने का कोई तरीका है? – Stergios

+0

@ स्टेरिजियोस: मैं समस्या को और अधिक विचार दूंगा और आज/कल के बाद इस उत्तर में कुछ और दिशानिर्देश/सुझाव जोड़ूंगा। यह निश्चित रूप से सच है कि 'लागू' का उपयोग करना कभी-कभी सबसे सुविधाजनक विकल्प होता है और सबसे सामान्य समाधान प्रदान करता है (सभी कार्यों को त्वरित पांडा दिनचर्या के साथ नकल करना आसान नहीं होता है)। –

संबंधित मुद्दे