根据地图计算类值

时间:2016-09-29 20:49:29

标签: perl awk data-processing

我想基于已知标记类的接近度来标记标记类(A类或B类)。因此,例如,如果我知道M1和M4是A类,那么位于M1和M4之间的地图中的所有标记也可以归类为A.

如果我知道标记M4是A类,其位置是chr1 13,标记M7是B,位置16,那么我们可以将位置小于等于(13 + 16)/2=14.5的所有标记分类为A 14.5和16之间的所有东西都是同一条染色体上的B.所以M5是A,M6可以归类为B。

我有一个标记排序位置的地图

M0  chr1    9
M1  chr1    10
M2  chr1    11
M3  chr1    12
M4  chr1    13
M5  chr1    14
M6  chr1    15
M7  chr1    16
M8  chr2    1
M9  chr2    2
M10 chr2    3
M11 chr2    4

所以给出了一个简单的主干

M1  A
M4  A
M7  B
M8  B
M10 A

如果可能,我想将地图上的其他标记归咎于此。

所以我想要的输出是

M1  A
M2  A
M3  A
M4  A
M5  A
M6  B
M7  B
M8  B
M9  B
M10 A

我是一名试图学习一点awk的生物学家,并且将这可能只是一个计算问题,我不知道从哪里开始。请帮忙。我可以访问unix集群来运行awk和perl。请注意,正确的插补只能在映射到同一染色体的标记之间进行。

1 个答案:

答案 0 :(得分:0)

你从来没有回答过我的任何问题,所以这是一个做出大量猜测的Perl解决方案

use strict;
use warnings 'all';
use autodie;

my (@markers, %markers);
{
    open my $fh, '<', 'markers.txt';

    while ( <$fh> ) {
        my @marker = split;
        push @markers, \@marker;
        $markers{$marker[0]} = $#markers;
    }
}

my ($i0, $i1);

open my $fh, '<', 'classes.txt';

while ( <$fh> ) {

    my ($marker, $class) = split;

    $i1 = $markers{$marker};
    my $m1 = $markers[$i1];
    push @$m1, $class;

    next unless defined $i0;

    my $m0 = $markers[$i0];

    next if $m0->[1] ne $m1->[1];          # Different chromosomes

    my $mid = ( $m0->[2] + $m1->[2] ) / 2; # Mid point between markers

    for my $m ( @markers[ $i0+1 .. $i1-1 ] ) {
        push @$m, $m->[2] <= $mid ? $m0->[3] : $m1->[3];
    }
}
continue {
    $i0 = $i1;
}

printf "%-4s%-8s%-4d%-s\n", @{$_}[0..2], $_->[3] // '' for @markers;

输出

M0  chr1    9   
M1  chr1    10  A
M2  chr1    11  A
M3  chr1    12  A
M4  chr1    13  A
M5  chr1    14  A
M6  chr1    15  B
M7  chr1    16  B
M8  chr2    1   B
M9  chr2    2   B
M10 chr2    3   A
M11 chr2    4