Как перевести (суммировать) значения из набора диапазонов в диапазоны, которые охватывают эти диапазоны? - PullRequest
3 голосов
/ 20 марта 2019

Я работаю с данными секвенирования, но думаю, что проблема относится к различным типам данных диапазона значений.Я хочу объединить несколько экспериментов считывания количества (значений) из набора областей ДНК, которые имеют начальную и конечную позиции (диапазоны), в дополнительные подсчета для другого набора областей ДНК, которые обычно охватывают многие из первичных областей.Как в следующем примере:

Предоставление следующей таблицы A с диапазонами и счетами:

feature start end count1 count2 count3
gene1   1     10  100    30     22
gene2   15    40  20     10     6
gene3   50    70  40     11     7
gene4   100   150 23     15     9

и следующей таблицы B (с новыми диапазонами):

feature  start  end
range1   1      45
range2   55     160

Я хотел бы получить следующую таблицу подсчета с новыми диапазонами:

feature  start  end  count1  count2  count3
range1   1      45   120     40      28
range2   55     160  63      26      16

Просто для упрощения, если есть хотя бы некоторое перекрытие (хотя бы часть, элемент в таблице A содержится в элементе втаблица B), это должно быть сложено.Любая идея инструмента, доступного для этого или сценария на Perl, Python или R?Я считаю секвенирующие чтения с bedtools multicov, но, насколько я искал, нет другой функциональности, выполняющей то, что я хочу.Есть идеи?

Спасибо.

Ответы [ 3 ]

1 голос
/ 20 марта 2019

Мы можем сделать это:

  1. Создание искусственной key колонки
  2. Выполнить outer объединение (mxn)
  3. Фильтр по значению start ИЛИ end между нашими ranges
  4. pandas.DataFrame.groupby на feature и sum на count столбцах
  5. Наконец concat вывод на df2, чтобы получить желаемый вывод
df1['key'] = 'A'
df2['key'] = 'A'

df3 = pd.merge(df1,df2, on='key', how='outer')

df4 = df3[(df3.start_x.between(df3.start_y, df3.end_y)) | (df3.end_x.between(df3.start_y, df3.end_y))]

df5 = df4.groupby('feature_y').agg({'count1':'sum',
                                    'count2':'sum',
                                    'count3':'sum'}).reset_index()

df_final = pd.concat([df2.drop(['key'], axis=1), df5.drop(['feature_y'], axis=1)], axis=1)

выход

print(df_final)
  feature  start  end  count1  count2  count3
0  range1      1   45     120      40      28
1  range2     55  160      63      26      16
1 голос
/ 20 марта 2019

Вы можете использовать apply() и pd.concat() с пользовательской функцией, где a соответствует вашему первому фрейму данных, а b соответствует вашему второму фрейму данных:

def find_englobed(x):

    englobed = a[(a['start'].between(x['start'], x['end'])) | (a['end'].between(x['start'], x['end']))]

    return englobed[['count1','count2','count3']].sum()

pd.concat([b, b.apply(find_englobed, axis=1)], axis=1)

Урожайность:

  feature  start  end  count1  count2  count3
0  range1      1   45     120      40      28
1  range2     55  160      63      26      16
0 голосов
/ 21 марта 2019

Если это может кому-то помочь, основываясь на ответе @ rahlf23, я изменил его, чтобы сделать его более общим, учитывая, что с одной стороны счетных столбцов может быть больше, и что помимо диапазона важно также быть включенным правая хромосома.

Итак, если таблица "a" равна:

feature Chromosome  start   end count1  count2  count3
gene1   Chr1        1       10  100     30      22
gene2   Chr1        15      40  20      10      6
gene3   Chr1        50      70  40      11      7
gene4   Chr1        100     150 23      15      9
gene5   Chr2        5       30  24      17      2
gene5   Chr2        40      80  4       28     16

и таблица "b":

feature Chromosome  start   end
range1  Chr1        1       45
range2  Chr1        55      160
range3  Chr2        10      90
range4  Chr2        100     200

со следующим скриптом Python:

import pandas as pd

def find_englobed(x):
    englobed = a[(a['Chromosome'] == x['Chromosome']) & (a['start'].between(x['start'], x['end']) | (a['end'].between(x['start'], x['end'])))]
    return englobed[list(a.columns[4:])].sum()

pd.concat([b, b.apply(find_englobed, axis=1)], axis=1)

Теперь с a['Chromosome'] == x['Chromosome'] & я прошу, чтобы они были в одной и той же хромосоме, а с list(a.columns[4:]) я получаю все столбцы с 5-го до конца, независимо от количества столбцов подсчета.

Я получаю следующий результат:

feature Chromosome  start   end count1  count2  count3
range1  Chr1        1       45  120.0   40.0    28.0
range2  Chr1        55      160 63.0    26.0    16.0
range3  Chr2        10      90  28.0    45.0    18.0
range4  Chr2        100     200 0.0     0.0     0.0

Я не уверен, почему полученные числа с плавающей запятой ... какой-либо комментарий?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...