过滤BLAST序列的数据帧以在每个群集中获得最大pident_x

时间:2018-05-06 10:12:14

标签: python pandas dataframe blast

我遇到问题,我需要解析以下数据帧:

    cluster_name    qseqid  sseqid  pident_x    qstart  qend    sstar   send
2   1   seq1_0035_0035  seq13_0042_0035 0.73    42  133 46  189
3   1   seq1_0035_0035  seq13_0042_0035 0.73    146 283 287 389
4   1   seq1_0035_0035  seq13_0042_0035 0.73    301 478 402 503
5   1   seq13_0042_0035 seq1_0035_0035  0.73    46  189 42  133
6   1   seq13_0042_0035 seq1_0035_0035  0.73    287 389 146 283
7   1   seq13_0042_0035 seq1_0035_0035  0.73    402 503 301 478
8   2   seq4_0042_0035  seq2_0035_0035  0.71    256 789 125 678
9   2   seq4_0042_0035  seq2_0035_0035  0.71    802 1056    706 985
10  2   seq4_0042_0035  seq7_0035_0042  0.83    123 745 156 723
12  4   seq11_0035_0035 seq14_0042_0035 0.89    145 647 236 921
13  4   seq11_0035_0035 seq17_0042_0042 0.97    148 623 241 1002
14  5   seq17_0035_0042 seq17_0042_0042 0.94    188 643 179 746

数据帧和爆炸输出的说明:

  • cluster_name :是存在一个,两个或更多配对序列的群集。
  • qseqid:是一个序列的名称
  • sseqid:是另一个序列的名称。这些比较qseqid vs sseqid
  • pident_x:是这两个序列比较(对齐)后的分数,1表示它们是相同的。 当blast对齐两个序列时,它给出了我的序列在我的比对中对齐的位置("同源"),例如,如果我有:

             10            24
    

    seq1:AAATTTCCCGGGATGCGATGACGATGAAAAAATTTGG        XXXXXXXXX !!!!!!!!!!!!!!! XXXXXXXXXXXXX seq2:GATGAGATCGGGATGCGATGAGGAGATAGAGATAGAG 其中x是差异而且!是一场比赛,爆炸会给我: qstart(第一个seq的开始):10 qend(第一个seq结束):24 sstar(第二个seq的开始):10 发送(第二个seq的结尾):24

注意:这是一个示例,但不一定从0开始。

我真正想要的只是在每个群集中得到最大的pident_x,但问题在于你可以看到我可以有反向序列(如果你看一下2,3,4和5,6,7它们是相同但反转的)我需要做的只是保留一个例子只有2,3和4行,因为blast将比较每个序列,甚至是倒数的序列。

然后输出:

cluster_name    qseqid  sseqid  pident_x    qstart  qend    sstar   send
    2   1   seq1_0035_0035  seq13_0042_0035 0.73    42  133 46  189
    3   1   seq1_0035_0035  seq13_0042_0035 0.73    146 283 287 389
    4   1   seq1_0035_0035  seq13_0042_0035 0.73    301 478 402 503
    10  2   seq4_0042_0035  seq7_0035_0042  0.83    123 745 156 723
    13  4   seq11_0035_0035 seq17_0042_0042 0.97    148 623 241 1002
    14  5   seq17_0035_0042 seq17_0042_0042 0.94    188 643 179 746

确实: 对于cluster1: seq1_0035_0035 vs seq13_0042_0035有他的反转seq13_0042_0035 seq1_0035_0035,但我只保留第一个cluster2:

代表seq4_0042_0035 vs seq7_0035_0042 (0.83) seq4_0042_0035 vs seq2_0035_0035 (0.71)的得分高于cluster4:

代表seq11_0035_0035 vs seq17_0042_0042 (0.97) seq11_0035_0035 vs seq14_0042_0035 (0.89)的得分高于custer5:

代表seq17_0035_0042 vs seq17_0042_0042 只有一个配对序列blast=pd.read_csv("match.csv",header=0) #blast=blast.drop(columns=[ "length", "mismatch", "gapopen", "evalue", "bitscore","pident"]) #Cluster Dataframe cluster=pd.read_csv("cluster_test.csv",header=0) cluster.columns = ["cluster_name", "seq_names"] #Distance mean dataframe dist=pd.read_csv("fnode.csv",header=0) dist.columns = ["qseqid", "sseqid","pident","coverage"] dist=dist.drop(columns=["coverage"]) #Including cluster information and distance mean information into one dataframe: data = cluster.merge(dist, left_on='seq_names', right_on='qseqid') #Adding for each two remaining dataframe a concatened colomn data["name_concatened"] = data["qseqid"].map(str) + data["sseqid"] blast["name_concatened"] = blast["qseqid"].map(str) + blast["sseqid"] #We do not need these columns anymore blast=blast.drop(columns=[ "qseqid","sseqid"]) #Including cluster information + distance mean information + coordinate sequences from blast into one dataframe: data = data.merge(blast, left_on='name_concatened', right_on='name_concatened') data=data.drop(columns=[ "seq_names","name_concatened","pident_y"]) print(data) this = data[["qseqid", "sseqid"]].apply(tuple, axis=1) cum = pd.get_dummies(data[["sseqid", 'qseqid']].apply(tuple, axis=1)).cumsum() this_zeros = pd.get_dummies(this) this_zeros[:] = 0 pd.concat([cum, this_zeros[this_zeros.columns.difference(cum.columns)]], axis=1) keep = pd.concat([cum, this_zeros[this_zeros.columns.difference(cum.columns)]], axis=1).lookup(data.index, this) data=data[keep.astype(bool)] print(data) (0.94),然后我保留这个

我真的不知道如何设法做这样的事情,有人有想法吗?

部分补充:

以下是我在这个小数据集中使用的脚本(与我上面的示例相同):smalldata

  cluster_name           qseqid          sseqid  pident_x  qstart  qend  \
4             1  seq13_0042_0035  seq1_0035_0035      0.73      46   189   
5             1  seq13_0042_0035  seq1_0035_0035      0.73     287   389   
6             1  seq13_0042_0035  seq1_0035_0035      0.73     402   503   

   sstar  send  
4     42   133  
5    146   283  
6    301   478   

但正如你在这里看到的那样我只能得到:

cluster_name    qseqid  sseqid  pident_x    qstart  qend    sstar   send
        2   1   seq1_0035_0035  seq13_0042_0035 0.73    42  133 46  189
        3   1   seq1_0035_0035  seq13_0042_0035 0.73    146 283 287 389
        4   1   seq1_0035_0035  seq13_0042_0035 0.73    301 478 402 503
        10  2   seq4_0042_0035  seq7_0035_0042  0.83    123 745 156 723
        13  4   seq11_0035_0035 seq17_0042_0042 0.97    148 623 241 1002
        14  5   seq17_0035_0042 seq17_0042_0042 0.94    188 643 179 746

我应该得到:

df = pd.DataFrame({'a': [1, 1, 4, 5, 2, 5], 'b': [7, 5, 2, 1, 4, 2]})
this = df[['a', 'b']].apply(tuple, axis=1)
cum = pd.get_dummies(df[['b', 'a']].apply(tuple, axis=1)).cumsum()
this_zeros = pd.get_dummies(this)
this_zeros[:] = 0
pd.concat([cum, this_zeros[this_zeros.columns.difference(cum.columns)]], axis=1)
keep = pd.concat([cum, this_zeros[this_zeros.columns.difference(cum.columns)]], axis=1).lookup(df.index, this)
df=df[keep.astype(bool)]
print(df)

以下是我的真实数据:datas

这是你的例子:

 a  b
3  5  1
4  2  4

和我的结果:

    this.state = {
      pokemon: {
        abilities: []
      }
    }

2 个答案:

答案 0 :(得分:1)

如果您从列中创建一个元组,然后执行累积总和,您可以检查反转对是否已经出现在累计总和中:

df[~pd.DataFrame({
    'tup': df[['sseqid', 'qseqid']].apply(tuple, axis=1), 
    'inv_tups': df[['qseqid', 'sseqid']].apply(lambda t: (tuple(t), ), axis=1).cumsum().shift(1)}
).apply(lambda r: isinstance(r.inv_tups, tuple) and r.tup in r.inv_tups, axis=1)]
  • df[['sseqid', 'qseqid']].apply(tuple, axis=1)会在列中创建元组。

  • df[['qseqid', 'sseqid']].apply(lambda t: (tuple(t), ), axis=1).cumsum().shift(1)创建反元组,并在元组中累加它们

  • 其余的检查是否包含另一个。

答案 1 :(得分:0)

这是另一个答案,希望更有效率。

我将集中讨论您问题中的要点:查看前一行中是否出现了几列中的反向对。例如,我将使用

df = pd.DataFrame({'a': [1, 1, 4, 5, 2, 5], 'b': [7, 5, 2, 1, 4, 2]})
>>> df
    a   b
0   1   7
1   1   5
2   4   2
3   5   1
4   2   4
5   5   2

让我们找到每一行的元组:

this = df[['a', 'b']].apply(tuple, axis=1)
>>> this
0    (1, 7)
1    (1, 5)
2    (4, 2)
3    (5, 1)
4    (2, 4)
5    (5, 2)
dtype: object

这是反向元组的累积总和'外观:

cum = pd.get_dummies(df[['b', 'a']].apply(tuple, axis=1)).cumsum()
>>> cum
(1, 5)  (2, 4)  (2, 5)  (4, 2)  (5, 1)  (7, 1)
0   0.0 0.0 0.0 0.0 1.0 1.0
1   0.0 1.0 0.0 0.0 1.0 1.0
2   1.0 1.0 0.0 0.0 1.0 1.0
3   1.0 1.0 0.0 1.0 1.0 1.0
4   1.0 1.0 1.0 1.0 1.0 1.0
5   NaN NaN NaN NaN NaN NaN

为此,我们需要显示当前行的元组,如果它没有反向存在,则找不到:

this_zeros = pd.get_dummies(this)
this_zeros[:] = 0
>>> pd.concat([cum, this_zeros[this_zeros.columns.difference(cum.columns)]], axis=1)
(1.0, 5.0)  (2.0, 4.0)  (2.0, 5.0)  (4.0, 2.0)  (5.0, 1.0)  (nan, nan)  (1, 7)  (2, 2)  (5, 2)
0   0.0 0.0 0.0 0.0 1.0 0.0 0   0   0
1   0.0 1.0 0.0 0.0 1.0 0.0 0   0   0
2   1.0 1.0 0.0 0.0 1.0 0.0 0   0   0
3   1.0 1.0 0.0 1.0 1.0 0.0 0   0   0
4   1.0 1.0 1.0 1.0 1.0 0.0 0   0   0
5   1.0 1.0 1.0 1.0 1.0 1.0 0   0   0
6   NaN NaN NaN NaN NaN NaN 0   0   0

现在我们可以使用此DataFrame查找当前元组:

keep = pd.concat([cum, this_zeros[this_zeros.columns.difference(cum.columns)]], axis=1).lookup(df.index, this)

我们应该保留原始的DataFrame

>>> df[keep.astype(bool)]
    a   b
0   1   7
1   1   5
2   4   2
5   5   2