2013-03-13 5 views
18

पर फ़ंक्शन लागू करें मेरे पास my_labels नामक कॉलम के साथ एक पांडा डेटाफ्रेम है जिसमें स्ट्रिंग्स: 'A', 'B', 'C', 'D', 'E' शामिल हैं। मैं इन तारों में से प्रत्येक की घटनाओं की संख्या को गिनना चाहता हूं, फिर सभी गिनती के योग से गणना की संख्या विभाजित करें। मैं इस तरह पांडा में यह करने के लिए कोशिश कर रहा हूँ:पांडा समूहby

func = lambda x: x.size()/x.sum() 
data = frame.groupby('my_labels').apply(func) 

इस कोड को एक त्रुटि फेंकता है, आकार '' DataFrame वस्तु कोई गुण नहीं है '। पांडों में इसकी गणना करने के लिए मैं एक फ़ंक्शन कैसे लागू कर सकता हूं?

उत्तर

21

applyप्रत्येक मान पर लागू करने के लिए एक फ़ंक्शन लेता है, श्रृंखला नहीं, और kwargs स्वीकार करता है। तो, मानों में .size() विधि नहीं है।

शायद यह काम करेगा:

from pandas import * 

d = {"my_label": Series(['A','B','A','C','D','D','E'])} 
df = DataFrame(d) 


def as_perc(value, total): 
    return value/float(total) 

def get_count(values): 
    return len(values) 

grouped_count = df.groupby("my_label").my_label.agg(get_count) 
data = grouped_count.apply(as_perc, total=df.my_label.count()) 

यहाँ .agg() विधि एक समारोह है कि groupby object की सभी मूल्यों के लिए लागू किया जाता है लेता है।

6

प्रयास करें:

g = pd.DataFrame(['A','B','A','C','D','D','E']) 

# Group by the contents of column 0 
gg = g.groupby(0) 

# Create a DataFrame with the counts of each letter 
histo = gg.apply(lambda x: x.count()) 

# Add a new column that is the count/total number of elements  
histo[1] = histo.astype(np.float)/len(g) 

print histo 

आउटपुट:

0   1 
0    
A 2 0.285714 
B 1 0.142857 
C 1 0.142857 
D 2 0.285714 
E 1 0.142857 
+1

तुम भी उपयोग कर सकते हैं 'histo = gg.size()' सादगी के लिए काफी तेजी से होता है – Reservedegotist

1

मैं S.O. पर एक भारित औसत की गणना के लिए एक नेस्टेड समारोह तकनीक देखा एक बार, उस तकनीक को बदलने से आपकी समस्या हल हो सकती है।

def group_weight(overall_size): 
    def inner(group): 
     return len(group)/float(overall_size) 
    inner.__name__ = 'weight' 
    return inner 

d = {"my_label": pd.Series(['A','B','A','C','D','D','E'])} 
df = pd.DataFrame(d) 
print df.groupby('my_label').apply(group_weight(len(df))) 



my_label 
A 0.285714 
B 0.142857 
C 0.142857 
D 0.285714 
E 0.142857 
dtype: float64 

यहाँ कैसे समूहों के भीतर एक भारित औसत करने के लिए

def wavg(val_col_name,wt_col_name): 
    def inner(group): 
     return (group[val_col_name] * group[wt_col_name]).sum()/group[wt_col_name].sum() 
    inner.__name__ = 'wgt_avg' 
    return inner 



d = {"P": pd.Series(['A','B','A','C','D','D','E']) 
    ,"Q": pd.Series([1,2,3,4,5,6,7]) 
    ,"R": pd.Series([0.1,0.2,0.3,0.4,0.5,0.6,0.7]) 
    } 

df = pd.DataFrame(d) 
print df.groupby('P').apply(wavg('Q','R')) 

P 
A 2.500000 
B 2.000000 
C 4.000000 
D 5.545455 
E 7.000000 
dtype: float64 
0

Starting with Pandas version 0.22, वहाँ भी apply के लिए एक विकल्प मौजूद है: pipe है, जो काफी तेज apply का उपयोग करने से हो सकता है (आप भी this question जाँच कर सकते हैं दो कार्यक्षमताओं के बीच अधिक अंतर के लिए)।

अपने उदाहरण के लिए

:

df = pd.DataFrame({"my_label": ['A','B','A','C','D','D','E']}) 

    my_label 
0  A 
1  B 
2  A 
3  C 
4  D 
5  D 
6  E 

apply संस्करण

df.groupby('my_label').apply(lambda grp: grp.count()/df.shape[0]) 

देता

  my_label 
my_label   
A   0.285714 
B   0.142857 
C   0.142857 
D   0.285714 
E   0.142857 

और pipe संस्करण

df.groupby('my_label').pipe(lambda grp: grp.size()/grp.size().sum()) 

पैदावार

my_label 
A 0.285714 
B 0.142857 
C 0.142857 
D 0.285714 
E 0.142857 

तो मान रहे हैं समान है, तथापि, समय काफी एक बहुत अलग (कम से कम इस छोटे से dataframe के लिए):

%timeit df.groupby('my_label').apply(lambda grp: grp.count()/df.shape[0]) 
100 loops, best of 3: 5.52 ms per loop 

और

%timeit df.groupby('my_label').pipe(lambda grp: grp.size()/grp.size().sum()) 
1000 loops, best of 3: 843 µs per loop 

इसे एक फ़ंक्शन में लपेटना तब भी सरल होता है:

def get_perc(grp_obj): 
    gr_size = grp_obj.size() 
    return gr_size/gr_size.sum() 

अब आप

df.groupby('my_label').pipe(get_perc) 

my_label 
A 0.285714 
B 0.142857 
C 0.142857 
D 0.285714 
E 0.142857 

उपज हालांकि, इस विशेष मामले के लिए, आप भी एक groupby की जरूरत नहीं है कॉल कर सकते हैं, लेकिन आप सिर्फ इस तरह value_counts उपयोग कर सकते हैं:

df['my_label'].value_counts(sort=False)/df.shape[0] 

उपज
A 0.285714 
C 0.142857 
B 0.142857 
E 0.142857 
D 0.285714 
Name: my_label, dtype: float64 

इस छोटे से dataframe के लिए यह

%timeit df['my_label'].value_counts(sort=False)/df.shape[0] 
1000 loops, best of 3: 770 µs per loop