pandas通过将列条目与多个其他列中的条目进行匹配来选择行

时间:2017-02-24 15:19:24

标签: python python-2.7 pandas

在python2.7中,我创建了以下形式的pandas数据帧:

import pandas as pd

df = pd.DataFrame({
'ID' : ['1','2','3'],
'sps1' : ['1001', '1111', '1000'],
'sps2' : ['1001','0001','NaN'],
'sps3' : ['1001','NaN','1000'],
'sps4' : ['1001','1101','0101']
})

因此它看起来像:

     ID  sps1  sps2  sps3  sps4
0     1  1001  1001  1001  1001
1     2  1111  0001   NaN  1101
2     3  1000   NaN  1000  0101

每行包含不同生物序列的数据,其具有唯一ID(1,2,3等)。每个序列存在于4种不同的物种中(sps1-4)。每个序列中4个不同特征的存在(1)或不存在(0)被编码为4位代码。某些物种缺失序列,因此记录了NaN。

从这个数据框中,我想选择sps1的代码匹配所有其他物种的代码的行。

所以在上面的例子中,我想丢弃第0行(代码1001对于所有sps是相同的)和第2行(sps1代码1000与sps3的匹配),但保留第1行(sps1代码1111是唯一的)。

最终,我想将这些选定的行放在具有相同结构的新数据框中。

我是使用熊猫的新手。到目前为止,我设法找到了这样做的方法:

matches = df.loc[( (df['sps1'] != df['sps2']) & (df['sps1'] != df['sps3']) )].index
df_match = df.iloc[matches]

我可以为sps1和spsX的所有组合继续这种风格,但在我的全面分析中,我将处理超过12种,所以这是很多打字而不是非常有效。我想必须有一个更清洁的方式?

3 个答案:

答案 0 :(得分:3)

您可以使用filter按模式选择列,并使用eq检查sps1列是否与所有其他列相同,此处指定axis = rows进行比较逐列。这会生成一个逻辑向量,您可以将其用于子集化:

df[(df.filter(regex = "^sps").eq(df.sps1, axis="rows")).sum(axis=1) == 1]

#  ID   sps1    sps2    sps3    sps4
#1  2   1111    0001     NaN    1101

答案 1 :(得分:1)

Psidom已经为您提供了great answer,但是稍微捎带它,您无法包含您要比较的列,然后使用any()来避免必须对每一行求和。

df[~df.filter(regex="^sps(?!1$)\d+$").eq(df.sps1, axis='rows').any(1)]

答案 2 :(得分:0)

你猜错了:

df.loc[[df.iloc[i,1:].duplicated().sum() == 0 for i in df.index]]

结果:

  ID  sps1  sps2 sps3  sps4
1  2  1111  0001  NaN  1101