2017-02-24 146 views
4

在python2.7列条目中的条目匹配,我创建以下形式的熊猫数据帧:大熊猫选择行通过在多个其他列

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种,所以这打字很多,效率不高。我想一定有更清晰的方法?

+0

在行'1',SPS1共享相同的代码('1111')与SPS4 –

+0

对不起,愚蠢的错误。现在纠正。 – Jack

回答

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

This is clever,+1 – miradulo

+0

@Psidom FutureWarning:numpy equal将来不会检查对象身份。比较没有返回与身份('is')所提示的结果相同的结果)并且将改变。 结果= op(x,y) – Jack

+0

@Psidom尽管您的代码生成了数据框并且似乎可行,但它会报告此错误。虽然我不明白这个错误。这是个问题吗? – Jack

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 
1

Psidom已经有你覆盖了great answer,但捎带过的有点,你可以不包括你是比较反对列,然后使用any()避免必须对每一行进行求和。

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