Объединить pandas строк данных для создания диапазонов? - PullRequest
1 голос
/ 29 апреля 2020

первый пост на SO, и я довольно новичок в Python, поэтому извиняюсь, если этот вопрос тривиален / уже был дан ответ (я не смог найти его, если бы он был).

У меня есть pandas dataframe df, состоящий из геномных c координат в следующем формате:

    chrom     start       end
0   chr22  10510357  10510357
1   chr22  10512304  10512304
2   chr22  10516109  10516109
3   chr22  10516111  10516111
4   chr22  10516129  10516129
5   chr22  10516130  10516130
6   chr22  10516131  10516131
7   chr22  10516133  10516133
8   chr22  10516161  10516161
9   chr22  10516162  10516162
10  chr22  10516163  10516163
11  chr22  10516164  10516164
12  chr22  10516165  10516165
13  chr22  10516166  10516166
14  chr22  10516167  10516167
15  chr22  10516168  10516168
16  chr22  10516169  10516169
17  chr22  10516170  10516170
18  chr22  10516171  10516171
19  chr22  10516172  10516172

Что я хотел бы сделать, это объединить строки, где позиция 'end' предыдущего row находится на расстоянии 1 базовой пары от позиции 'start' текущей строки, возможно, в итоге получится что-то вроде этого:

 chrom     start       end
0   chr22  10510357  10510357
1   chr22  10512304  10512304
2   chr22  10516109  10516109
3   chr22  10516111  10516111
4   chr22  10516129  10516129
5   chr22  10516130  10516133
6   chr22  10516161  10516172

Я работал над небольшим набором тестовых данных, который состоит только из позиции в chr22, но для моего реального сценария я буду использовать весь геном, поэтому проверка того, одинаковы ли хромосомы соседних позиций, также важна. Вот то, что я попробовал до сих пор без удачи:

for i in range(0, len(df)-1):
    if df.loc[i, 'chrom'] == df.loc[i+1, 'chrom'] and df.loc[i, 'end'] == df.loc[i+1, 'start']:
        df.loc[i, 'end'] = df.loc[i+1, 'end']

Спасибо всем заранее, любая помощь / руководство приветствуется!

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

Попробуйте это:

df = pd.DataFrame([[1],[3],[4],[5],[7], [11],[12],[13],[14],[18]])
df_end = df[~((df[0].shift(0) == df[0].shift(-1)-1))]
df_start = df[~((df[0].shift(0) == df[0].shift(+1)+1))]
for start, end in zip(df_start[0], df_end[0]):
    print (start, end)
0 голосов
/ 29 апреля 2020

Я предполагаю, что "1 базовая пара" означает, что начальная позиция текущей строки равна значению конечной позиции предыдущей строки плюс 1.

import pandas as pd

#Function to find the end position of consecutive rows 
    def findEnd(df, index):
        while index < len(df)-1:
            if(df.iloc[index]['end']+1) == df.iloc[index+1]['start']:
                index+=1
            else: return(df.iloc[index]['end'], index)
        return (df.iloc[index]['end'], index)


    lst = []
    i = 0
    genLen = len(df)
    #Traverse entire dataframe
    while i < genLen:  
        #Check if we have at least one more row
        if i < genLen-1: 
            #Check the next row is the same chrom
            if(df.iloc[i]['chrom'] == df.iloc[i+1]['chrom']):
                start = df.iloc[i]['start']
                end,i = findEnd(df,i)
                lst.append([df.iloc[i]['chrom'],start,end])
            else:
                #if the next row is a different 
                lst.append(list(df.iloc[i]))
        elif i == genLen -1:
            lst.append(list(df.iloc[i]))
        i+=1

    chrom = pd.DataFrame(lst,columns=['chrom','start','end'])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...