在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种,所以这是很多打字而不是非常有效。我想必须有一个更清洁的方式?
答案 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