我有一个包含多行和多列的巨大文件。每一行都有许多列,许多行在同一位置具有相同的名称。 E.g。
A C Z Y X
A C E J
B E K L M
查找在特定位置共享相同项目的所有行的最佳方法是什么?例如,我想知道有2个A,2个C,1个D等,都按列排序。
我
我达到了这一点:
#!/usr/local/bin/perl -w
use strict;
my $path='My:\Path\To\My\File.txt';
my $columns;
my $line;
open (FILE,$path), print "Opened!\n" or die ("Error opening");
while (<FILE>)
{
@line=split('\t',$_);
}
close FILE;
这个输出可以是另一个TSV,只检查文件直到第5列,从上到下排序,如:
A 2
C 2
Z 1
Y 1
E 1
J 1
B 1
E 1
K 1
L 1
请注意,第一个项目首先出现,当在行间共享时,不会再显示后续行。
编辑:根据评论中的问题,我更改了数据集和输出。请注意,出现两个E:一个属于第三列,另一个属于第二列。
Edit2:或者,这也可以逐列分析,从而在第一列中显示结果,然后在第二列中显示结果,依此类推,只要它们清楚地分开即可。像
这样的东西 "1st" "col"
A 2
B 1
"2nd" "col"
C 2
E 1
"3rd" "col"
Z 1
E 1
K 1
"4th" "col"
Y 1
J 1
L 1
答案 0 :(得分:1)
我没有完全理解所需输出的格式,因此下面的脚本会输出第一行第一列的所有数据,依此类推。这可以很容易地修改为您想要的格式,但它是如何首先对数据进行累积然后再处理它的快速起点。
use strict;
use warnings;
use autodie;
my $path='My:\Path\To\My\File.txt';
open my $fh, '<', $path;
my @data;
# while (<$fh>) { Switch these lines when ready for real data
while (<DATA>) {
my @row = split ' ';
for my $col (0..$#row) {
$data[$col]{$row[$col]}++;
}
}
for my $coldata (@data) {
for my $letter (sort keys %$coldata) {
print "$letter $coldata->{$letter} ";
}
print "\n";
}
close $fh;
__DATA__
A C Z Y X
A C D J
B E K L M
输出
A 2 B 1
C 2 E 1
D 1 K 1 Z 1
J 1 L 1 Y 1
M 1 X 1
答案 1 :(得分:0)
也许以下内容会有所帮助:
use strict;
use warnings;
my $path = 'My:\Path\To\My\File.txt';
my %hash;
open my $fh, '<', $path or die $!;
while (<$fh>) {
my @cols = split ' ', $_, 5;
$hash{$_}{ $cols[$_] || '' }++ for 0 .. 3;
}
close $fh;
for my $key ( sort { $a <=> $b } keys %hash ) {
print "Col ", $key + 1, "\n";
print "$_ $hash{$key}{$_}\n"
for sort { $hash{$key}->{$b} <=> $hash{$key}->{$a} } grep $_,
keys %{ $hash{$key} };
}
数据集输出:
Col 1
A 2
B 1
Col 2
C 2
E 1
Col 3
Z 1
K 1
E 1
Col 4
J 1
L 1
Y 1