perl - Create Matrix from redundant list -
i have input redundant list looks this:
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
i created hash counts how each sample gives result water,air,dirt (note example data structure identical).
use warnings; use strict; $input = "examplesample"; open(read,$input) || die "coult not read $input: $!"; %samplehash; while (<read>) { chomp; @temp = split("\t",$_); $sample = $temp[0]; $type = $temp[1]; $samplehash{$type}{$sample} += 1; }
this works intended , gives output:
$var1 = { 'dirt' => { 'sample1.16' => 4, 'sample1.14' => 1 }, 'air' => { 'sample1.16' => 1, 'sample2.45' => 4 }, 'water' => { 'sample1.14' => 3 } };
since quiet bad data structure further downstream stuff put data matrix lost at.
desired output or transposed of example, not matter:
sample1.14 sample2.45 sample1.16 air 0 4 1 dirt 4 0 4 water 3 0 0
i stuck here, appreciated! thanks.
the easiest way create unique list in perl use elements hash keys dummy values. after filling hash can unique list of values keys
.
my %samples; $samples{"some value"} = 1; $samples{"some other value"} = 1; $samples{"some value"} = 1; @samples = sort keys %samples;
if want make perl behaving awk
, can use split function single space argument. , if want assign result of split 2 variables can use perl's list notation.
my ($a, $b) = split ' ';
the complicated part build table. can done for
loops or map
. use of for
loops might easier read, map
s allow more compact notation.
the following creates array reference (square brackets) , fills array return list of map
expression, prefixed $t
value. map
expression takes pice of code , list , executes code each element of list. value of current list element available in variable $_
.
[ $t, map { $samplehash{$t}{$_} or '0' } @samples ]
if nest map
expressions, have give outer $_
name access inner map
, because inner $_
shadows outer.
a basic way format tables in perl use perl's report feature perlform. have define list of alternating lines: first pattern line , value line.
if put example becomes this
#! /usr/bin/perl use strict; use warnings; %samplehash; %samples; %types; while (<data>) { chomp; ($sample, $type) = split ' '; $samplehash{$type}{$sample} += 1; $samples{$sample} = 1; $types{$type} = 1; } @samples = sort keys %samples; @types = sort keys %types; @table = (['', @samples], map { $t=$_; [ $t, map { $samplehash{$t}{$_} or '0' } @samples ] } @types ); $row; format = @<<<<<< @|||||||||| @|||||||||| @|||||||||| @$row . $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
which outputs this
sample1.14 sample1.16 sample2.45 air 0 1 4 dirt 1 4 0 water 3 0 0
note: desired output not match input.
in order read file have keep code using open
. have used __data__
section simplify example in order mcve.
Comments
Post a Comment