Starting with a TPM expression matrix, if you convert the data into long format (tidy) then you can use lm the way you have mentioned. Here is an example with dummy data:
# create TPM matrix with 100 genes and 5 samples
df <- data.frame(names = paste("gene", 1:100, sep = "_"),
matrix(rnorm(500, 100, 3),
nrow = 100,ncol = 5))
colnames(df) <- c("genes", paste("dose", 0:4, sep = "_"))
head(df)
genes dose_0 dose_1 dose_2 dose_3 dose_4
1 gene_1 101.20585 100.89322 99.97335 99.00884 97.33674
2 gene_2 98.53161 96.90215 102.41959 104.73646 97.76265
3 gene_3 96.44946 102.37975 95.46167 104.92316 106.92175
4 gene_4 93.86651 96.95756 102.77468 100.03604 102.40414
5 gene_5 98.92690 100.13105 101.63389 99.56012 98.30926
6 gene_6 101.38702 99.75266 103.63846 100.90292 99.08118
# convert data into long format
library(reshape2)
df1 <- melt(df, id.vars = "genes")
colnames(df1) <- c("genes", "dose", "tpm")
head(df1)
genes dose tpm
1 gene_1 dose_0 101.20585
2 gene_2 dose_0 98.53161
3 gene_3 dose_0 96.44946
4 gene_4 dose_0 93.86651
5 gene_5 dose_0 98.92690
6 gene_6 dose_0 101.38702
# create lm, dose_0 will be assumed as reference
model <- lm(tpm ~ dose, data = df1)
summary(model)
Call:
lm(formula = tpm ~ dose, data = df1)
Residuals:
Min 1Q Median 3Q Max
-9.5597 -2.0167 0.2412 1.9823 10.3174
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 100.25062 0.29414 340.821 <2e-16 ***
dosedose_1 -0.43665 0.41598 -1.050 0.294
dosedose_2 0.09950 0.41598 0.239 0.811
dosedose_3 0.23839 0.41598 0.573 0.567
dosedose_4 0.07475 0.41598 0.180 0.857
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.941 on 495 degrees of freedom
Multiple R-squared: 0.0061, Adjusted R-squared: -0.001931
F-statistic: 0.7595 on 4 and 495 DF, p-value: 0.552