Python 熊猫-非重叠组成员
我有以下数据帧:Python 熊猫-非重叠组成员,python,pandas,Python,Pandas,我有以下数据帧: id start end score C1 2 592 157 C1 179 592 87 C1 113 553 82 C2 152 219 350 C2 13 70 319 C2 13 70 188 C2 15 70 156 C2 87 139 130 C2 92 140 102 C
id start end score
C1 2 592 157
C1 179 592 87
C1 113 553 82
C2 152 219 350
C2 13 70 319
C2 13 70 188
C2 15 70 156
C2 87 139 130
C2 92 140 102
C3 18 38 348
C3 20 35 320
C3 31 57 310
C4 347 51 514
数据按id和分数排序
id代表一个DNA序列
开始和结束表示id中的位置,我希望保留不重叠的切片,并且从重叠中仅保留排名最高的切片:
id start end score
C1 2 592 157
C2 152 219 350
C2 13 70 319
C2 87 139 130
C3 18 38 348
C4 347 51 514
有什么想法吗
谢谢这是较短的,满足所有要求。你需要:
groupby
# from Ned Batchfelder
# http://nedbatchelder.com/blog/201310/range_overlap_in_two_compares.html
def overlap(start1, end1, start2, end2):
"""
Does the range (start1, end1) overlap with (start2, end2)?
"""
return end1 >= start2 and end2 >= start1
def compare_rows(group):
winners = []
skip = []
if len(group) == 1:
return group[['start', 'end', 'score']]
for i in group.index:
if i in skip:
continue
for j in group.index:
last = j == group.index[-1]
istart = group.loc[i, 'start']
iend = group.loc[i, 'end']
jstart = group.loc[j, 'start']
jend = group.loc[j, 'end']
if overlap(istart, iend, jstart, jend):
winner = group.loc[[i, j], 'score'].idxmax()
if winner == j:
winners.append(winner)
skip.append(i)
break
if last:
winners.append(i)
return group.loc[winners, ['start', 'end', 'score']].drop_duplicates()
grouped = df.groupby('id')
print grouped.apply(compare_rows)
这是一个简短的版本
- 添加一列以计算范围,并使用最大范围可以嵌套范围较小的任何内容这一事实
- 在范围列上排序以利用此属性
- 删除每个过程中嵌套的任何对象,以便不会对它们进行多次比较
import pandas as pd
import numpy as np
import StringIO as sio
data = """
id,start,end,score
C1,2,592,157
C1,179,592,87
C1,113,553,82
C2,152,219,350
C2,13,70,319
C2,13,70,188
C2,15,70,156
C2,87,139,130
C2,92,140,102
C3,18,38,348
C3,20,35,320
C3,31,57,310
C4,347,51,514"""
data = pd.read_csv(sio.StringIO(data))
下一个街区就可以了
data['range'] = data.end - data.start
data.sort_values(['id','range'])
g = data.groupby('id')
def f(df):
keep = []
while df.shape[0] > 0:
widest = df.iloc[0]
nested = (df.start >= widest.start) & (df.end <= widest.end)
retain = df.loc[nested]
loc = retain.score.values.argmax()
keep.append(retain.iloc[[loc]])
df = df.loc[np.logical_not(nested)]
return pd.concat(keep,0)
out = g.apply(f).drop('range', 1)
out.index = np.arange(out.shape[0])
谢谢我只是稍微修改了istart、iend、jstart和jend值赋值,因为有时感兴趣的片段可以反转
istart,iend=sorted([group.loc[i,'start'],group.loc[i,'end']])
jstart,jend=sorted([group.loc[j,'start'],group.loc[j,'end']])
假设数据没有嵌套,但只是部分重叠<代码>嵌套=(df.start>=widest.start)&(df.end)我考虑过这种情况,但认为这个问题没有足够的细节来确定如何解决不重叠情况的规则集。例如,假设[1,5]的val=1,[1,3]的val=3,[2,4]的val=3。在这种情况下,[1,3]或[2,4]显然比[1,3]好[1,5],但由于这两个方面没有重叠,我确定应该返回什么。我同意打破平局的问题,只是想提出这个问题
In[3]: out
Out[3]:
id start end score
0 C1 2 592 157
1 C2 152 219 350
2 C2 13 70 319
3 C2 87 139 130
4 C2 92 140 102
5 C3 18 38 348
6 C3 31 57 310
7 C4 347 51 514