2017-02-17 6 views
1

特定のバーコードに関連付けられた値のペアを含む大きな(ish)一連の実験データがあります。理想的には、各ペアには一意のバーコードが必要です。残念ながら、私は実験中に何かをねじ込み、いくつかのペアが1つのバーコードを共有することが判明しました。私はこれらのペア/バーコードを分析から除外する必要があります。パンダデータフレームに複数の共通値を持つ行のみを選択する

私のデータは、種類の次のようになります。

ペアが、列「A」と「B」である - 私はちょうど含ま「X」いくつかの任意の関連するデータを表すために:

df = pd.DataFrame({'Barcode' : ['AABBCC', 'AABBCC', 'BABACC', 'AABBCC', 'DABBAC', 'ABDABD', 'DABBAC'], 
       'A' : ['v', 'v', 'x', 'y', 'z', 'h', 'z'], 
       'B' : ['h', 'h', 'j', 'k', 'l', 'v', 'l'], 
       'X' : np.random.randint(10, size = 7)}) 
df = df[['Barcode', 'A', 'B', 'X']] 
df 

    Barcode A B X 
0 AABBCC v h 8 
1 AABBCC v h 7 
2 BABACC x j 2 
3 AABBCC y k 3 
4 DABBAC z l 8 
5 ABDABD h v 0 
6 DABBAC z l 4 

をこのバーコードは2つの異なるペアに関連付けられているので、バーコード 'AABBCC'で記述された行を取り除きたい(行0と行1は両方とも同じペアです - うまくいきますが、行3は別のペアです) 。これまで

df.loc[df.Barcode != 'AABBCC'] 

    Barcode A B X 
2 BABACC x j 6 
4 DABBAC z l 0 
5 ABDABD h v 7 
6 DABBAC z l 5 

私のソリューションは:

def duplicates(bar): 
    if len(df.loc[df.Barcode == bar].A.unique()) > 1 or len(df.loc[df.Barcode == bar].B.unique()) > 1: 
     return 'collision' 
    else: 
     return 'single' 

df['Barcode_collision'] = df.apply(lambda row: duplicates(row['Barcode']), axis = 1) 
df.loc[df.Barcode_collision == 'single'] 

    Barcode A B X Barcode_collision 
2 BABACC x j 6 single 
4 DABBAC z l 0 single 
5 ABDABD h v 7 single 
6 DABBAC z l 5 single 

残念ながら、これは私の繊細なコンピュータを使用して大規模なデータフレーム(〜50万行)と非常に遅いです。私はより良い/より速い方法でなければならないと確信しています。おそらくgroupby関数を使用していますか?

df.groupby(['Barcode', 'A', 'B']).count() 

       X 
Barcode A B 
AABBCC v h 2 
     y k 1 
ABDABD h v 1 
BABACC x j 1 
DABBAC z l 2 

次に、2番目または3番目のインデックスに複数の値を持つ行を除外しますか?しかし、私の脳と私のグーグルでスキルはさらにこれよりも私を得るように見えることはできません...

答えて

1

あなたはfilterを使用することができます。

print(df.groupby('Barcode').filter(lambda x: ((x.A.nunique() == 1) or (x.B.nunique() == 1)))) 

    Barcode A B X Barcode_collision 
2 BABACC x j 4   single 
4 DABBAC z l 9   single 
5 ABDABD h v 3   single 
6 DABBAC z l 9   single 

transformboolean indexingのもう一つの解決策:

g = df.groupby('Barcode') 
A = g.A.transform('nunique') 
B = g.B.transform('nunique') 

print (df[(A == 1) | (B == 1)]) 
    Barcode A B X Barcode_collision 
2 BABACC x j 2   single 
4 DABBAC z l 6   single 
5 ABDABD h v 1   single 
6 DABBAC z l 3   single 
+0

幻想を!それはかなり高速です。ありがとう! – Ben

+0

100%確かではありませんが、2番目の解決策が速くなる可能性がありますので、テストしてください。 – jezrael

+0

私のマシンでは、最初のソリューションは約30%高速です – Ben

関連する問題