पंडों के समूह में संचयी योग


97

मैं अपने पंडों के डेटाफ्रेम में एक संचयी योग कॉलम जोड़ना चाहूंगा ताकि:

name | day       | no
-----|-----------|----
Jack | Monday    | 10
Jack | Tuesday   | 20
Jack | Tuesday   | 10
Jack | Wednesday | 50
Jill | Monday    | 40
Jill | Wednesday | 110

हो जाता है:

Jack | Monday     | 10  | 10
Jack | Tuesday    | 30  | 40
Jack | Wednesday  | 50  | 90
Jill | Monday     | 40  | 40
Jill | Wednesday  | 110 | 150

मैं df.groupbyऔर df.agg(lambda x: cumsum(x))कोई फायदा नहीं हुआ के विभिन्न combos की कोशिश की ।


क्या आप वाकई सप्ताह के दिनों में एकत्रीकरण चाहते हैं? यह सूचकांक खो देता है, और संचयी योग भी कम समझ में आता है अगर कई सप्ताह हैं। Dmitry-andreev और @vjayky द्वारा दिए गए उत्तर, प्रत्येक नाम के बदले दिनों के अनुक्रम में कमसुम की गणना करते हैं। यह सोचें कि यदि एक तिथि स्तंभ भी होता है, तो इसे कैसे बढ़ाया जा सकता है, ताकि प्रविष्टियों को समूहीकरण और एकत्रीकरण से पहले हल किया जा सके।
एलियास हसले

जवाबों:


93

इसे groupby()दो बार करना चाहिए :

df.groupby(['name', 'day']).sum() \
  .groupby(level=0).cumsum().reset_index()

स्पष्टीकरण:

print(df)
   name        day   no
0  Jack     Monday   10
1  Jack    Tuesday   20
2  Jack    Tuesday   10
3  Jack  Wednesday   50
4  Jill     Monday   40
5  Jill  Wednesday  110

# sum per name/day
print( df.groupby(['name', 'day']).sum() )
                 no
name day           
Jack Monday      10
     Tuesday     30
     Wednesday   50
Jill Monday      40
      Wednesday  110

# cumulative sum per name/day
print( df.groupby(['name', 'day']).sum() \
         .groupby(level=0).cumsum() )
                 no
name day           
Jack Monday      10
     Tuesday     40
     Wednesday   90
Jill Monday      40
     Wednesday  150

पहले योग से उत्पन्न डेटाफ्रेम अनुक्रमित 'name'और इसके द्वारा होता है 'day'। आप इसे प्रिंट करके देख सकते हैं

df.groupby(['name', 'day']).sum().index 

संचयी योग की गणना करते समय, आप 'name'पहले सूचकांक (स्तर 0) के अनुरूप ऐसा करना चाहते हैं ।

अंत में, reset_indexदोहराया जाने वाले नामों का उपयोग करें।

df.groupby(['name', 'day']).sum().groupby(level=0).cumsum().reset_index()

   name        day   no
0  Jack     Monday   10
1  Jack    Tuesday   40
2  Jack  Wednesday   90
3  Jill     Monday   40
4  Jill  Wednesday  150

3
जवाब के लिए धन्यवाद। हालांकि मेरे कुछ सवाल थे: 1. क्या आप बता सकते हैं कि 'स्तर = [0] का क्या मतलब है? 2. इसके अलावा, जैसा कि आप देख सकते हैं, पहले आपके डेटा फ्रेम में पंक्ति संख्याएं थीं और एक बार जब आप संचयी योग करते हैं तो ये पंक्ति संख्याएं चली जाती हैं। वहाँ उन्हें वापस करने के लिए एक रास्ता है?
user3694373

5
1), इंडेक्स नंबर को जाना है, क्योंकि कम्स कई पंक्तियों से हैं, जैसे कि 2 नंबर, 40, 10 + 20 + 10 है, इसे किस इंडेक्स वैल्यू को प्राप्त करना चाहिए? 1, 2 या 3? तो, चलिए उपयोग करते हैं nameऔर dayजैसे multiIndex, जो बेहतर समझ में आता है ( सूचकांक reset_index()प्राप्त करने के लिए int, यदि वांछित है)। 2), level=[0]इसका मतलब कॉलम groupbyके 1 स्तर से संचालित होता है । MultiIndexname
सीटी झू

धन्यवाद सीटी। मैं समझ गया था कि बाद में और रीसेट () मेरी समस्या को हल करने की कोशिश की। विस्तृत विवरण के लिए धन्यवाद!
user3694373

4
एक सूक्ष्म बग है: groupby()कुंजियों को छांटने के लिए पहला चूक, इसलिए यदि आप इनपुट डेटासेट के निचले भाग में जैक-गुरुवार की पंक्ति जोड़ते हैं तो आपको अप्रत्याशित परिणाम मिलेंगे। और चूंकि groupby()मैं स्तर के नामों के साथ काम कर सकता हूं इसलिए मुझे df.groupby(['name', 'day'], sort=False).sum().groupby(by='name').cumsum().reset_index()कम गूढ़ लगता है ।
निकोले

आप कॉलम का नाम कैसे बदल सकते हैं?
जोनाथन लैम

48

यह पांडा 0.16.2 में काम करता है

In[23]: print df
        name          day   no
0      Jack       Monday    10
1      Jack      Tuesday    20
2      Jack      Tuesday    10
3      Jack    Wednesday    50
4      Jill       Monday    40
5      Jill    Wednesday   110
In[24]: df['no_cumulative'] = df.groupby(['name'])['no'].apply(lambda x: x.cumsum())
In[25]: print df
        name          day   no  no_cumulative
0      Jack       Monday    10             10
1      Jack      Tuesday    20             30
2      Jack      Tuesday    10             40
3      Jack    Wednesday    50             90
4      Jill       Monday    40             40
5      Jill    Wednesday   110            150

यह दिखाना कि इसे df में वापस कैसे जोड़ा जाए, वास्तव में मददगार है। मैंने एक परिवर्तन का उपयोग करने की कोशिश की, लेकिन वह अच्छी तरह से कम्सुम () के साथ नहीं खेला।
ज़ीरोवेक्टर

2
ध्यान दें कि यह उत्तर ( @vjayky द्वारा सरल समाधान के बराबर लगता है ) संचयी राशि की गणना करने से पहले nameऔर बाद में एकत्र नहीं करता dayहै name(नोट: परिणाम में जैक + मंगलवार के लिए 2 पंक्तियाँ हैं)। यह वही है जो सीटी झू के उत्तर की तुलना में सरल बनाता है ।
निकोले

44

@ दिमित्री के जवाब में संशोधन। यह सरल है और पांडा 0.19.0 में काम करता है:

print(df) 

 name        day   no
0  Jack     Monday   10
1  Jack    Tuesday   20
2  Jack    Tuesday   10
3  Jack  Wednesday   50
4  Jill     Monday   40
5  Jill  Wednesday  110

df['no_csum'] = df.groupby(['name'])['no'].cumsum()

print(df)
   name        day   no  no_csum
0  Jack     Monday   10       10
1  Jack    Tuesday   20       30
2  Jack    Tuesday   10       40
3  Jack  Wednesday   50       90
4  Jill     Monday   40       40
5  Jill  Wednesday  110      150

2
यह सबसे सरल समाधान प्रतीत होता है यदि आपको प्रश्न में अनुरोध किए गए दो-चरण एकत्रीकरण की आवश्यकता नहीं है
निकोले

एकमात्र हिस्सा जो मुझे विशेष रूप से पसंद नहीं है वह यह है कि इसने मेरे int dtype को एक फ्लोट में बदल दिया।
क्रिस फर्र

यह समूह भाग में कम्सम के लिए स्वीकृत उत्तर होना चाहिए। @ क्रिस। यह पंडों 1.0.3 के रूप में मेरे लिए अब फ्लोट करने के लिए परिवर्तित करने के लिए प्रतीत नहीं होता है।
लुइस यांग

8

आपको उपयोग करना चाहिए

df['cum_no'] = df.no.cumsum()

http://pandas.pydata.org/pandas-docs/version/0.19.2/generated/pandas.DataFrame.cumsum.html

इसे करने का दूसरा तरीका

import pandas as pd
df = pd.DataFrame({'C1' : ['a','a','a','b','b'],
           'C2' : [1,2,3,4,5]})
df['cumsum'] = df.groupby(by=['C1'])['C2'].transform(lambda x: x.cumsum())
df

यहां छवि विवरण दर्ज करें


3
यह प्रत्येक समूह के लिए अलग-अलग राशि के बजाय एक वैश्विक चल रहे कुल की गणना करता है। तो जिल-मंडे को 130 का मान दिया जाता है ( 90, सभी जैक के मूल्यों के योग के रूप में, + 40, जिल-मंडे के लिए मूल्य)।
निकोले

@ निकोले ने सिर्फ एक और जवाब जोड़ा, मुझे पता है कि अगर यह काम करता है
सुष्मिता

मुझे यकीन नहीं है कि अगर यह मेरे उदाहरण पंक्ति 3 के अनुसार वैश्विक चल रहे कुल की गणना करता है तो 4 का मान मिलता है
सुष्मिता

मैं pandas.series.cumsum () के बजाय यहाँ लैम्ब्डा x: x.cumsum () का उपयोग क्यों करूँ?
जिंहुआ वांग

7

इसके बजाय df.groupby(by=['name','day']).sum().groupby(level=[0]).cumsum() (ऊपर देखें) आप ए भी कर सकते थेdf.set_index(['name', 'day']).groupby(level=0, as_index=False).cumsum()

  • df.groupby(by=['name','day']).sum() वास्तव में सिर्फ दोनों कॉलम को एक मल्टीआईंडेक्स में ले जा रहा है
  • as_index=False इसका मतलब है कि आपको बाद में reset_index पर कॉल करने की आवश्यकता नहीं है

इसे पोस्ट करने के लिए धन्यवाद, इससे मुझे यह समझने में मदद मिली कि यहाँ क्या हो रहा है! ध्यान दें कि groupby().sum()है नहीं बस MultiIndex के दोनों स्तंभ चलती - यह भी जैक + मंगलवार को दो मूल्यों का सार। और as_index=Falseइस मामले में कोई प्रभाव नहीं पड़ता है, क्योंकि सूचकांक पहले से ही निर्धारित किया गया था groupby। और चूंकि groupby().cumsum()डेटा फ्रेम के कॉलम से नाम / दिन को nukes करता है, इसलिए आपको परिणामी संख्यात्मक कॉलम को मूल डेटा फ्रेम (जैसे vjayky और दिमित्री द्वारा सुझाए गए) में जोड़ना होगा, या नाम / दिन को इंडेक्स में स्थानांतरित करना होगा, और बाद में रीसेट करना होगा।
निकोलय

0

data.csv:

name,day,no
Jack,Monday,10
Jack,Tuesday,20
Jack,Tuesday,10
Jack,Wednesday,50
Jill,Monday,40
Jill,Wednesday,110

कोड:

import numpy as np
import pandas as pd

df = pd.read_csv('data.csv')
print(df)
df = df.groupby(['name', 'day'])['no'].sum().reset_index()
print(df)
df['cumsum'] = df.groupby(['name'])['no'].apply(lambda x: x.cumsum())
print(df)

आउटपुट:

   name        day   no
0  Jack     Monday   10
1  Jack    Tuesday   20
2  Jack    Tuesday   10
3  Jack  Wednesday   50
4  Jill     Monday   40
5  Jill  Wednesday  110
   name        day   no
0  Jack     Monday   10
1  Jack    Tuesday   30
2  Jack  Wednesday   50
3  Jill     Monday   40
4  Jill  Wednesday  110
   name        day   no  cumsum
0  Jack     Monday   10      10
1  Jack    Tuesday   30      40
2  Jack  Wednesday   50      90
3  Jill     Monday   40      40
4  Jill  Wednesday  110     150
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.