# Read/manipulate column data for nth recurrence

I have a matrix where I have counts for genes in different samples

Col1: GeneName
Col2: Length
Col3;Col4;Col5; Counts for genes in sampleA/sampleB/sampleC
Col6;Col7;Col8; Total counts in sampleA/sampleB/sampleC


This is an example matrix.

A1BG    1758    53  4373    207 46005749    43849471    31554941
A1BG-AS1    2126    5   88  12  46005749    43849471    31554941
A1CF    9695    8882    3522    437 46005749    43849471    31554941
A2M 5399    15963   12325   7227    46005749    43849471    31554941
A2M-AS1 6660    50  33  36  46005749    43849471    31554941


I want to divide counts_sampleA / (total_counts_sampleA*Length), and so on for other samples

cat inFile | awk 'BEGIN {OFS="\t"} { print $1,$2,$3/($6*$2),$4/($7*$2),$5/($8*$2) }' This is the expected result A1BG 1758 6.55307e-10 5.67278e-08 3.73151e-09 A1BG-AS1 2126 5.11204e-11 9.43963e-10 1.78875e-10 A1CF 9695 1.99136e-08 8.28471e-09 1.42845e-09 A2M 5399 6.42672e-08 5.20606e-08 4.24207e-08 A2M-AS1 6660 1.63186e-10 1.12999e-10 1.71301e-10  Works fine, but isn't good when the matrix is large. How would I write if there are 100 samples, where column3-colum102 would have geneCountinEachSample and Coulmn103-column202 would have totalCountinEachSample. I want to use it with a for loop, so when there are more samples, it works with an arbitrary number of columns ? cat inFile | awk 'BEGIN {OFS="\t"} { row=NF; samples=3; size=$samples+2; for ( i=3; i<=$size; i++); END print$i/$[$i+$samples] }'  Any suggestion on how to make this work. Thanks ! • Is the sample always 3? As when say it is 4 or more, then you run out of columns to divide with. Also, your comments "(col3/col6)*col2" DONOT match the awk expression "$3/($6*$2)". That is why you need to supply input and expected output for various values of sample.
– user218374
Apr 29, 2017 at 0:22
• You shouldn't write $samples, use samples instead. Using a dollar sign gives you the samplesth column's value. Apr 29, 2017 at 7:22 • In summary, please define your problem clearer. Apr 29, 2017 at 7:23 • Sorry, i have tried to make the question clear. Apr 29, 2017 at 8:01 • show the expected result Apr 29, 2017 at 8:07 ## 2 Answers Well, you almost got the answer there: awk ' {cols=((NF/2) + 1) for (i=1; i <= cols; i++) { if (i >= 3) { count_index= i + cols - 2 printf("%s\t", 1.0 *$i / ($count_index *$2))
} else {
printf("%s\t", $i) } } printf("\n") }' inFile  Note that using cat file | awk ... is suboptimal, awk handles files as arguments directly; even so, doing awk ... < infile would be better than a useless use of cat. perl -F'\s+' -lane '$,="\t"; # OFS made a TAB
my($gN,$gL) = splice @F, 0, 2; # store gene name & length
print $gN,$gL, map { sprintf "%.5e", $F[$_] / ( $F[$_+@F/2] * \$gL ) } 0 .. @F/2-1;
' gene_samples.file


• FS is set to one or more whitespace.
• ORS = RS = \n
• @F holds fields for a given record.
• splice breaks away 2 elements starting from offset 0 and reduces the array size as well.
• From OP spec, from what remains in @F is even numbered elements. The first half is counts_for_each_sample & the latter half is total_count_for_each_sample.

## Results

A1BG      1758  6.55307e-10  5.67278e-08  3.73151e-09
A1BG-AS1  2126  5.11204e-11  9.43963e-10  1.78875e-10
A1CF      9695  1.99136e-08  8.28471e-09  1.42845e-09
A2M       5399  6.42672e-08  5.20606e-08  4.24207e-08
A2M-AS1   6660  1.63186e-10  1.12999e-10  1.71301e-10