9

मेरे पास एकाधिक कॉलम के साथ एक पांडा डेटा फ्रेम है। मैं लगातार मूल्यों से एक नया स्तंभ weighted_sum और एक अन्य स्तंभ वेक्टर dataframe weightपांडा में एक पंक्ति में सभी तत्वों के भारित योग की गणना कैसे करें?

weighted_sum निम्नलिखित मान होना चाहिए बनाना चाहते हैं:

row[weighted_sum] = row[col0]*weight[0] + row[col1]*weight[1] + row[col2]*weight[2] + ...

मैं समारोह sum(axis=1) पाया, लेकिन यह 'नहीं करता है मुझे weight के साथ गुणा करने दें।

संपादित करें: मैंने चीजों को थोड़ा सा बदल दिया।

weight इस तरह दिखता है:

 0 
col1 0.5 
col2 0.3 
col3 0.2 

df इस तरह दिखता है:

col1 col2 col3 
1.0 2.2 3.5 
6.1 0.4 1.2 

df*weight एक dataframe Nan मूल्यों से भरा देता है।

+0

क्या आप अपने कुछ 'डेटाफ्रेम' और 'वजन' दिखा सकते हैं? यह स्पष्ट नहीं है कि आपको ऐसा करने में कोई समस्या क्यों है। यदि आप पंक्ति मानों के डॉट उत्पाद को 'भार' के साथ चाहते हैं तो 'ndarray.dot' विधि का उपयोग करें:' row.values.dot (weights.values) '। –

उत्तर

9

समस्या यह है कि आप एक अलग पंक्ति के साथ एक अलग आकार के फ्रेम के साथ एक फ्रेम को गुणा कर रहे हैं।

In [121]: df = DataFrame([[1,2.2,3.5],[6.1,0.4,1.2]], columns=list('abc')) 

In [122]: weight = DataFrame(Series([0.5, 0.3, 0.2], index=list('abc'), name=0)) 

In [123]: df 
Out[123]: 
      a   b   c 
0  1.00  2.20  3.50 
1  6.10  0.40  1.20 

In [124]: weight 
Out[124]: 
      0 
a  0.50 
b  0.30 
c  0.20 

In [125]: df * weight 
Out[125]: 
      0   a   b   c 
0  nan  nan  nan  nan 
1  nan  nan  nan  nan 
a  nan  nan  nan  nan 
b  nan  nan  nan  nan 
c  nan  nan  nan  nan 

आप स्तंभ का उपयोग या तो कर सकते हैं::

In [126]: df * weight[0] 
Out[126]: 
      a   b   c 
0  0.50  0.66  0.70 
1  3.05  0.12  0.24 

In [128]: (df * weight[0]).sum(1) 
Out[128]: 
0   1.86 
1   3.41 
dtype: float64 

या dot का उपयोग वापस पाने के लिए एक और DataFrame

In [127]: df.dot(weight) 
Out[127]: 
      0 
0  1.86 
1  3.41 

एक साथ यह सब लाने के लिए:

In [130]: df['weighted_sum'] = df.dot(weight) 

In [131]: df 
Out[131]: 
      a   b   c weighted_sum 
0  1.00  2.20  3.50   1.86 
1  6.10  0.40  1.20   3.41 
यहाँ समाधान है

एक बड़े DataFrame का उपयोग करके, प्रत्येक विधि के timeit एस यहां दिए गए हैं।

In [145]: df = DataFrame(randn(10000000, 3), columns=list('abc')) 
weight 
In [146]: weight = DataFrame(Series([0.5, 0.3, 0.2], index=list('abc'), name=0)) 

In [147]: timeit df.dot(weight) 
10 loops, best of 3: 57.5 ms per loop 

In [148]: timeit (df * weight[0]).sum(1) 
10 loops, best of 3: 125 ms per loop 

एक विस्तृत DataFrame के लिए:

In [162]: df = DataFrame(randn(10000, 1000)) 

In [163]: weight = DataFrame(randn(1000, 1)) 

In [164]: timeit df.dot(weight) 
100 loops, best of 3: 5.14 ms per loop 

In [165]: timeit (df * weight[0]).sum(1) 
10 loops, best of 3: 41.8 ms per loop 

तो, dot तेजी से और अधिक पठनीय है।

नोट: यदि आपका डेटा के किसी भी NaN रों होते हैं तो आप dot उपयोग नहीं करना चाहिए आप गुणा और योग पद्धति का उपयोग करना चाहिए। dotNaN एस को संभाल नहीं सकता है क्योंकि यह numpy.dot() (जो NaN एस को संभाल नहीं करता है) के आसपास सिर्फ एक पतली आवरण है।

+0

मैं इस गति को बढ़ावा से बहुत आश्चर्यचकित था, लेकिन वास्तव में मुझे यकीन नहीं है कि डॉट एक ही परिणाम उत्पन्न करता है। और 'df.mul (भार) .sum (1) 'वही लगता है (यदि थोड़ा धीमा)। –

+0

'df.dot (weight) '' डेटाफ्रेम' का उत्पादन करेगा यदि 'df' और' weight' दोनों 'डेटाफ्रेम' हैं, तो 'सीरीज़' है या तो 'सीरीज़' है और यदि दोनों 'श्रृंखला' हैं तो स्केलर। संख्यात्मक रूप से, वे बराबर हैं। –

+0

स्पीडअप शायद '*' ऑपरेशन द्वारा बनाए गए अस्थायी की वजह से है। 'dot' को इस तरह के अस्थायी की आवश्यकता नहीं है :) –

6

भार संभालने के बाद प्रत्येक कॉलम के लिए वजन की एक श्रृंखला है तुम सिर्फ गुणा कर सकते हैं और योग करते हैं:

In [11]: df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=['a', 'b', 'c']) 

In [12]: weights = pd.Series([7, 8, 9], index=['a', 'b', 'c']) 

In [13]: (df * weights) 
Out[13]: 
    a b c 
0 7 16 27 
1 28 40 54 

In [14]: (df * weights).sum(1) 
Out[14]: 
0  50 
1 122 
dtype: int64 

इस दृष्टिकोण का लाभ यह कॉलम जो आप वजन नहीं करना चाहते का ख्याल रखता है है :

In [21]: weights = pd.Series([7, 8], index=['a', 'b']) 

In [22]: (df * weights) 
Out[22]: 
    a b c 
0 7 16 NaN 
1 28 40 NaN 

In [23]: (df * weights).sum(1) 
Out[23]: 
0 23 
1 68 
dtype: float64 
संबंधित मुद्दे