【问题标题】:Extract information from lines and columns in PERL从 PERL 中的行和列中提取信息
【发布时间】:2014-03-11 01:05:36
【问题描述】:

我有一个包含多行多列的大文件。每行有许多列,并且许多行在同一位置具有相同的名称。例如

 A  C  Z  Y  X
 A  C  E  J
 B  E  K  L  M

查找在某个位置共享相同项目的所有行的最佳方法是什么?比如我想知道有2个A、2个C、1个D等等,都是按列排序的。

我真的是 Perl 的新手,所以我在这方面付出了很多努力,因此感谢任何提示。

我到了这一点:

#!/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

请注意,第一个项目首先出现,并且在各行之间共享时,不会在后续行中再次显示。

编辑:根据 cmets 中的问题,我更改了数据集和输出。注意出现了两个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

【问题讨论】:

  • 请显示您希望看到的输出。
  • @Borodin 完成,我希望现在很清楚
  • 那么如果一个符号出现,它总是在同一个位置? (那为什么位置在要求中完全相关?只是说你想计算符号?)
  • @tripleee,可能会发生某些行共享相同的名称,但由于它们位于不同的列中而无法分组。例如A B E 和 X E Z。在这种情况下,我想将E 都算作不同的位置
  • 好吧,我认为职位之间的区别很难实现

标签: arrays perl


【解决方案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

【讨论】:

  • 感谢您的帮助。请查看我的编辑以获取更新!再次感谢
  • @Sosi 我的输出已经按列分隔数据。第一列在第 1 行,第 2 列在第 2 行,依此类推。
  • 一个小评论(或者我理解错了):你用''分割行的地方,你应该用'\t'替换,因为它们是制表符分隔的。我在示例中使用了空格来避免在任何地方写 '\t'
  • @Sosi split ' ' 是一种特殊情况,它实际上等同于 split /\s+/ 并具有跳过任何前导空格的额外好处。只需阅读split 文档了解详细信息。换句话说,它也会处理标签。
【解决方案2】:

也许以下内容会有所帮助:

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

【讨论】:

    猜你喜欢
    • 2019-05-09
    • 1970-01-01
    • 1970-01-01
    • 2014-11-23
    • 1970-01-01
    • 2011-02-19
    • 2021-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多