पंडों का समूह: स्ट्रिंग्स का एक संघ कैसे प्राप्त करें


122

मेरे पास इस तरह एक डेटाफ्रेम है:

   A         B       C
0  1  0.749065    This
1  2  0.301084      is
2  3  0.463468       a
3  4  0.643961  random
4  1  0.866521  string
5  2  0.120737       !

कॉलिंग

In [10]: print df.groupby("A")["B"].sum()

वापस होगा

A
1    1.615586
2    0.421821
3    0.463468
4    0.643961

अब मैं कॉलम "C" के लिए "वही" करना चाहूंगा। क्योंकि उस कॉलम में स्ट्रिंग्स हैं, योग () काम नहीं करता है (हालांकि आप सोच सकते हैं कि यह स्ट्रिंग्स को समाप्‍त कर देगा)। मैं वास्तव में जो देखना चाहता हूं, वह प्रत्येक समूह के लिए एक सूची या सेट है, अर्थात

A
1    {This, string}
2    {is, !}
3    {a}
4    {random}

मैं ऐसा करने के तरीके खोजने की कोशिश कर रहा हूं।

Series.unique () ( http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.unique.html ) हालांकि काम नहीं करता है

df.groupby("A")["B"]

एक है

pandas.core.groupby.SeriesGroupBy object

इसलिए मुझे उम्मीद थी कि कोई भी श्रृंखला विधि काम करेगी। कोई विचार?

जवाबों:


178
In [4]: df = read_csv(StringIO(data),sep='\s+')

In [5]: df
Out[5]: 
   A         B       C
0  1  0.749065    This
1  2  0.301084      is
2  3  0.463468       a
3  4  0.643961  random
4  1  0.866521  string
5  2  0.120737       !

In [6]: df.dtypes
Out[6]: 
A      int64
B    float64
C     object
dtype: object

जब आप अपना स्वयं का फ़ंक्शन लागू करते हैं, तो गैर-संख्यात्मक कॉलम के स्वचालित बहिष्करण नहीं होते हैं। यह, हालांकि, के आवेदन की तुलना में धीमी .sum()हैgroupby

In [8]: df.groupby('A').apply(lambda x: x.sum())
Out[8]: 
   A         B           C
A                         
1  2  1.615586  Thisstring
2  4  0.421821         is!
3  3  0.463468           a
4  4  0.643961      random

sum डिफ़ॉल्ट रूप से

In [9]: df.groupby('A')['C'].apply(lambda x: x.sum())
Out[9]: 
A
1    Thisstring
2           is!
3             a
4        random
dtype: object

आप जो चाहें बहुत ज्यादा कर सकते हैं

In [11]: df.groupby('A')['C'].apply(lambda x: "{%s}" % ', '.join(x))
Out[11]: 
A
1    {This, string}
2           {is, !}
3               {a}
4          {random}
dtype: object

एक पूरे फ्रेम पर ऐसा करना, एक समय में एक समूह। कुंजी को वापस करना हैSeries

def f(x):
     return Series(dict(A = x['A'].sum(), 
                        B = x['B'].sum(), 
                        C = "{%s}" % ', '.join(x['C'])))

In [14]: df.groupby('A').apply(f)
Out[14]: 
   A         B               C
A                             
1  2  1.615586  {This, string}
2  4  0.421821         {is, !}
3  3  0.463468             {a}
4  4  0.643961        {random}

यह इन कार्रवाईयों को के लिए की जरूरत को हटाने vectorised कर रहे हैं लगता है applyऔर lambdaरों। मैं यह सोचकर यहाँ आया था कि pandasवास्तव में समन क्यों है और समिंग स्ट्रिंग्स पर कोई त्रुटि नहीं है।
नेल्सनगॉन

1
यदि आप तारों को समतल करने और बीच में एक चरित्र जोड़ने की कोशिश कर रहे हैं, तो। मेरे परीक्षण में मैं 5-10 गुना तेज हो रहा था।
डबल्डाउन

70

आप applyसमूहीकृत डेटा के लिए एक मनमाना फ़ंक्शन लागू करने के लिए विधि का उपयोग कर सकते हैं । इसलिए यदि आप एक सेट चाहते हैं, तो आवेदन करें set। यदि आप एक सूची चाहते हैं, तो आवेदन करें list

>>> d
   A       B
0  1    This
1  2      is
2  3       a
3  4  random
4  1  string
5  2       !
>>> d.groupby('A')['B'].apply(list)
A
1    [This, string]
2           [is, !]
3               [a]
4          [random]
dtype: object

यदि आप कुछ और चाहते हैं, तो बस एक फ़ंक्शन लिखें जो आपको चाहिए और फिर applyवह।


ठीक काम कर रहा है, लेकिन कॉलम ए गायब है।
विनेश टीपी

@VineeshTP: कॉलम ए का उपयोग ग्रुपिंग कॉलम के रूप में किया गया था, इसलिए यह सूचकांक में है, जैसा कि आप उदाहरण में देख सकते हैं। आप इसे एक स्तंभ के रूप में उपयोग करके वापस प्राप्त कर सकते हैं .reset_index()
ब्रेनबार

30

आप मानों को संक्षिप्त करने के लिए aggregate(या agg) फ़ंक्शन का उपयोग करने में सक्षम हो सकते हैं। (अनटेड कोड)

df.groupby('A')['B'].agg(lambda col: ''.join(col))

यह सचमुच काम करता है। गजब का। जैसा कि @voithos ने "अप्रयुक्त" का उल्लेख किया है, मैं बहुत आशावादी नहीं था। बिट I ने एग शब्दकोश में एक प्रविष्टि के रूप में अपने संस्करण का परीक्षण किया और यह इरादा के अनुसार काम किया: .agg ({'tp': 'sum', 'BaseWgt': 'max', 'TP_short': lambda col: ',' .join (कर्नल)}) मेरा दिन बनाया
१६

2
यदि आप किसी प्रकार के विभाजक के साथ मिलकर तार को समेटने की कोशिश कर रहे हैं, तो मैंने इसे। 600k + टेक्स्ट स्ट्रिंग्स के डेटासेट के लिए, मुझे 5-10x तेज़ी से समान परिणाम मिले।
डबल्डडाउन

14

आप यह कोशिश कर सकते हैं:

df.groupby('A').agg({'B':'sum','C':'-'.join})

2
समीक्षा से: क्या आप कृपया अपने उत्तर में अधिक स्पष्टीकरण जोड़ सकते हैं?
toti08

1
Groupby को कॉलम 'A' पर लागू किया जाता है और agg फ़ंक्शन के साथ मैं अलग-अलग स्तंभों पर अलग-अलग फ़ंक्शन का उपयोग कर सकता हूं, कॉलम 'C' में तत्वों को योग करें, शब्दों के बीच '-' सम्मिलित करते हुए कॉलम 'C' में तत्वों को
मिलाएं

8

एक सरल समाधान होगा:

>>> df.groupby(['A','B']).c.unique().reset_index()

यह सही उत्तर होना चाहिए। तुम साफ जवाब देता है। आपका बहुत बहुत धन्यवाद!
imsrgadich

अगर किसी को सूची की सामग्री को एक स्ट्रिंग में शामिल करने में दिलचस्पी है df.groupby(['A','B']).c.unique().apply(lambda x: ';'.join(x)).reset_index()
विवेक-अनंत

8

जिसका नाम एकत्रीकरण है pandas >= 0.25.0

पांडा संस्करण 0.25.0 के बाद से हमने एकत्रीकरण को नाम दिया है जहां हम समूह बना सकते हैं, एकत्र कर सकते हैं और उसी समय हमारे कॉलम में नए नाम निर्दिष्ट कर सकते हैं। इस तरह से हमें MultiIndex कॉलम नहीं मिलेंगे, और कॉलम के नाम उनके द्वारा दिए गए डेटा को अधिक अर्थ देते हैं:


एकत्रित करें और तार की एक सूची प्राप्त करें

grp = df.groupby('A').agg(B_sum=('B','sum'),
                          C=('C', list)).reset_index()

print(grp)
   A     B_sum               C
0  1  1.615586  [This, string]
1  2  0.421821         [is, !]
2  3  0.463468             [a]
3  4  0.643961        [random]

समग्र और तार में शामिल हों

grp = df.groupby('A').agg(B_sum=('B','sum'),
                          C=('C', ', '.join)).reset_index()

print(grp)
   A     B_sum             C
0  1  1.615586  This, string
1  2  0.421821         is, !
2  3  0.463468             a
3  4  0.643961        random

6

यदि आप डेटाफ़्रेम में स्तंभ B को अधिलेखित करना चाहते हैं, तो यह काम करना चाहिए:

    df = df.groupby('A',as_index=False).agg(lambda x:'\n'.join(x))

2

@ इरफान के अच्छे जवाब के बाद, कुल मूल्यों के विश्लेषण में अधिकांश बार आप इन मौजूदा चरित्र मूल्यों के अद्वितीय संभव संयोजन चाहते हैं:

unique_chars = lambda x: ', '.join(x.unique())
(df
 .groupby(['A'])
 .agg({'C': unique_chars}))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.