Operating System - HP-UX
1752591 Members
3670 Online
108788 Solutions
New Discussion юеВ

Re: matrix conversion in shell scripting

 
Gopi Kishore m
Occasional Advisor

matrix conversion in shell scripting

Hi,
Today I got a requirement for matrix conversion,
rows to columns

The input file for this is something like below:
------------------------------------------
VOUCHER_TYPE BUCKET_TYPE VOUCHER_AMT VALIDITY
1000 1 0 4500
1000 4 1000 10
1000 5 0 1
1000 7 700 1


and i need the output as below:


------------------------------------------
v_type b1_amt b1_val b2_amt b2_val b3_amt b3_val b4_amt b4_val b5_amt b5_val b6_amt b6_val b7_amt b7_val
1000 0 4500 0 0 0 0 1000 10 0 1 0 0 700 1


I am trying to do the same with awk command and while loop but iam not getting desired output please give me some solution.
...Gopi
5 REPLIES 5
Steven Schweda
Honored Contributor

Re: matrix conversion in shell scripting

> Today I got a requirement for matrix
> conversion, rows to columns

Congratulations.

> and i need the output as below:

This must be some new definition of "rows to
columns", because you seem to be converting
a four-by-four array of values into a set of
fifteen different values (in no obvious
order, with no obvious structure).

> [...] please give me some solution.

Please provide a problem description which
makes more sense.

Then send money.
James R. Ferguson
Acclaimed Contributor

Re: matrix conversion in shell scripting

Hi Gopi:

Using Perl, we could do something like this:

# cat ./mymatrix
#!/usr/bin/perl
use strict;
use warnings;
my ($i, $j, $square, @line);
undef $/;
$_ = ;
push @line, split;
$square = int(sqrt @line);
for ($i=0; $i<$square; $i++) {
for ($j=0; $j<@line; $j+=$square) {
printf "%s ", $line[$i+$j];
}
print "\n";
}
__DATA__
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15

...which when executed, transforms the maxtix in the file named DATA to:

0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15

Regards!

...JRF...
James R. Ferguson
Acclaimed Contributor

Re: matrix conversion in shell scripting

Hi (again):

Use this version and you can pass any file as long as the number of rows equals the number of columns. That is, the matrix is a square.

# cat ./mymatrix
#!/usr/bin/perl
use strict;
use warnings;
my ($i, $j, $square, @line);
while (<>) {
chomp;
push @line, split;
}
$square = int(sqrt @line);
for ($i=0; $i<$square; $i++) {
for ($j=0; $j<@line; $j+=$square) {
printf "%s ", $line[$i+$j];
}
print "\n";
}

...run as:

# ./mymatrix file

Regards!

...JRF...
James R. Ferguson
Acclaimed Contributor

Re: matrix conversion in shell scripting

Hi (again):

Actually, we can invert rectangular matrices with just a slight modification:

# cat ./mymatrix
#!/usr/bin/perl
use strict;
use warnings;
my ($i, $j, $seen, $side, @line);
while (<>) {
chomp;
push @line, split;
if (! $seen) {
$seen++;
$side = @line; #...nbr elements in 1st row...
}
}
for ($i=0; $i<$side; $i++) {
for ($j=0; $j<@line; $j+=$side) {
printf "%s ", $line[$i+$j];
}
print "\n";
}
1;

Now you can have transformations like:

1 2 3
4 5 6
7 8 9

to:

1 4 7
2 5 8
3 6 9

and:

1 2 3 4 5
6 7 8 9 0

to:

1 6
2 7
3 8
4 9
5 0

and:

1 2
3 4
5 6
7 8
9 0

to:

1 3 5 7 9
2 4 6 8 0

Regards and Enjoy!

...JRF...
Hein van den Heuvel
Honored Contributor

Re: matrix conversion in shell scripting

Nice generic solutions.
The GAWK manual specificically has a rotate array example:
http://www.math.utah.edu/docs/info/gawk_12.html#SEC121

But this is a more specific example.

Here is some awk that will do the job...

----------------
NR > 1 {
amt[$2] = $3;
val[$2] = $4;
if ($2 > values) values = $2;
type = $1;
}
END {
head = "type";
line = type;
for (i = 1; i <= values; i++) {
head = head " amt" i " val" i
a = v = 0;
if (i in val) { a = amt[i]; v = val[i] }
line = line " " a " " v;
}
print head;
print line;
}
---------

So for each line execpt the first it sticks the critical columns in arrays indexed by the 'bucket_type' column.
At the end it builds a header line and data line for each present type number, filling out with zeroes otherwise.

Now I suspect that the usage is more involved.
For example more 'voucher_types', each together.
In that case you'd need to print at the end, but also at each voucher type change.
So you need a new header, when the number of columns change? I don't know.
The code below gives a more complex example handling multiple voucher_types in a single file.

Cheers,
Hein


NR == 1 { next }
$1 != type {
if (values) {
head = "type";
line = type;
for (i = 1; i<= values; i++) {
head = head " amt" i " val" i
a = v = 0;
if (i in val) { a = amt[i]; v = val[i]; delete amt[i]; delete val[i] }
line = line " " a " " v;
}
print head;
print line;
values = 0;
}
type = $1;
}
$1 == type {
amt[$2] = $3;
val[$2] = $4;
if ($2 > values) values = $2;
}
END {
head = "type";
line = type;
for (i = 1; i <= values; i++) {
head = head " amt" i " val" i
a = v = 0;
if (i in val) { a = amt[i]; v = val[i]; delete amt[i]; delete val[i] }
line = line " " a " " v;
}
print head;
print line;
}