CPM Normalisation of a Count Matrix

Intermediate Computational Biology RNA-seq Normalisation Tabular Data Gene Expression
Significance:

Raw RNA-seq counts cannot be compared across samples, because a sample sequenced to
twice the depth will show roughly twice the counts for every gene regardless of biology. Counts Per
Million rescales each column by its own library size, making samples comparable — it is the first
transformation applied in essentially every differential expression workflow, and the input to the log
transforms that follow.

Statement

You are given a gene expression count matrix. The first line is a header with the gene
column label followed by sample names. Each subsequent line is a gene name followed by its integer
count in each sample.

Convert each count to Counts Per Million using the formula:

CPM = (count / library_size) * 1000000

where library_size is the total of all counts in that sample's column.

Print the header line unchanged, then one line per gene with the gene name followed by its CPM values,
each formatted to two decimal places. Use single spaces as separators throughout.

Input — read from standard input
Variable Type Description
header
line 1
str Column header, gene label followed by sample names, space separated
2 <= columns <= 10
rows
line 2..n
str One gene per line, gene name followed by integer counts
1 <= genes <= 500, counts are non-negative integers

These variables are already read for you in the starter code on the right.

Output

str the original header, then one line per gene with CPM values to two decimal places

Sample Cases
Sample 1
Input
gene s1 s2
GAPDH 500 1000
ACTB 300 600
TP53 200 400
Expected Output
gene s1 s2
GAPDH 500000.00 500000.00
ACTB 300000.00 300000.00
TP53 200000.00 200000.00
Each column is scaled by its own library size, so the two samples become directly comparable.
Sample 2
Input
gene ctrl
A 1
B 1
C 2
Expected Output
gene ctrl
A 250000.00
B 250000.00
C 500000.00
A single sample with a library size of four.

Submit also runs your code against 4 hidden test cases. Hidden inputs are never shown — if one fails you'll get its number and a description of the mismatch, not the data.

Constraints
  • 1 <= number of genes <= 500
  • 1 <= number of samples <= 9
  • All counts are non-negative integers
  • Every sample column has a library size of at least 1
  • Output the header exactly as it was received
Further Reading
  • Compute all library sizes first with a single pass down each column, before normalising anything.
  • Normalise per column, not per row — a common mistake is dividing by the row total.
  • f"{v:.2f}" keeps Python and R output byte-identical.

My Notes
Log in to save personal notes.
Console output will appear here when you click Run Code or Submit...
Expected: header (str), rows (remaining lines)
Next Problem
Greedy Motif Search