2016-03-28 10 views
6

के आधार पर लगभग डुप्लिकेट पंक्तियां मर्ज करें मेरे पास pandas डेटाफ्रेम है जो कई पंक्तियों के साथ एक दूसरे के डुप्लिकेट के पास है, एक मान को छोड़कर। मेरा लक्ष्य संख्यात्मक मानों को संक्षेप किए बिना, इन पंक्तियों को एक पंक्ति में विलय करना या "सहवास" करना है।पांडा - कॉलम मान

यहाँ है कि मैं क्या साथ काम कर रहा हूँ का एक उदाहरण है:

Name Sid Use_Case   Revenue 
A  xx01 Voice, SMS   $10.00 
B  xx02 Voice    $5.00 
C  xx03 Voice, SMS, Video $15.00 

कारण मैं "राजस्व योग करने के लिए नहीं करना चाहती:

Name Sid Use_Case Revenue 
A  xx01 Voice  $10.00 
A  xx01 SMS  $10.00 
B  xx02 Voice  $5.00 
C  xx03 Voice  $15.00 
C  xx03 SMS  $15.00 
C  xx03 Video  $15.00 

और यहाँ मैं क्या चाहते हैं "कॉलम इसलिए है क्योंकि मेरी तालिका कई समय अवधि में एक पिवट करने का परिणाम है जहां" राजस्व "बस" Use_Case "प्रति अलग मूल्य रखने के बजाय कई बार सूचीबद्ध हो जाता है।

इस मुद्दे से निपटने का सबसे अच्छा तरीका क्या होगा? मैंने groupby() फ़ंक्शन में देखा है लेकिन मुझे अभी भी यह बहुत अच्छी तरह से समझ में नहीं आया है।

+0

यदि मेरा या अमी का उत्तर सहायक था, तो [स्वीकार करें] (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) को मत भूलना। धन्यवाद। – jezrael

+0

धन्यवाद! वे दोनों अच्छी तरह से काम करते हैं। मुझे कुछ कॉलम मर्ज करना पड़ सकता है क्योंकि मेरा वास्तविक डेटासेट 4 प्रदान किए गए मुकाबले से काफी व्यापक है, लेकिन यह चाल –

उत्तर

5

मुझे लगता है कि आप aggregatefirst और कस्टम समारोह ', '.join साथ groupby उपयोग कर सकते हैं:

df = df.groupby('Name').agg({'Sid':'first', 
          'Use_Case': ', '.join, 
          'Revenue':'first' }).reset_index() 

#change column order       
print df[['Name','Sid','Use_Case','Revenue']]        
    Name Sid   Use_Case Revenue 
0 A xx01   Voice, SMS $10.00 
1 B xx02    Voice $5.00 
2 C xx03 Voice, SMS, Video $15.00 

टिप्पणी से अच्छा विचार है, धन्यवाद Goyo:

df = df.groupby(['Name','Sid','Revenue'])['Use_Case'].apply(', '.join).reset_index() 

#change column order       
print df[['Name','Sid','Use_Case','Revenue']]        
    Name Sid   Use_Case Revenue 
0 A xx01   Voice, SMS $10.00 
1 B xx02    Voice $5.00 
2 C xx03 Voice, SMS, Video $15.00 
+1

करना चाहिए, मैं बस 'Use_Case' 'को छोड़कर सबकुछ द्वारा समूहित करूँगा। साथ ही कुल कार्य केवल '', '.join' हो सकता है,' lambda' का उपयोग करने की कोई आवश्यकता नहीं है .. – Goyo

+0

यदि आपके कॉलम में 'join' पसंद नहीं है तो इस ब्रेक को बाहर कर देता है। इसे साफ करने के लिए 'लागू' से पहले मुझे '.map (str)' फेंकना पड़ा। –

+1

हां, या '.astype (str)' का उपयोग करें, यह स्ट्रिंग के लिए कलाकार के लिए कार्य है। – jezrael

1

आप कर सकते हैं groupby और applylist समारोह:

>>> df['Use_Case'].groupby([df.Name, df.Sid, df.Revenue]).apply(list).reset_index() 
    Name Sid  Revenue  0 
0 A xx01 $10.00 [Voice, SMS] 
1 B xx02 $5.00 [Voice] 
2 C xx03 $15.00 [Voice, SMS, Video] 

(मामले में आप डुप्लिकेट के बारे में चिंतित हैं, list के बजाय set का उपयोग करें।)

1

मैं कुछ कोड मुझे नहीं लगता था कि इष्टतम था और अंत में jezrael's answer पाया उपयोग कर रहा था। लेकिन इसे का उपयोग और एक timeit परीक्षण चलाने के बाद, मैं वास्तव में वापस मैं क्या कर रहा था करने के लिए, चला गया जो था: मेरे 100 रन timeit परीक्षण के अनुसार

cmnts = {} 
for i, row in df.iterrows(): 
    while True: 
     try: 
      if row['Use_Case']: 
       cmnts[row['Name']].append(row['Use_Case']) 

      else: 
       cmnts[row['Name']].append('n/a') 

      break 

     except KeyError: 
      cmnts[row['Name']] = [] 

df.drop_duplicates('Name', inplace=True) 
df['Use_Case'] = ['; '.join(v) for v in cmnts.values()] 

, दोहराएं और की जगह विधि परिमाण के एक आदेश से अधिक तेजी से है groupby विधि।

import pandas as pd 
from my_stuff import time_something 

df = pd.DataFrame({'a': [i/(i % 4 + 1) for i in range(1, 10001)], 
        'b': [i for i in range(1, 10001)]}) 

runs = 100 

interim_dict = 'txt = {}\n' \ 
       'for i, row in df.iterrows():\n' \ 
       ' try:\n' \ 
       "  txt[row['a']].append(row['b'])\n\n" \ 
       ' except KeyError:\n' \ 
       "  txt[row['a']] = []\n" \ 
       "df.drop_duplicates('a', inplace=True)\n" \ 
       "df['b'] = ['; '.join(v) for v in txt.values()]" 

grouping = "new_df = df.groupby('a')['b'].apply(str).apply('; '.join).reset_index()" 

print(time_something(interim_dict, runs, beg_string='Interim Dict', glbls=globals())) 
print(time_something(grouping, runs, beg_string='Group By', glbls=globals())) 

पैदावार:

Interim Dict 
    Total: 59.1164s 
    Avg: 591163748.5887ns 

Group By 
    Total: 430.6203s 
    Avg: 4306203366.1827ns 

जहां time_something एक समारोह जो कई बार एक टुकड़ा timeit साथ और ऊपर प्रारूप में परिणाम देता है।

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