2016-07-24 10 views
1

名前が後続の行に表示される場合は、その行を削除します。主に私は重複を発見したインデックスを取得し、そのインデックス番号を使用してdfからドロップする方法がわかりません。複数の列とドロップ行で重複を見つける - Pandas

import pandas as pd 
data = {'interviewer': ['Jason', 'Molly', 'Jermaine', 'Jake', 'Amy'], 
     'candidate': ['Bob', 'Jermaine', 'Ahmed', 'Karl', 'Molly'], 
     'year': [2012, 2012, 2013, 2014, 2014], 
     'reports': [4, 24, 31, 2, 3]} 

df = pd.DataFrame(data) 
#names = pd.unique(df[['interviewer', 'candidate']].values.ravel()).tolist() 

mt = [] 

for i, c in zip(df.interviewer, df.candidate): 
    print i, c 
    if i not in mt: 
     if c not in mt: 
      mt.append(df.loc[(df.interviewer == i) & (df.candidate == c)]) 
    else: 
     continue 

私の考えはdf.dropに渡すと、これらのインデックスを持つ行を削除するには、リストとして使用mtました。私が望む結果は、MollyまたはJermaineがインデックス2または4に再び現れるのを見ることなく、df.drop([2,4], inplace=True)です。

EDITED

私がドロップする渡したいインデックスのリストを作成する方法を考え出した:

import pandas as pd 
data = {'interviewer': ['Jason', 'Molly', 'Jermaine', 'Jake', 'Amy'], 
     'candidate': ['Bob', 'Jermaine', 'Ahmed', 'Karl', 'Molly'], 
     'year': [2012, 2012, 2013, 2014, 2014], 
     'reports': [4, 24, 31, 2, 3]} 

df = pd.DataFrame(data) 
#print df 
counter = -1 
bad_rows = [] 
names = [] 
for i, c in zip(df.interviewer, df.candidate): 
    print i, c 

    counter += 1 
    print counter 
    if i not in names: 
     names.append(i) 
    else: 
     bad_rows.append(counter) 
    if c not in names: 
     names.append(c) 
    else: 
     bad_rows.append(counter) 

#print df.drop(bad_rows) 

しかしこれを行うには、よりスマートな方法がなければなりません、おそらく@Ami_Tavory itertoolsの答えに沿った何か?

+0

あなたはこれを見を持っている場合があります:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.drop_duplicates.html – albert

+0

私は( 'df.drop_duplicatesを試してみました[ 'candidate'、 'interviewer')) 'しかし、それは両方が一致したときにのみ動作します。私は '見た名前が見つかった - 行を落とす'機能を探しています – noblerthanoedipus

答えて

1

(この答えが書かれた時点では、口頭での説明とコード例の間にいくつかの相違があった。)

あなたがそうのように、項目が異なる列に表示されるかどうかを確認するためにisinを使用することができます。

In [5]: df.candidate.isin(df.interviewer) 
Out[5]: 
0 False 
1  True 
2 False 
3 False 
4  True 
Name: candidate, dtype: bool 

その結果、あなたはこれがあなたの元のコードではなく、あなたのspecificati一致していること

df[~df.candidate.isin(df.interviewer)] 

ノートのような何かを行うことができますの続き、行。あなただけの行が、その後のであればドロップしたい場合は、私がitertoolsで行くと思い、何かのように:あなたは後続の行を削除する場合

In [18]: bads = [i for ((i, cn), (j, iv)) in itertools.product(enumerate(df.candidate), enumerate(df.interviewer)) if j >=i and cn == iv] 

In [19]: df[~df.index.isin(bads)] 
Out[19]: 
    candidate interviewer reports year 
0  Bob  Jason  4 2012 
2  Ahmed Jermaine  31 2013 
3  Karl  Jake  2 2014 
4  Molly   Amy  3 2014 

また、単に

In [18]: bads = [j for ((i, cn), (j, iv)) in itertools.product(enumerate(df.candidate), enumerate(df.interviewer)) if j >=i and cn == iv] 
+0

ありがとうございましたが、私が望んでいたものではありませんでした。私は今答えを出していますので、itertoolsにショートカットがあることを知らせてください。 – noblerthanoedipus

+0

@noblerthanoedipus更新を参照してください。 –

+0

は、インデックス= 1では 'Molly'の最初のインスタンスを削除しますが、インデックスは削除する必要があります - 4 - 'Molly'の2番目のインスタンス。その後の発生。私は 'pd.drop_duplicates([subset]、keep = 'first')'と同じアイデアを使用しています。 – noblerthanoedipus

0
に物事を変えます

私は何をしたいのか機能させました。 df.indexを使用すると、任意の数値インデックスに安全に使用できます。

def drop_dup_rows(df): 
    names = [] 
    for i, c, ind in zip(df.interviewer, df.candidate, df.index.tolist()): 
     if any(x in names for x in [i, c]): 
      df.drop(ind, inplace=True) 
     else: 
      names.extend([i,c]) 
    return df 
関連する問題