我有下一个数据:
miRNA17 70 105 dvex699824 12 233
miRNA17 21 60 dvex699824 42 20
miRNA17 55 89 dvex699824 6 40
miRNA18 58 85 dvex701176 119 92
miRNA17 66 105 dvex703815 35 75
miRNA17 31 71 dvex703815 43 83
miRNA17 39 79 dvex703815 43 83
miRNA2 28 56 dvex731981 313 286
miRNA17 10 70 dvex735428 142 203
miRNA17 29 91 dvex735428 213 152
miRNA17 66 105 dvex735668 163 125
问题是:如果我有这6列,我需要按照这个规则进行分组和打印:
相同的miRNA ## \ t无论如何都不是\ t相同的dvex #### \ t取下面\ t取最高
例如,这是可能的输出:
miRNA17 21 105 dvex699824 6 233
miRNA18 58 85 dvex701176 119 92
miRNA17 31 105 dvex703815 35 83
miRNA2 28 56 dvex731981 313 286
miRNA17 10 105 dvex735428 142 203
通过Hashes-keys作为数组解决此问题的可能方法是什么?
答案 0 :(得分:2)
按顺序处理文件更有效率,而不是首先将所有内容都加载到大数组中。以下是这样的解决方案:
my @output_line = split / /, <IN_FILE>;
while (<IN_FILE>)
{
my @current_line = split / /, $_;
if ($current_line[0] ne $output_line[0])
{
printf OUT_FILE "%-8s %5d %5d %-10s %3d %3d\n", @output_line;
@output_line = @current_line;
}
else
{
$output_line[1] = $current_line[1] if ($current_line[1] < $output_line[1]);
$output_line[2] = $current_line[2] if ($current_line[2] > $output_line[2]);
$output_line[4] = $current_line[4] if ($current_line[4] < $output_line[4]);
$output_line[5] = $current_line[5] if ($current_line[5] > $output_line[5]);
}
}
printf OUT_FILE "%-8s %5d %5d %-10s %3d %3d\n", @output_line;
警告:您的问题表明输出行应该具有“相同的dvex ####”。但是,您的示例输出未显示此信息。因此我忽略了这个要求。但是,您可以通过在if
语句中添加另一个条件来轻松引入该要求。
第二个警告:这种方法还要求将分组为彼此相邻的行,就像它们在样本数据中一样。
答案 1 :(得分:1)
Perl脚本:
use strict;
# Not shown... Parse the data file, stuff into an array of arrays.
my @data = (
[ 'miRNA17', 70, 105, 'dvex699824', 12, 233 ],
[ 'miRNA17', 21, 60, 'dvex699824', 42, 20 ],
[ 'miRNA17', 55, 89, 'dvex699824', 6, 40 ],
[ 'miRNA18', 58, 85, 'dvex701176', 119, 92 ],
[ 'miRNA17', 66, 105, 'dvex703815', 35, 75 ],
[ 'miRNA17', 31, 71, 'dvex703815', 43, 83 ],
[ 'miRNA17', 39, 79, 'dvex703815', 43, 83 ],
[ 'miRNA2', 28, 56, 'dvex731981', 313, 286 ],
[ 'miRNA17', 10, 70, 'dvex735428', 142, 203 ],
[ 'miRNA17', 29, 91, 'dvex735428', 213, 152 ],
[ 'miRNA17', 66, 105, 'dvex735668', 163, 125 ]
);
my %results;
foreach my $record (@data) {
my ($mirna, $col2, $col3, $dvex, $col5, $col6) = @$record;
$results{$mirna}{$dvex}{col2} = $col2; # don't care.
$results{$mirna}{$dvex}{col3} = $col3; # don't care.
$results{$mirna}{$dvex}{col5} = $col5
if not $results{$mirna}{$dvex}{col5} or $results{$mirna}{$dvex}{col5} > $col5;
$results{$mirna}{$dvex}{col6} = $col6
if not $results{$mirna}{$dvex}{col6} or $results{$mirna}{$dvex}{col6} < $col6;
}
foreach my $mirna (keys %results) {
foreach my $dvex (sort keys %{$results{$mirna}}) {
printf "%-8s %5d %5d %-10s %3d %3d\n",
$mirna, $results{$mirna}{$dvex}{col2}, $results{$mirna}{$dvex}{col3},
$dvex, $results{$mirna}{$dvex}{col5}, $results{$mirna}{$dvex}{col6};
}
}
1;
输出:
miRNA2 28 56 dvex731981 313 286
miRNA17 55 89 dvex699824 6 233
miRNA17 39 79 dvex703815 35 83
miRNA17 29 91 dvex735428 142 203
miRNA17 66 105 dvex735668 163 125
miRNA18 58 85 dvex701176 119 92
答案 2 :(得分:1)
这是一个简单的脚本,可以生成您想要的输出,但它会超出您的要求状态,因为它还会检查第2列和第3列的最小值/最大值。
我使用List::Util来获取最小/最大值,这纯粹是方便的。从v5.7.3开始,该模块是核心,所以不应该出现问题。使用Text::CSV是谨慎的,但可能不需要,具体取决于您的数据。假设列中没有非制表符空格,可以使用split
,这将删除模块依赖性。
use strict;
use warnings;
use Text::CSV;
use List::Util qw(min max);
my $csv = Text::CSV->new({
sep_char => "\t",
eol => $/, # required for $csv->print
binary => 1,});
my %data;
my @order;
# *DATA and *STDOUT represent file handles, and can be replaced with
# any other file handle as you require. DATA is used here for simplicity.
#
while (my $row = $csv->getline(*DATA)) {
my ($mir, $dv) = @{$row}[0,3];
my $field = "$mir/$dv";
unless (defined $data{$field}) { # new fields are stored as-is
push @order, $field; # preserving original order of input
$data{$field} = $row;
next;
}
$data{$field}[1] = min($data{$field}[1], $row->[1]);
$data{$field}[2] = max($data{$field}[2], $row->[2]);
$data{$field}[4] = min($data{$field}[4], $row->[4]);
$data{$field}[5] = max($data{$field}[5], $row->[5]);
}
for my $field (@order) {
$csv->print(*STDOUT, $data{$field});
}
__DATA__
miRNA17 70 105 dvex699824 12 233
miRNA17 21 60 dvex699824 42 20
miRNA17 55 89 dvex699824 6 40
miRNA18 58 85 dvex701176 119 92
miRNA17 66 105 dvex703815 35 75
miRNA17 31 71 dvex703815 43 83
miRNA17 39 79 dvex703815 43 83
miRNA2 28 56 dvex731981 313 286
miRNA17 10 70 dvex735428 142 203
miRNA17 29 91 dvex735428 213 152
miRNA17 66 105 dvex735668 163 125
<强>输出:强>
miRNA17 21 105 dvex699824 6 233
miRNA18 58 85 dvex701176 119 92
miRNA17 31 105 dvex703815 35 83
miRNA2 28 56 dvex731981 313 286
miRNA17 10 91 dvex735428 142 203
miRNA17 66 105 dvex735668 163 125
注意输出与您的输出不匹配,因为您无法区分样本输入的最后一行的dvex数字。