Reputation: 19
I have been searching around for some ways to transpose a large csv file using Perl, but can't get it right with my loops.
There is a header row with 7 columns (I have 200+ columns actually). The first 3 columns are fixed and the subsequent columns are numbers. If the account amount is 0, skip and do not transpose.
Source Data:
Name,Age,Gender,Acct1,Acct2,Acct3,Acct4
Jack,12,M,10,20,0,999
Mary,20,F,40,50,0,111
Transposed Data:
Column_ID,Name,Age,Gender,Acct
4,Jack,12,M,10
5,Jack,12,M,20
7,Jack,12,M,999
4,Mary,20,F,40
5,Mary,20,F,50
7,Mary,20,F,111
Upvotes: 1
Views: 803
Reputation: 8711
Using Perl one-liner
$ cat liquan.txt
Name,Age,Gender,Acct1,Acct2,Acct3,Acct4
Jack,12,M,10,20,0,999
Mary,20,F,40,50,0,111
$ perl -F, -lane ' BEGIN { print "Column_ID,Name,Age,Gender,Acct" } for(3..$#F) { if($F[$_]!=0 and $.>1) { print $_+1,",$F[0],$F[1],$F[2],",$F[$_] }}' liquan.txt
Column_ID,Name,Age,Gender,Acct
4,Jack,12,M,10
5,Jack,12,M,20
7,Jack,12,M,999
4,Mary,20,F,40
5,Mary,20,F,50
7,Mary,20,F,111
$
Upvotes: 1
Reputation: 558
I'm guessing this source data is in a file, rather than handily parsed into a perl assignment.
#!/usr/bin/perl
use strict;
use warnings;
print "Column_ID,Name,Age,Gender,Acct\n";
foreach my $file (@ARGV) {
open my $FH, '<', $file
or warn("Couldn't open $file: $!\n"), next;
while (<$FH>) {
chomp;
my @cols = split /\,/;
my @retained = @rows[0 .. 2];
foreach my $col (3 .. $#cols) {
print join(',', 1 + $col, @retained, $cols[$col]) . "\n"
if $cols[$col];
}
}
}
Upvotes: 1
Reputation: 5962
Assuming that you have read the CSV into an array of arrays with one of the CSV modules (please don't parse CSV yourself), I would proceed like this:
#!/usr/bin/perl
use strict;
use warnings;
my @rows = (
['Jack',12,'M',10,20,0,999],
['Mary',20,'F',40,50,0,111],
);
my @output;
foreach my $row (@rows) {
foreach my $col (3..$#{$row}) {
if ($row->[$col] != 0) {
push(@output, [$col + 1, @{$row}[0,1,2,$col]]);
}
}
}
foreach my $row (@output) {
print join(',', @{$row}), "\n";
}
Example output:
$ perl dummy.pl
4,Jack,12,M,10
5,Jack,12,M,20
7,Jack,12,M,999
4,Mary,20,F,40
5,Mary,20,F,50
7,Mary,20,F,111
Upvotes: 0