2016-08-15 13 views
6

パンダのデータフレームの各重複セットの2番目から最後までを選択する最も効率的な方法は何ですか?私は基本的にこの操作を行うにはしたく例えばPython Pandas Drop重複を最後に続ける

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

しかし、この:

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

抽象質問:どのように重複が最大でも最小でもない場合保つためにどの重複を選択します? groupby.applyで

+0

は何である特定の列のデータのようなグループが多い場合、これは特にそうですか? – SO44

+1

抽象化された質問:重複が実際の重複である場合、なぜ2番目のものが最後のものか、そうでなければ重複しない。 – Merlin

+3

@Merlin私の理解では、パンダが重複を特定する際に考慮する唯一のカラムは「[Person、Questions]」なので、残りのカラムはすべて区別できる値を持つ可能性があります。 .groupby(['A'、 'B'])の代わりに –

答えて

6

:異なるDATAFRAMEで

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 

、サブセット2列:

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)から最初のアイテムを取るために、その後、groupby/head(1)を最後の2つの項目を取ることができテール:

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

グループの項目tail(2)は1つの項目を返します。例えば


、(例えばtailheadなど)

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) 

組み込みGROUPBYの方法は、しばしばカスタムPythonの機能を有する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(['A'、 'B'])'のようになります。 – ayhan

+0

@ayhan:改善をありがとう! – unutbu

関連する問題