How to insert zero elements in sparse matrix using shell, bash, awk, sed

I need to insert the zero elements in any sparse matrix in the Matrix Market format (but already without the headers).

The first column is the number of the ROW, the second columns is the number of the COLUMN and the third column is the VALUE of the element.

I'm using a 2 x 3 matrix for testing it. But i need to be able to do this to any dimension matrix, m x n.

The number of rows, columns and non-zero elements of each matrix are already in separated variables.

I've used bash sed and awk to work with these matrices until now.

Input file:

1 1 1.0000
1 2 2.0000
2 1 4.0000
2 2 5.0000
2 3 6.0000

ROWS and COLUMNS are integer %d and VALUES are float %.4f

Here only one element is zero (row 1 column 3), the line that represents it is omitted.

So, how can i insert this line???

Output file:

1 1 1.0000
1 2 2.0000
1 3 0.0000
2 1 4.0000
2 2 5.0000
2 3 6.0000

An empty 2 x 3 matrix would be like this:

1 1 0.0000
1 2 0.0000
1 3 0.0000
2 1 0.0000
2 2 0.0000
2 3 0.0000

Another example, a 3 x 4 matrix with more zero elements.

Input file:

1 2 9.7856
1 4 4.2311
2 1 3.4578
2 2 45.1231
2 3 -12.0124
3 4 0.1245

Output file:

1 1 0.0000
1 2 9.7856
1 3 0.0000
1 4 4.2311
2 1 3.4578
2 2 45.1231
2 3 -12.0124
2 4 0.0000
3 1 0.0000
3 2 0.0000
3 3 0.0000
3 4 0.1245

I hope you can help me. I already spent more then 3 days with trying a solution.

The best i got was this:

for((i=1;i<3;i++))
do
    for((j=1;j<4;j++))
    do
        awk -v I=${i} -v J=${j} 'BEGIN{FS=" "}
                            {if($1==I && $2==J)
                                    printf("%d %d %.4f\n",I,J,$3)
                            else
                                    printf("%d %d %d\n",I,J,0)
                            }' ./etc/A.2
        done
done

But its not efficient and prints lots of non desired lines:

1 1 1.0000
1 1 0
1 1 0
1 1 0
1 1 0
1 2 0
1 2 2.0000
1 2 0
1 2 0
1 2 0
1 3 0
1 3 0
1 3 0
1 3 0
1 3 0
2 1 0
2 1 0
2 1 4.0000
2 1 0
2 1 0
2 2 0
2 2 0
2 2 0
2 2 5.0000
2 2 0
2 3 0
2 3 0
2 3 0
2 3 0
2 3 6.0000

Please! Help me! Thank you all!

Answers


If you want to specify the max "I" and "J" values:

# cat tst.awk
{ a[$1,$2] = $3 }
END {
    for (i=1;i<=I;i++)
        for (j=1;j<=J;j++)
            print i, j, ( (i,j) in a ? a[i,j] : "0.0000" )
}

$ awk -v I=2 -v J=3 -f tst.awk file
1 1 1.0000
1 2 2.0000
1 3 0.0000
2 1 4.0000
2 2 5.0000
2 3 6.0000

If you'd rather the tool just figures it out (won't work for an empty file or if the max desired values are otherwise never populated):

$ cat tst2.awk
NR==1 { I=$1; J=$2 }

{
    a[$1,$2] = $3
    I = (I > $1 ? I : $1)
    J = (J > $2 ? J : $2)
}

END {
    for (i=1;i<=I;i++)
        for (j=1;j<=J;j++)
            print i, j, ( (i,j) in a ? a[i,j] : "0.0000" )
}

$ awk -f tst2.awk file
1 1 1.0000
1 2 2.0000
1 3 0.0000
2 1 4.0000
2 2 5.0000
2 3 6.0000

Need Your Help

Process lines between patterns

bash sed awk

I'm trying to extract some information from a very huge document. The file follows this pattern:

problem with function call in c++

c++ function main result

I have a problem with my program, I work actually on interpolation with Cubic BSplines, but when I call my interpolate function in main() I get a wrong result, and when I write directly the functio...