2017-01-05 6 views
6

यह सबसे अधिक संभावना है कि कुछ बुनियादी है, लेकिन मैं इसे समझ नहीं सकता। मान लीजिए है कि मैं इस तरह की एक श्रृंखला है:एक पांडस पर लूपिंग के लिए अधिक पाइथोनिक/पांडाइक दृष्टिकोण श्रृंखला

s1 = pd.Series([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]) 

कैसे मैं एक के लिए लूप का इस्तेमाल करने लगी बिना इस श्रृंखला की उप-सीरीज पर कार्रवाई कर सकता है?

मान लीजिए, उदाहरण के लिए, कि मैं इसे एक नई श्रृंखला में बदलना चाहता हूं जिसमें चार तत्व शामिल हैं। इस नई श्रृंखला में पहला तत्व मूल श्रृंखला (1, 1, 1) में पहले तीन तत्वों का योग है, दूसरा दूसरा तीन (2, 2, 2), आदि का योग है .:

s2 = pd.Series([3, 6, 9, 12]) 

मैं यह कैसे कर सकता हूं?

उत्तर

4

आप श्रृंखला एस 1 numpy का उपयोग कर नयी आकृति प्रदान कर सकता है और उसके बाद पंक्तियों पर योग करें:

np.sum(np.array(s1).reshape(len(s1)/3,3), axis = 1) 

जिसमें

array([ 3, 6, 9, 12], dtype=int64) 

संपादित परिणाम:

np.sum(np.array(s1).reshape(-1, 3), axis=1) 
+0

साफ। और मेरे जवाब से तेज़। – IanS

+1

फिर भी आपका उत्तर अधिक मजबूत है क्योंकि यह भी काम करता है अगर एस 1 की लंबाई है जो 3 –

+2

का बहुमत नहीं है, तो लंबाई की गणना करने के बजाय आप इसे गणना करने के लिए numpy भी बता सकते हैं: 'np.sum (np.array (s1)। reshape (-1, 3), अक्ष = 1) ' – MSeifert

2

यह रोलिंग राशि की गणना करता है:

s1.rolling(3).sum() 

आप बस हर तीसरे तत्व का चयन करने की जरूरत है:

s1.rolling(3).sum()[2::3] 

आउटपुट:

2  3.0 
5  6.0 
8  9.0 
11 12.0 
+0

साफ। पहले 2 मूल्य NaN क्यों हैं? – MYGz

+0

पहले 2 मान NaN हैं क्योंकि रोलिंग योग की गणना करने के लिए आपको कम से कम 3 मानों की आवश्यकता है। आप इसे बदल सकते हैं: 's1.rolling (3, min_periods = 1) .sum()'। – IanS

5

यहाँ संभाल करने np.bincount का उपयोग कर एक NumPy दृष्टिकोण है: MSeifert उसकी टिप्पणी में उल्लेख किया है के रूप में, आप भी numpy जैसे लंबाई की गणना कर सकते हैं तत्वों की सामान्य संख्या -

pd.Series(np.bincount(np.arange(s1.size)//3, s1)) 

नमूना रन -

In [42]: s1 = pd.Series([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 9, 5]) 

In [43]: pd.Series(np.bincount(np.arange(s1.size)//3, s1)) 
Out[43]: 
0  3.0 
1  6.0 
2  9.0 
3 12.0 
4 14.0 
dtype: float64 

हम वास्तव में प्रदर्शन के लिए और मामले के लिए जब श्रृंखला की लंबाई खिड़की लंबाई से विभाज्य है तरस रहे हैं, तो हम दृश्य श्रृंखला में s1.values साथ तो प्राप्त कर सकते हैं, reshape एक ही बेंचमार्क डाटासेट साथ

pd.Series(np.einsum('ij->i',s.values.reshape(-1,3))) 

समय के रूप में @Nickil Maveli's post में इस्तेमाल किया - - और अंत में योग के लिए np.einsum उपयोग करते हैं, तो जैसे

In [140]: s = pd.Series(np.repeat(np.arange(10**5), 3)) 

# @Nickil Maveli's soln 
In [141]: %timeit pd.Series(np.add.reduceat(s.values, np.arange(0, s.shape[0], 3))) 
100 loops, best of 3: 2.07 ms per loop 

# Using views+sum 
In [142]: %timeit pd.Series(s.values.reshape(-1,3).sum(1)) 
100 loops, best of 3: 2.03 ms per loop 

# Using views+einsum 
In [143]: %timeit pd.Series(np.einsum('ij->i',s.values.reshape(-1,3))) 
1000 loops, best of 3: 1.04 ms per loop 
5

तुम भी स्लाइस को निर्दिष्ट करके np.add.reduceat इस्तेमाल कर सकते हैं हर 3 तत्व पर कम करने के लिए किया जा और उनके चल रहे योग की गणना:

>>> pd.Series(np.add.reduceat(s1.values, np.arange(0, s1.shape[0], 3))) 
0  3 
1  6 
2  9 
3 12 
dtype: int64 

समय की कमी:

arr = np.repeat(np.arange(10**5), 3) 
s = pd.Series(arr) 
s.shape 
(300000,) 

# @IanS soln 
%timeit s.rolling(3).sum()[2::3]   
100 loops, best of 3: 15.6 ms per loop 

# @Divakar soln 
%timeit pd.Series(np.bincount(np.arange(s.size)//3, s)) 
100 loops, best of 3: 5.44 ms per loop 

# @Nikolas Rieble soln 
%timeit pd.Series(np.sum(np.array(s).reshape(len(s)/3,3), axis = 1)) 
100 loops, best of 3: 2.17 ms per loop 

# @Nikolas Rieble modified soln 
%timeit pd.Series(np.sum(np.array(s).reshape(-1, 3), axis=1)) 
100 loops, best of 3: 2.15 ms per loop 

# @Divakar modified soln 
%timeit pd.Series(s.values.reshape(-1,3).sum(1)) 
1000 loops, best of 3: 1.62 ms per loop 

# Proposed solution in post 
%timeit pd.Series(np.add.reduceat(s.values, np.arange(0, s.shape[0], 3))) 
1000 loops, best of 3: 1.45 ms per loop 
+0

अच्छा! एक समय तुलना करने के लिए यह भी अच्छा होगा ... – MaxU

+1

यह एक ही पैटर्न के बाद श्रृंखला की एक काफी लंबाई के लिए जोड़ा गया है। –

+1

मुझे लगता है कि संक्षेप में एक तेज़ संस्करण दृश्य प्राप्त करेगा: '% timeit pd.Series (s.values.reshape (-1,3) .sum (1))'। – Divakar

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