2016-08-15 14 views
6

पर दूसरे स्थान पर रखें, एक पांडा डेटाफ्रेम में प्रत्येक डुप्लिकेट सेट के आखिरी के लिए दूसरा चयन करने का सबसे प्रभावी तरीका क्या है?पायथन पांडस ड्रॉप डुप्लिकेट्स

उदाहरण के लिए

मैं मूल रूप से इस कार्रवाई को क्या करना चाहते हैं:

df = df.drop_duplicates(['Person','Question'],take_last=True) 

लेकिन इस:

df = df.drop_duplicates(['Person','Question'],take_second_last=True) 

पृथक प्रश्न: कैसे जो करता है, तो डुप्लिकेट न अधिकतम और न ही मिनट है रखने के लिए नकल का चयन करने के ?

+0

क्या तरह की पहचान स्तंभ डेटा है? – SO44

+1

सारित प्रश्न: यदि डुप्लिकेट वास्तविक डुप्लिकेट हैं, तो आखिरी मामले में दूसरा क्यों होगा, अन्यथा वे डुप्लिकेट नहीं हैं। – Merlin

+3

@ मार्लिन मेरी समझ यह है कि '[व्यक्ति, प्रश्न]' डुप्लीकेट की पहचान करते समय केवल कॉलम पांडा विचार करेंगे, इसलिए शेष बचे हुए कॉलम में विशिष्ट मान हो सकते हैं। –

उत्तर

6
groupby.apply साथ

:

df = pd.DataFrame({'A': [1, 1, 1, 1, 2, 2, 2, 3, 3, 4], 
        'B': np.arange(10), 'C': np.arange(10)}) 

df 
Out: 
    A B C 
0 1 0 0 
1 1 1 1 
2 1 2 2 
3 1 3 3 
4 2 4 4 
5 2 5 5 
6 2 6 6 
7 3 7 7 
8 3 8 8 
9 4 9 9 

(df.groupby('A', as_index=False).apply(lambda x: x if len(x)==1 else x.iloc[[-2]]) 
    .reset_index(level=0, drop=True)) 
Out: 
    A B C 
2 1 2 2 
5 2 5 5 
7 3 7 7 
9 4 9 9 
एक अलग DataFrame साथ

, सबसेट दो कॉलम:

df = pd.DataFrame({'A': [1, 1, 1, 1, 2, 2, 2, 3, 3, 4], 
        'B': [1, 1, 2, 1, 2, 2, 2, 3, 3, 4], 'C': np.arange(10)}) 

df 
Out: 
    A B C 
0 1 1 0 
1 1 1 1 
2 1 2 2 
3 1 1 3 
4 2 2 4 
5 2 2 5 
6 2 2 6 
7 3 3 7 
8 3 3 8 
9 4 4 9 

(df.groupby(['A', 'B'], as_index=False).apply(lambda x: x if len(x)==1 else x.iloc[[-2]]) 
    .reset_index(level=0, drop=True)) 
Out: 
    A B C 
1 1 1 1 
2 1 2 2 
5 2 2 5 
7 3 3 7 
9 4 4 9 
2

आप groupby/tail(2) पिछले 2 आइटम लेने के लिए सकता है, तो groupby/head(1) से पहले आइटम लेने के लिए पूंछ:

df.groupby(['A','B']).tail(2).groupby(['A','B']).head(1) 

यदि केवल एक ही है समूह में आइटम, tail(2) केवल एक आइटम देता है।


उदाहरण के लिए,

import numpy as np 
import pandas as pd 

df = pd.DataFrame(np.random.randint(10, size=(10**2, 3)), columns=list('ABC')) 
result = df.groupby(['A','B']).tail(2).groupby(['A','B']).head(1) 

expected = (df.groupby(['A', 'B'], as_index=False).apply(lambda x: x if len(x)==1 else x.iloc[[-2]]).reset_index(level=0, drop=True)) 
assert expected.sort_index().equals(result) 

builtin GroupBy तरीकों (जैसे tail और head के रूप में) अक्सर से कस्टम पायथन कार्यों के साथ groupby/apply बहुत तेजी से कर रहे हैं। यह विशेष रूप से सच है अगर वहाँ समूहों के एक बहुत हैं:

In [96]: %timeit df.groupby(['A','B']).tail(2).groupby(['A','B']).head(1) 
1000 loops, best of 3: 1.7 ms per loop 

In [97]: %timeit (df.groupby(['A', 'B'], as_index=False).apply(lambda x: x if len(x)==1 else x.iloc[[-2]]).reset_index(level=0, drop=True)) 
100 loops, best of 3: 17.9 ms per loop 

वैकल्पिक रूप से, ayhan suggests एक अच्छा सुधार:

alt = df.groupby(['A','B']).tail(2).drop_duplicates(['A','B']) 
assert expected.sort_index().equals(alt) 

In [99]: %timeit df.groupby(['A','B']).tail(2).drop_duplicates(['A','B']) 
1000 loops, best of 3: 1.43 ms per loop 
+0

'.drop_duplicates (['ए', 'बी'] '' के बजाय' .groupby (['ए', 'बी'])। सिर (1) 'थोड़ा तेज लगता है। – ayhan

+0

@ayhan: सुधार के लिए धन्यवाद! – unutbu

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