我有一个带有多索引的数据表。多索引的第一级是对应于给定序列(DNA)的名称,多索引的第二级对应于特定类型的序列变体wt
,m1
,{{ 1}},m2
在下面的示例中。并非所有给定的m3
序列都包含所有类型的变体(请参阅下面的wt
和seqA
)。
seqC
我想对仅具有特定变体类型(本例中为df = pd.DataFrame(data={'A':range(1,9), 'B':range(1,9), 'C': range(1,9)},
index=pd.MultiIndex.from_tuples([('seqA', 'wt'), ('seqA', 'm1'),
('seqA', 'm2'), ('seqB', 'wt'), ('seqB', 'm1'), ('seqB', 'm2'),
('seqB', 'm3'), ('seqC', 'wt') ]))
df.index.rename(['seq_name','type'], inplace=True)
print df
A B C
seq_name type
seqA wt 1 1 1
m1 2 2 2
m2 3 3 3
seqB wt 4 4 4
m1 5 5 5
m2 6 6 6
m3 7 7 7
seqC wt 8 8 8
和m1
)的序列的数据进行后续分析。因此,我想过滤我的数据框,要求给定m2
具有seq_name
中指定的所有变体类型。
我目前的解决方案非常笨重,并不是非常美观的IMO。
list
我觉得必须是一个可以做到这一点的单行。类似的东西:
var_l = ['wt', 'm1', 'm2']
df1 = df[df.index.get_level_values('type').isin(var_l)] #Filter varaints not of interest
set_l = []
for v in var_l: #Filter for each variant individually, and store seq_names
df2 = df[df.index.get_level_values('type').isin([v])]
set_l.append(set(df2.index.get_level_values('seq_name')))
seq_s = set.intersection(*set_l) # Get seq_names that only have all three variants
df3 = df1[df1.index.get_level_values('seq_name').isin(seq_s)] #Filter based on seq_name
print df3
A B C
seq_name type
seqA wt 1 1 1
m1 2 2 2
m2 3 3 3
seqB wt 4 4 4
m1 5 5 5
m2 6 6 6
我已尝试搜索此网站,并且只找到了可以过滤列表中任何项目的答案。
答案 0 :(得分:2)
选项1
使用query
+ stack
正如@jezrael指出的那样,这取决于要分析的行中不存在NaN
。
df.query('type in @var_l').unstack().dropna().stack()
A B C
seq_name type
seqA m1 2.0 2.0 2.0
m2 3.0 3.0 3.0
wt 1.0 1.0 1.0
seqB m1 5.0 5.0 5.0
m2 6.0 6.0 6.0
wt 4.0 4.0 4.0
保留dtypes
df.query('type in @var_l').unstack().dropna().stack().astype(df.dtypes)
A B C
seq_name type
seqA m1 2 2 2
m2 3 3 3
wt 1 1 1
seqB m1 5 5 5
m2 6 6 6
wt 4 4 4
选项2
使用filter
它检查与var_l
相交的子索引是否与var_l
def correct_vars(df, v):
x = set(v)
n = df.name
y = set(df.xs(n).index.intersection(v))
return x == y
df.groupby(level=0).filter(correct_vars, v=var_l)
A B C
seq_name type
seqA wt 1 1 1
m1 2 2 2
m2 3 3 3
seqB wt 4 4 4
m1 5 5 5
m2 6 6 6
m3 7 7 7
答案 1 :(得分:2)
var_l = ['wt', 'm1', 'm2']
filtered_df=df.query('type in @var_l').groupby(level=0).filter(lambda x: len(x)==len(var_l))
print (filtered_df)
A B C
seq_name type
seqA wt 1 1 1
m1 2 2 2
m2 3 3 3
seqB wt 4 4 4
m1 5 5 5
m2 6 6 6
使用transform
size
然后按boolean indexing
过滤的另一种解决方案:
filtered_df = df.query('type in @var_l')
filtered_df = filtered_df[filtered_df.groupby(level=0)['A']
.transform('size')
.eq(len(var_l))
.rename(None)]
print (filtered_df)
A B C
seq_name type
seqA wt 1 1 1
m1 2 2 2
m2 3 3 3
seqB wt 4 4 4
m1 5 5 5
m2 6 6 6
它的工作原因是:
print (filtered_df.groupby(level=0)['A'].transform('size'))
seq_name type
seqA wt 3
m1 3
m2 3
seqB wt 3
m1 3
m2 3
seqC wt 1
Name: A, dtype: int32
print (filtered_df.groupby(level=0)['A']
.transform('size')
.eq(len(var_l))
.rename(None))
seq_name type
seqA wt True
m1 True
m2 True
seqB wt True
m1 True
m2 True
seqC wt False
dtype: bool