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
有什么想法吗


谢谢

这是较短的,满足所有要求。你需要:

  • 一种检查重叠的方法
  • 按ID对数据进行分组的方法
  • 在检查重叠后,从每组中获取最佳结果的方法
  • 这就是所有这些,通过使用逻辑和
    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