List 从冗余列表创建矩阵

List 从冗余列表创建矩阵,list,perl,matrix,List,Perl,Matrix,我有一个带有冗余列表的输入,如下所示: Sample1.14 Water Sample2.45 Air Sample1.16 Dirt Sample1.14 Water Sample2.45 Air Sample1.16 Dirt Sample1.14 Water Sample2.45 Air Sample1.16 Dirt Sample1.16 Dirt Sample1.14 Dirt Sample2.45 Air Sample1.16 Air 我创建了一个散列,计

我有一个带有冗余列表的输入,如下所示:

Sample1.14  Water
Sample2.45  Air
Sample1.16  Dirt
Sample1.14  Water
Sample2.45  Air
Sample1.16  Dirt
Sample1.14  Water
Sample2.45  Air
Sample1.16  Dirt
Sample1.16  Dirt
Sample1.14  Dirt
Sample2.45  Air
Sample1.16  Air
我创建了一个散列,计算每个样本给出结果的频率(水、空气、灰尘)(注意,这只是示例数据,但结构相同)

因为这是一个很糟糕的数据结构,我想把这些数据放到一个矩阵中,我有点不知所措

本例的期望输出或转置并不重要:

    Sample1.14  Sample2.45  Sample1.16
Air     0           4           1
Dirt    4           0           4
Water   3           0           0
我真的被困在这里了,任何帮助都将不胜感激!谢谢。

您可以将散列“咀嚼”到数组数组中,然后将其输入::pivot()或::pivot()。像这样:

use Acme::Tools;
my $data={
    'Dirt' => {
        'Sample1.16' => 4,
        'Sample1.14' => 1
    },
    'Air' => {
        'Sample1.16' => 1,
        'Sample2.45' => 4
    },
    'Water' => {
        'Sample1.14' => 3
    }
};
my @sample=uniq(sort map keys(%$_), values %$data);
my @element=sort keys %$data;
my $data2=[ map { my $x=$_; map [$x,$_,$$data{$x}{$_}||' 0'], @sample } @element ];
print tablestring([Acme::Tools::pivot($data2,"Element")]);
输出:

Element Sample1.14 Sample1.16 Sample2.45
------- ---------- ---------- ---------- 
Air              0          1          4
Dirt             1          4          0
Water            3          0          0

在Perl中创建唯一列表的最简单方法是将元素用作具有伪值的哈希键。填充散列后,可以使用
获得唯一的值列表

my %samples;
$samples{"some value"} = 1;
$samples{"some other value"} = 1;
$samples{"some value"} = 1;
my @samples = sort keys %samples;
如果要使Perl的行为类似于
awk
,可以使用带有单个空格参数的split函数。如果要将拆分结果分配给两个变量,可以使用Perl的列表表示法

my ($a, $b) = split ' ';
复杂的部分是建立表格。这可以通过
for
循环或
map
完成。使用
for
循环可能更容易阅读,但是
map
s允许更紧凑的表示法

my ($a, $b) = split ' ';
下面创建一个数组引用(方括号),并用
映射
表达式的返回列表填充数组,该列表以
$t
值为前缀。
map
表达式获取一张代码和一个列表,并为列表中的每个元素执行代码。当前列表元素的值在变量
$\uu
中可用

[ $t, map { $sampleHash{$t}{$_} or '0' } @samples ]
如果嵌套
映射
表达式,则必须为外部
$\uuz>指定一个名称,以便从内部
映射
访问它,因为内部
$\uz>会遮挡外部

在Perl中格式化表的基本方法是使用Perl的报告特性。为此,您必须定义一个交替线列表:首先是图案线,然后是值线

如果你把所有这些放在一起,你的例子就是这样

#! /usr/bin/perl
use strict;
use warnings;

my %sampleHash;
my %samples;
my %types;

while (<DATA>)
{
  chomp;
  my ($sample, $type) = split ' ';
  $sampleHash{$type}{$sample} += 1;
  $samples{$sample} = 1;
  $types{$type} = 1;
}

my @samples = sort keys %samples;
my @types = sort keys %types;

my @table =
    (['', @samples],
     map { my $t=$_; [ $t, map { $sampleHash{$t}{$_} or '0' } @samples ] } @types );

my $row;
format =
@<<<<<<  @||||||||||  @||||||||||  @||||||||||
@$row
.
for $row (@table) { write; }

__DATA__
Sample1.14  Water
Sample2.45  Air
Sample1.16  Dirt
Sample1.14  Water
Sample2.45  Air
Sample1.16  Dirt
Sample1.14  Water
Sample2.45  Air
Sample1.16  Dirt
Sample1.16  Dirt
Sample1.14  Dirt
Sample2.45  Air
Sample1.16  Air
#/usr/bin/perl
严格使用;
使用警告;
我的%sampleHash;
我的%样品;
我的%类型;
而()
{
咀嚼;
我的($sample,$type)=拆分“”;
$sampleHash{$type}{$sample}+=1;
$samples{$sample}=1;
$types{$type}=1;
}
my@samples=排序键%samples;
my@types=排序键%types;
我的@table=
(['',@样本],
map{my$t=$\[$t,map{$sampleHash{$t}{$\}或'0'}@samples]}@types);
我的美元行;
格式=

@您的示例的变量名错误。为了提供帮助,我们需要了解您的下游产品需要什么。如果您不知道,请稍后告诉我们您打算如何处理这些数据。你现在的结构非常典型。看看这些数据,我也会这么做。您可以按类型分组,然后计算样本数。这与您显示的表相对应,第一个键是行,第二个键是列。感谢您的提醒。下游我想创建一个矩阵结构的输出文件,以查看哪个样本最常以哪种类型出现,但由于分组是冗余的,我不太确定如何将数据转换为更具R可读性的格式。因此,您的问题归结为如何将其转换为CSV文件?显然如此……我希望了解一些关于如何在perl中正确创建矩阵的内容,但现在我觉得有点愚蠢。但似乎…是的。。。
#! /usr/bin/perl
use strict;
use warnings;

my %sampleHash;
my %samples;
my %types;

while (<DATA>)
{
  chomp;
  my ($sample, $type) = split ' ';
  $sampleHash{$type}{$sample} += 1;
  $samples{$sample} = 1;
  $types{$type} = 1;
}

my @samples = sort keys %samples;
my @types = sort keys %types;

my @table =
    (['', @samples],
     map { my $t=$_; [ $t, map { $sampleHash{$t}{$_} or '0' } @samples ] } @types );

my $row;
format =
@<<<<<<  @||||||||||  @||||||||||  @||||||||||
@$row
.
for $row (@table) { write; }

__DATA__
Sample1.14  Water
Sample2.45  Air
Sample1.16  Dirt
Sample1.14  Water
Sample2.45  Air
Sample1.16  Dirt
Sample1.14  Water
Sample2.45  Air
Sample1.16  Dirt
Sample1.16  Dirt
Sample1.14  Dirt
Sample2.45  Air
Sample1.16  Air
Sample1.14 Sample1.16 Sample2.45 Air 0 1 4 Dirt 1 4 0 Water 3 0 0