2

因此,我使用此代码在主序列中打印子序列的开始和停止位置,表示为 SOURCE。主序列由 GENE 识别。GENE 中的某些序列具有 DIRECTION 两个组成部分,+ 和 -,它们被视为唯一序列。但是,我没有意识到的是,在首先生成数据集时(通过将许多 SOURCE 序列的文件与 GENE 序列进行比对),我有多个实例,其中存在多个 SOURCE 序列的“有效”比对针对基因序列。我需要一种方法来从 SOURCE 序列中删除在 GENE 序列中出现次数最少的条目,或者在 SOURCE 序列数量相等的情况下,从 POS1 到最终 POS2 的最小范围。我在下面有一个示例输出,其中包含一个清晰的示例。

这是我的 Python 代码:

import pandas
import pandas as pd
import sys
import csv

##sys.stdout = open("Sampletest2d.txt", "w")
##data = pd.read_csv('Sampletest2.txt', sep='\t')
sys.stdout = open("ExonFileTry1Part3.txt", "w")
data = pd.read_csv('ExonFileTry1.txt', sep='\t')
groups = data.groupby(['GENE', 'DIRECTION'])

fixedgroups = []

for (gene_id, strand), group in groups:
    #print gene_id, strand
    if strand == '+':
        group['POS-1'] = group.POS1
        group['POS-2'] = group.POS2
    else:
        group['POS-1'] = group.POS2
        group['POS-2'] = group.POS1
    #print group
    fixedgroups.append(group)
print fixedgroups

数据集(制表符分隔)

GENE    DIRECTION   POS1    POS2    SOURCE
TT-1    +   1   16  A1
TT-1    +   130 289 A1
TT-1    +   353 438 A1
TT-1    +   519 580 A1
TT-1    +   665 742 A1
TT-1    +   813 864 A1
TT-1    +   931 975 A1
TT-1    +   1053    1166    A1
TT-1    +   1   16  B2
TT-1    +   130 289 B2
TT-1    +   353 438 B2
TT-1    +   519 580 B2
TT-1    +   665 742 B2
TT-1    +   813 864 B2
TT-1    +   931 975 B2
TT-1    +   1053    1161    B2
BB-2    +   3   659 C3
BB-2    +   3   640 D4
BB-2    -   1093    426 E5
BB-2    -   1093    508 F6
EE-3    +   1   95  G7
EE-3    +   155 377 G7
EE-3    +   439 513 G7
EE-3    +   577 840 G7
EE-3    +   1   95  H8
EE-3    +   155 377 H8
EE-3    +   439 513 H8
EE-3    -   840 577 I9
EE-3    -   513 439 I9
EE-3    -   377 155 I9
EE-3    -   840 577 J10
EE-3    -   513 458 J10

有时一个 GENE 有多个 SOURCE 序列,并且来自一个 SOURCE 的序列比另一个多。但是,有时来自两个不同 SOURCE 的序列数量相同,在这种情况下,我需要保留该 SOURCE 的第一个 POS1 和最后一个 POS2 之间值范围最大的 SOURCE。

例如,在 + DIRECTION 的 GENE TT-1 中,有两个 SOURCE 集 A1 和 B2,它们都有 8 个条目。但是,SOURCE A1 的最终 POS2 为 1166,而 B2 的最终 POS2 为 1161,因此 B2 的范围较小,应删除。

我花了令人难以置信的时间来理解如何做我已经做过的事情,而且那是基于类似的代码开始的。我觉得我知道我想在这里做什么,但我只是不知道语法,因为我的计算机科学知识非常有限。提前感谢您的帮助!

4

2 回答 2

2

我不是 100% 确定我理解你写的所有内容,但我跳过了你的数据和'例如'段落,它说“源 A1 的最终 POS2 为 1166,而 B2 的最终 POS2 为 1161,并且所以 B2 的范围较小,应该删除”。我将“TT-1 +”和“TT-1 -”视为不同的实体,并且我正在对每一行的范围求和。我想这就是你想要的。

将 RANGE 列添加到 DataFrame

df['RANGE'] = abs(df['POS2']-df['POS1'])

现在为每个序列、源组合累积每个源。

df['SUMRANGE'] = df.groupby(["GENE", "DIRECTION", "SOURCE"])['RANGE'].cumsum()

提取每个序列具有最大“SUMRANGE”的行的索引。

dfm = pandas.DataFrame(df.ix[df.groupby(["GENE", "DIRECTION"]).agg(lambda df: df.idxmax())['SUMRANGE']])

join设置要在接下来的函数中使用的索引。

dfm.index = pandas.MultiIndex.from_arrays([dfm['GENE'], dfm['DIRECTION']])

加入 df 和 dfm。

dfj = df.join(other=dfm['SOURCE'], on=['GENE', 'DIRECTION'], rsuffix='.r')

现在根据“SOURCE”是否与“SOURCE.r”相同来过滤 dfj。

dfj[dfj.apply(lambda x: x['SOURCE'] == x['SOURCE.r'], axis=1)]

    GENE DIRECTION  POS1  POS2 SOURCE  RANGE  SUMRANGE SOURCE.r
0   TT-1         +     1    16     A1     15        15       A1
1   TT-1         +   130   289     A1    159       174       A1
2   TT-1         +   353   438     A1     85       259       A1
3   TT-1         +   519   580     A1     61       320       A1
4   TT-1         +   665   742     A1     77       397       A1
5   TT-1         +   813   864     A1     51       448       A1
6   TT-1         +   931   975     A1     44       492       A1
7   TT-1         +  1053  1166     A1    113       605       A1
16  BB-2         +     3   659     C3    656       656       C3
18  BB-2         -  1093   426     E5    667       667       E5
20  EE-3         +     1    95     G7     94        94       G7
21  EE-3         +   155   377     G7    222       316       G7
22  EE-3         +   439   513     G7     74       390       G7
23  EE-3         +   577   840     G7    263       653       G7
27  EE-3         -   840   577     I9    263       263       I9
28  EE-3         -   513   439     I9     74       337       I9
29  EE-3         -   377   155     I9    222       559       I9

当然,您可以根据需要删除不需要的列dfj。作为参考,这是我开始使用的 DataFrame。

In [2]: df
Out[2]: 
    GENE DIRECTION  POS1  POS2 SOURCE
0   TT-1         +     1    16     A1
1   TT-1         +   130   289     A1
2   TT-1         +   353   438     A1
3   TT-1         +   519   580     A1
4   TT-1         +   665   742     A1
5   TT-1         +   813   864     A1
6   TT-1         +   931   975     A1
7   TT-1         +  1053  1166     A1
8   TT-1         +     1    16     B2
9   TT-1         +   130   289     B2
10  TT-1         +   353   438     B2
11  TT-1         +   519   580     B2
12  TT-1         +   665   742     B2
13  TT-1         +   813   864     B2
14  TT-1         +   931   975     B2
15  TT-1         +  1053  1161     B2
16  BB-2         +     3   659     C3
17  BB-2         +     3   640     D4
18  BB-2         -  1093   426     E5
19  BB-2         -  1093   508     F6
20  EE-3         +     1    95     G7
21  EE-3         +   155   377     G7
22  EE-3         +   439   513     G7
23  EE-3         +   577   840     G7
24  EE-3         +     1    95     H8
25  EE-3         +   155   377     H8
26  EE-3         +   439   513     H8
27  EE-3         -   840   577     I9
28  EE-3         -   513   439     I9
29  EE-3         -   377   155     I9
30  EE-3         -   840   577    J10
31  EE-3         -   513   458    J10
于 2013-02-27T19:04:32.417 回答
2

这是@DA答案的变体:

首先,一些样板设置:

import pandas as pd
import io

data = '''\
GENE    DIRECTION   POS1    POS2    SOURCE
TT-1    +   1   16  A1
TT-1    +   130 289 A1
TT-1    +   353 438 A1
TT-1    +   519 580 A1
TT-1    +   665 742 A1
TT-1    +   813 864 A1
TT-1    +   931 975 A1
TT-1    +   1053    1166    A1
TT-1    +   1   16  B2
TT-1    +   130 289 B2
TT-1    +   353 438 B2
TT-1    +   519 580 B2
TT-1    +   665 742 B2
TT-1    +   813 864 B2
TT-1    +   931 975 B2
TT-1    +   1053    1161    B2
BB-2    +   3   659 C3
BB-2    +   3   640 D4
BB-2    -   1093    426 E5
BB-2    -   1093    508 F6
EE-3    +   1   95  G7
EE-3    +   155 377 G7
EE-3    +   439 513 G7
EE-3    +   577 840 G7
EE-3    +   1   95  H8
EE-3    +   155 377 H8
EE-3    +   439 513 H8
EE-3    -   840 577 I9
EE-3    -   513 439 I9
EE-3    -   377 155 I9
EE-3    -   840 577 J10
EE-3    -   513 458 J10'''

df = pd.read_table(io.BytesIO(data), sep='\t')

现在我们添加RANGESUMRANGE列,就像@DA 所做的那样:

df['RANGE'] = abs(df['POS2']-df['POS1'])
df['SUMRANGE'] = df.groupby(["GENE", "DIRECTION", "SOURCE"])['RANGE'].cumsum()
print(df)
#     GENE DIRECTION  POS1  POS2 SOURCE  RANGE  SUMRANGE
# 0   TT-1         +     1    16     A1     15        15
# 1   TT-1         +   130   289     A1    159       174
# 2   TT-1         +   353   438     A1     85       259
# 3   TT-1         +   519   580     A1     61       320
# 4   TT-1         +   665   742     A1     77       397
# 5   TT-1         +   813   864     A1     51       448
# 6   TT-1         +   931   975     A1     44       492
# 7   TT-1         +  1053  1166     A1    113       605
# 8   TT-1         +     1    16     B2     15        15
# 9   TT-1         +   130   289     B2    159       174
# 10  TT-1         +   353   438     B2     85       259
# 11  TT-1         +   519   580     B2     61       320
# 12  TT-1         +   665   742     B2     77       397
# 13  TT-1         +   813   864     B2     51       448
# 14  TT-1         +   931   975     B2     44       492
# 15  TT-1         +  1053  1161     B2    108       600
# 16  BB-2         +     3   659     C3    656       656
# 17  BB-2         +     3   640     D4    637       637
# 18  BB-2         -  1093   426     E5    667       667
# 19  BB-2         -  1093   508     F6    585       585
# 20  EE-3         +     1    95     G7     94        94
# 21  EE-3         +   155   377     G7    222       316
# 22  EE-3         +   439   513     G7     74       390
# 23  EE-3         +   577   840     G7    263       653
# 24  EE-3         +     1    95     H8     94        94
# 25  EE-3         +   155   377     H8    222       316
# 26  EE-3         +   439   513     H8     74       390
# 27  EE-3         -   840   577     I9    263       263
# 28  EE-3         -   513   439     I9     74       337
# 29  EE-3         -   377   155     I9    222       559
# 30  EE-3         -   840   577    J10    263       263
# 31  EE-3         -   513   458    J10     55       318

对于具有共同 GENE 和 DIRECTION 的每个组,记录具有最大 SUMRANGE 的行的索引:

idx = df.groupby(["GENE", "DIRECTION"])['SUMRANGE'].agg(lambda col: col.idxmax())
print(idx)
# GENE  DIRECTION
# BB-2  +            16
#       -            18
# EE-3  +            23
#       -            29
# TT-1  +             7
# Name: SUMRANGE

df选择具有 GENE、DIRECTION 和 SOURCE 列的子 DataFrame,行由 给出idx

dfm = df.ix[idx, ['GENE','DIRECTION','SOURCE']]
print(dfm)
#     GENE DIRECTION SOURCE
# 16  BB-2         +     C3
# 18  BB-2         -     E5
# 23  EE-3         +     G7
# 29  EE-3         -     I9
# 7   TT-1         +     A1

df在和上进行内部合并dfm。键是 和 的公共列的交集,dfdfmGENE、DIRECTION 和 SOURCE。“内部”合并仅保留两者df共享dfm相同键的行。所以在合并的 DataFrame 中,df's GENE、DIRECTION 和 SOURCE 必须匹配dfm' GENE、DIRECTION 和 SOURCE。因此,所有带有错误 SOURCE 的行都将被删除:

result = pd.merge(df, dfm, how = 'inner')
print(result)
#     GENE DIRECTION  POS1  POS2 SOURCE  RANGE  SUMRANGE
# 0   TT-1         +     1    16     A1     15        15
# 1   TT-1         +   130   289     A1    159       174
# 2   TT-1         +   353   438     A1     85       259
# 3   TT-1         +   519   580     A1     61       320
# 4   TT-1         +   665   742     A1     77       397
# 5   TT-1         +   813   864     A1     51       448
# 6   TT-1         +   931   975     A1     44       492
# 7   TT-1         +  1053  1166     A1    113       605
# 8   BB-2         +     3   659     C3    656       656
# 9   BB-2         -  1093   426     E5    667       667
# 10  EE-3         +     1    95     G7     94        94
# 11  EE-3         +   155   377     G7    222       316
# 12  EE-3         +   439   513     G7     74       390
# 13  EE-3         +   577   840     G7    263       653
# 14  EE-3         -   840   577     I9    263       263
# 15  EE-3         -   513   439     I9     74       337
# 16  EE-3         -   377   155     I9    222       559
于 2013-02-27T22:51:24.820 回答