0

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 !

6
  • 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 '17 at 0:22
  • You shouldn't write $samples, use samples instead. Using a dollar sign gives you the samplesth column's value. – onur güngör Apr 29 '17 at 7:22
  • In summary, please define your problem clearer. – onur güngör Apr 29 '17 at 7:23
  • Sorry, i have tried to make the question clear. – CN_229133 Apr 29 '17 at 8:01
  • show the expected result – RomanPerekhrest Apr 29 '17 at 8:07
0
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
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.