首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl排序基因组位置

Perl排序基因组位置
EN

Stack Overflow用户
提问于 2014-07-18 14:26:48
回答 5查看 458关注 0票数 1

我有染色体格式中基因组位置的列表:开始-结束。

例如

代码语言:javascript
复制
chr1:100-110
chr1:1000-1100
chr1:200-300
chr10:100-200
chr2:100-200
chrX:100-200

我想按染色体数目和数字起始位置来排序,得到:

代码语言:javascript
复制
chr1:100-110
chr1:200-300
chr1:1000-1100
chr2:100-200
chr10:100-200
chrX:100-200

在perl中,有什么好的、有效的方法来做到这一点呢?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-08-11 21:43:23

只需使用模块Sort::Keys::Natural

代码语言:javascript
复制
use strict;
use warnings;

use Sort::Key::Natural qw(natsort);

print natsort <DATA>;

__DATA__
chr1:100-110
chr1:1000-1100
chr1:200-300
chr10:100-200
chr2:100-200
chrX:100-200
chrY:100-200
chrX:1-100
chr10:100-150

产出:

代码语言:javascript
复制
chr1:100-110
chr1:200-300
chr1:1000-1100
chr2:100-200
chr10:100-150
chr10:100-200
chrX:1-100
chrX:100-200
chrY:100-200
票数 1
EN

Stack Overflow用户

发布于 2014-07-18 15:07:59

您可以通过提供自定义比较器对此进行排序。您似乎希望有一个两个级别的值作为排序键,因此您的自定义比较器将导出一行的键,然后进行比较:

代码语言:javascript
复制
# You want karyotypical sorting on the first element,
# so set up this hash with an appropriate normalized value
# per available input:

my %karyotypical_sort = (
    1 => 1,
    ...
    X => 100,
);

sub row_to_sortable {
    my $row = shift;
    $row =~ /chr(.+):(\d+)-/; # assuming match here! Be careful
    return [$karyotypical_sort{$1}, $2];
}

sub sortable_compare {
    my ($one, $two) = @_;

    return $one->[0] <=> $two->[0] || $one->[1] <=> $two->[1];
    # If first comparison returns 0 then try the second
}

@lines = ...

print join "\n", sort {
    sortable_compare(row_to_sortable($a), row_to_sortable($b))
} @lines;

由于计算将稍微繁琐(字符串操作并不是免费的),而且您可能正在处理大量数据(基因组!)如果执行Schwartzian变换,很可能会注意到性能的提高。执行此操作的方法是预先计算行的排序键,然后使用它进行排序,最后删除其他数据:

代码语言:javascript
复制
@st_lines = map { [ row_to_sortable($_), $_ ] } @lines;
@sorted_st_lines = sort { sortable_compare($a->[0], $b->[0]) } @st_lines;
@sorted_lines = map { $_->[1] } @sorted_st_lines;

或合并:

代码语言:javascript
复制
print join "\n",
    map { $_->[1] }
    sort { sortable_compare($a->[0], $b->[0]) }
    map { [ row_to_sortable($_), $_ ] } @lines;
票数 1
EN

Stack Overflow用户

发布于 2014-07-18 15:15:01

在我看来,你似乎想按以下顺序排序:

  1. 按染色体数目
  2. 然后按起始位置
  3. 然后(也许)到最后的位置。

所以,也许是这样的一种定制类型:

代码语言:javascript
复制
use strict;
use warnings;

print sort {
    my @a = split /chr|:|-/, $a;
    my @b = split /chr|:|-/, $b;
    "$a[1]$b[1]" !~ /\D/ ? $a[1] <=> $b[1] : $a[1] cmp $b[1]
      or $a[2] <=> $b[2]
      or $a[3] <=> $b[3]
} <DATA>;

__DATA__
chr1:100-110
chr1:1000-1100
chr1:200-300
chr10:100-200
chr2:100-200
chrX:100-200
chrY:100-200
chrX:1-100
chr10:100-150

产出:

代码语言:javascript
复制
chr1:100-110
chr1:200-300
chr1:1000-1100
chr2:100-200
chr10:100-150
chr10:100-200
chrX:1-100
chrX:100-200
chrY:100-200
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24827382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档