排除仅在一列

时间:2017-02-17 20:52:53

标签: python pandas

我有一组包含多对值的大型(ish)实验数据。每对与特定条形码相关联。理想情况下,每对应具有唯一的条形码。不幸的是,事实证明我在实验过程中搞砸了一些东西。现在有几对共享一个条形码。我需要从我的分析中排除这些对/条形码。

我的数据看起来像这样:

对在列'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

我想摆脱条形码'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

不幸的是,使用我的精密计算机时,使用大型数据帧(约500,000行)非常慢。我敢肯定必须有更好/更快的方式。也许使用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

然后过滤掉第二个或第三个索引中具有多个值的行?但是我的大脑和谷歌搜索技巧似乎无法让我比这更进一步......

1 个答案:

答案 0 :(得分: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