2017-07-08 33 views
0

我有一個數據幀:如何標記熊貓中的重複組?

>>> df 
    A 
0 foo 
1 bar 
2 foo 
3 baz 
4 foo 
5 bar 

我需要找到所有重複的組,並連續dgroup_id的標號:

>>> df 
    A dgroup_id 
0 foo   1 
1 bar   2 
2 foo   1 
3 baz 
4 foo   1 
5 bar   2 

(這意味着foo屬於第一組重複的,bar到第二組重複項,並且baz不重複。)

我這樣做了:

import pandas as pd 

df = pd.DataFrame({'A': ('foo', 'bar', 'foo', 'baz', 'foo', 'bar')}) 

duplicates = df.groupby('A').size() 
duplicates = duplicates[duplicates>1] 
# Yes, this is ugly, but I didn't know how to do it otherwise: 
duplicates[duplicates.reset_index().index] = duplicates.reset_index().index 
df.insert(1, 'dgroup_id', df['A'].map(duplicates)) 

這導致:

>>> df 
    A dgroup_id 
0 foo  1.0 
1 bar  0.0 
2 foo  1.0 
3 baz  NaN 
4 foo  1.0 
5 bar  0.0 

有沒有更簡單/更短的方式熊貓實現這一目標?我讀了,也許pandas.factorize可能在這裏的幫助,但我不知道如何使用它...(pandas documentation在這個功能是沒有幫助的)

另外:我不介意0-基於組的計數,也不是奇怪的排序順序;但我希望將dgroup_id作爲整數,而不是浮點數。

+0

不知道,但怎麼樣努力'(duplicates.reset_index ().index).astype(int)'? –

回答

1

利用連鎖經營,首先得到每個A VALUE_COUNT,計算每個組的序號,然後回到原來的DF。

(
    pd.merge(df, 
      df.A.value_counts().apply(lambda x: 1 if x>1 else np.nan) 
       .cumsum().rename('dgroup_id').to_frame(), 
      left_on='A', right_index=True).sort_index() 
) 
Out[49]: 
    A dgroup_id 
0 foo  1.0 
1 bar  2.0 
2 foo  1.0 
3 baz  NaN 
4 foo  1.0 
5 bar  2.0 

如果您需要Nan爲唯一組,那麼您不能將int當作數據類型,這是熊貓限制。如果您沒有問題的唯一的組設置爲0,你可以這樣做:

(
    pd.merge(df, 
      df.A.value_counts().apply(lambda x: 1 if x>1 else np.nan) 
       .cumsum().rename('dgroup_id').to_frame().fillna(0).astype(int), 
      left_on='A', right_index=True).sort_index() 
) 

    A dgroup_id 
0 foo   1 
1 bar   2 
2 foo   1 
3 baz   0 
4 foo   1 
5 bar   2 
2

您可以通過get_duplicates()做重複的list然後設置dgroup_id通過A的指數

def find_index(string): 
    if string in duplicates: 
     return duplicates.index(string)+1 
    else: 
     return 0 

df = pd.DataFrame({'A': ('foo', 'bar', 'foo', 'baz', 'foo', 'bar')}) 
duplicates = df.set_index('A').index.get_duplicates() 
df['dgroup_id'] = df['A'].apply(find_index) 
df 

輸出:

 
    A dgroup_id 
0 foo   2 
1 bar   1 
2 foo   2 
3 baz   0 
4 foo   2 
5 bar   1 
​
0

使用duplicated,以查明DUP將。使用where替換''的單身人士。使用分類來分解。

dups = df.A.duplicated(keep=False) 
df.assign(dgroup_id=df.A.where(dups, '').astype('category').cat.codes) 

    A dgroup_id 
0 foo   2 
1 bar   1 
2 foo   2 
3 baz   0 
4 foo   2 
5 bar   1 

如果堅持零爲''

dups = df.A.duplicated(keep=False) 
df.assign(
    dgroup_id=df.A.where(dups, '').astype('category').cat.codes.replace(0, '')) 

    A dgroup_id 
0 foo   2 
1 bar   1 
2 foo   2 
3 baz   
4 foo   2 
5 bar   1 
0

你可以去:

import pandas as pd 
import numpy as np 
df = pd.DataFrame(['foo', 'bar', 'foo', 'baz', 'foo', 'bar',], columns=['name']) 

# Create the groups order 
ordered_names = df['name'].drop_duplicates().tolist() # ['foo', 'bar', 'baz'] 

# Find index of each element in the ordered list 
df['duplication_index'] = df['name'].apply(lambda x: ordered_names.index(x) + 1) 

# Discard non-duplicated entries 
df.loc[~df['name'].duplicated(keep=False), 'duplication_index'] = np.nan 

print(df) 
# name duplication_index 
# 0 foo    1.0 
# 1 bar    2.0 
# 2 foo    1.0 
# 3 baz    NaN 
# 4 foo    1.0 
# 5 bar    2.0 
0
df = pd.DataFrame({'A': ('foo', 'bar', 'foo', 'baz', 'foo', 'bar')}) 
key_set = set(df['A']) 
df_a = pd.DataFrame(list(key_set)) 
df_a['dgroup_id'] = df_a.index 
result = pd.merge(df,df_a,left_on='A',right_on=0,how='left') 

In [32]: result.drop(0,axis=1) 
Out[32]: 
    A dgroup_id 
0 foo  2 
1 bar  0 
2 foo  2 
3 baz  1 
4 foo  2 
5 bar  0