2017-07-08 19 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を第2の重複グループに割り当て、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はこの機能には役に立たない)

また、奇妙な並べ替え順もありません。私はdgroup_idを浮動小数点数ではなくintとして使用したいと考えています。

+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を使用できません。 DUPのがどこにあるかを識別するために

(
    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

あなたは、インデックス

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を設定get_duplicates()ことにより、重複のlistを行うことができます。

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

使用duplicated:あなたはユニークなグループのためのセット0でOKであれば、あなたのような何かを行うことができます。シングルトンを''に置き換えるには、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 
関連する問題