如何将计数从一组范围转移到范围内的范围



我正在使用测序数据,但我认为问题适用于不同的范围值数据类型。我想将来自具有起始位置(范围)的集合DNA区域的读数(值)的几个实验结合在一起,将数量的其他DNA区域的计数加起来,这些DNA区域通常是许多主要区域。如下以下示例:

给出下表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来计算测序读取,但是据我搜索,没有其他功能可以做我想要的。有什么想法吗?

谢谢。

我们可以通过:

做到这一点
  1. 创建人工key
  2. 执行outer加入(mxn)
  3. 在我们的ranges之间的startend值上的过滤器
  4. featuresum上的pandas.DataFrame.groupby 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

您可以将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

如果它可以根据 @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:]),我从第五到结束时获得了所有列,并独立于计数列的数量。

我获得以下结果:

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

我不确定为什么获得的计数与浮点相关。.

如果您在熊猫中进行基因组学,则可能想研究perranges:

import pyranges as pr
c = """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
"""
c2 = """feature Chromosome  Start   End
range1  Chr1        1       45
range2  Chr1        55      160
range3  Chr2        10      90
range4  Chr2        100     200 """
gr, gr2 = pr.from_string(c), pr.from_string(c2)
j = gr2.join(gr).drop(like="_b")
# +------------+--------------+-----------+-----------+-----------+-----------+-----------+
# | feature    | Chromosome   |     Start |       End |    count1 |    count2 |    count3 |
# | (object)   | (category)   |   (int32) |   (int32) |   (int64) |   (int64) |   (int64) |
# |------------+--------------+-----------+-----------+-----------+-----------+-----------|
# | range1     | Chr1         |         1 |        45 |       100 |        30 |        22 |
# | range1     | Chr1         |         1 |        45 |        20 |        10 |         6 |
# | range2     | Chr1         |        55 |       160 |        40 |        11 |         7 |
# | range2     | Chr1         |        55 |       160 |        23 |        15 |         9 |
# | range3     | Chr2         |        10 |        90 |        24 |        17 |         2 |
# | range3     | Chr2         |        10 |        90 |         4 |        28 |        16 |
# +------------+--------------+-----------+-----------+-----------+-----------+-----------+
# Unstranded PyRanges object has 6 rows and 7 columns from 2 chromosomes.
# For printing, the PyRanges was sorted on Chromosome.
df = j.df
fs = {"Chromosome": "first", "Start":
      "first", "End": "first", "count1": "sum", "count2": "sum", "count3": "sum"}
result = df.groupby("feature".split()).agg(fs)
#         Chromosome  Start  End  count1  count2  count3
# feature
# range1        Chr1      1   45     120      40      28
# range2        Chr1     55  160      63      26      16
# range3        Chr2     10   90      28      45      18

最新更新