if(require("pacman"))
  install.packages("pacman")
## Loading required package: pacman
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)

Llamar paquetería

library("pacman")

p_load("vroom", "ggplot2", "dplyr", "ggrepel", "tidyverse", "scales")

Llamar base de datos

Datos_PCR <- vroom("https://raw.githubusercontent.com/ManuelLaraMVZ/Metabolomica_2026_1/refs/heads/main/Cts")
## Rows: 20 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): Well, Grupo, Practica, Fluor
## dbl (1): Cq
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Datos_PCR
## # A tibble: 20 × 5
##    Well       Grupo      Practica Fluor    Cq
##    <chr>      <chr>      <chr>    <chr> <dbl>
##  1 50         Curva      Absoluta SYBR   5.15
##  2 10         Curva      Absoluta SYBR  10.8 
##  3 5          Curva      Absoluta SYBR  13.9 
##  4 1          Curva      Absoluta SYBR  15.7 
##  5 0.5        Curva      Absoluta SYBR  16.5 
##  6 0.1        Curva      Absoluta SYBR  18.3 
##  7 Muestra    G1         Absoluta SYBR  11.5 
##  8 Muestra    G2         Absoluta SYBR  13.1 
##  9 A01        G1         Relativa SYBR  28.6 
## 10 A02        G1         Relativa SYBR  15.0 
## 11 A03        G1         Relativa SYBR  14.0 
## 12 A04        G1         Relativa SYBR  50   
## 13 A05        G1         Relativa SYBR  15.5 
## 14 A06        G1         Relativa SYBR  12.6 
## 15 A01        G2         Relativa SYBR  12.7 
## 16 A02        G2         Relativa SYBR  16.3 
## 17 A03        G2         Relativa SYBR  13.1 
## 18 Referencia Referencia Relativa SYBR  18.4 
## 19 Profesor   G1         Relativa SYBR  20.0 
## 20 Profesor   G2         Relativa SYBR  20.0

Filtrado de datos

Datos_curva <- Datos_PCR %>% 
  filter(Practica == "Absoluta",
         Grupo == "Curva") %>% 
  select("Well", "Cq") %>% 
  mutate(Well = as.numeric(Well),
         Curva = Well,
         LogConc = log10(Curva)) %>% 
  select(3,4,2)

Datos_curva
## # A tibble: 6 × 3
##   Curva LogConc    Cq
##   <dbl>   <dbl> <dbl>
## 1  50     1.70   5.15
## 2  10     1     10.8 
## 3   5     0.699 13.9 
## 4   1     0     15.7 
## 5   0.5  -0.301 16.5 
## 6   0.1  -1     18.3

Gráfica datos

Grafica <- ggplot(Datos_curva,
                  aes(x = LogConc,
                      y = Cq))+
  geom_point(color = "#900C3F", size = 4)+
  theme_classic()

Grafica

Ajuste lineal

Modelo_lineal <- lm(data = Datos_curva, Cq ~LogConc)

Modelo_lineal
## 
## Call:
## lm(formula = Cq ~ LogConc, data = Datos_curva)
## 
## Coefficients:
## (Intercept)      LogConc  
##      14.991       -4.655

Obtención coeficientes

Coeficientes <- coef(Modelo_lineal)

Coeficientes
## (Intercept)     LogConc 
##   14.990632   -4.654892

Pendiente

m <- round(Coeficientes [2], 2)

m
## LogConc 
##   -4.65

Intersección

Y0 <- round(Coeficientes [1], 2)

Y0
## (Intercept) 
##       14.99

Predicción

Prediccion <- data.frame(LogConc = seq(min(Datos_curva$LogConc),
                                       max(Datos_curva$LogConc),
                                       length.out = 100))
Prediccion$Cq <- predict(Modelo_lineal, newdata = Prediccion)

head(Prediccion)
##      LogConc       Cq
## 1 -1.0000000 19.64552
## 2 -0.9727377 19.51862
## 3 -0.9454754 19.39172
## 4 -0.9182130 19.26481
## 5 -0.8909507 19.13791
## 6 -0.8636884 19.01101

Valor de R2

Resumen_modelo <- summary(Modelo_lineal)

Resumen_modelo
## 
## Call:
## lm(formula = Cq ~ LogConc, data = Datos_curva)
## 
## Residuals:
##        1        2        3        4        5        6 
## -1.93651  0.43656  2.12380  0.69647  0.06971 -1.39002 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  14.9906     0.7233  20.725  3.2e-05 ***
## LogConc      -4.6549     0.7579  -6.142  0.00356 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.649 on 4 degrees of freedom
## Multiple R-squared:  0.9041, Adjusted R-squared:  0.8802 
## F-statistic: 37.73 on 1 and 4 DF,  p-value: 0.003563
R2 <- round(Resumen_modelo$r.squared, 4)

R2
## [1] 0.9041

Ecuación en gráfica

Ecuacion_recta <- paste0("y =", m, "x +", Y0, "\nR2 =", R2)

cat("y =", m, "x +", Y0, "\nR2 =", R2)
## y = -4.65 x + 14.99 
## R2 = 0.9041

Gráfica de ajuste con ecuación

Grafica_ajuste <- Grafica+
  geom_smooth(data = Prediccion,
              aes(x = LogConc,
                  y = Cq),
              color = "#141761",
              size = 1.5)+
  labs(title = "Curva estándar de qPCR",
       subtitle = "Equipo 5",
       caption = "Diseñó: SJM",
       x = "Log10 (Concentración) [pg/μL]",
       y = "Cycle threshold (Ct)")+
  theme_classic(base_size = 15)+
  scale_y_continuous(labels = number_format(accuracy = 1))+
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        axis.title.x = element_text(face = "bold"),
        axis.title.y = element_text(face = "bold"))+
  annotate("text",
           x = max(Datos_curva$LogConc) -1.2,
           y = min(Datos_curva$Cq) + 13,
           label = Ecuacion_recta,
           color = "#6B2018",
           size = 5,
           fontface = "bold",
           hjust = 0)
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Grafica_ajuste
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

Datos_PCR
## # A tibble: 20 × 5
##    Well       Grupo      Practica Fluor    Cq
##    <chr>      <chr>      <chr>    <chr> <dbl>
##  1 50         Curva      Absoluta SYBR   5.15
##  2 10         Curva      Absoluta SYBR  10.8 
##  3 5          Curva      Absoluta SYBR  13.9 
##  4 1          Curva      Absoluta SYBR  15.7 
##  5 0.5        Curva      Absoluta SYBR  16.5 
##  6 0.1        Curva      Absoluta SYBR  18.3 
##  7 Muestra    G1         Absoluta SYBR  11.5 
##  8 Muestra    G2         Absoluta SYBR  13.1 
##  9 A01        G1         Relativa SYBR  28.6 
## 10 A02        G1         Relativa SYBR  15.0 
## 11 A03        G1         Relativa SYBR  14.0 
## 12 A04        G1         Relativa SYBR  50   
## 13 A05        G1         Relativa SYBR  15.5 
## 14 A06        G1         Relativa SYBR  12.6 
## 15 A01        G2         Relativa SYBR  12.7 
## 16 A02        G2         Relativa SYBR  16.3 
## 17 A03        G2         Relativa SYBR  13.1 
## 18 Referencia Referencia Relativa SYBR  18.4 
## 19 Profesor   G1         Relativa SYBR  20.0 
## 20 Profesor   G2         Relativa SYBR  20.0

Predicción concentración muestra

Dato_muestra1 <- Datos_PCR %>% 
  filter(Practica == "Absoluta",
         Grupo == "G1",
         Well == "Muestra") %>% 
  select("Well", "Cq")

Dato_muestra1
## # A tibble: 1 × 2
##   Well       Cq
##   <chr>   <dbl>
## 1 Muestra  11.5
Dato_muestra2 <- Datos_PCR %>% 
  filter(Practica == "Absoluta",
         Grupo == "G2",
         Well == "Muestra") %>% 
  select("Well", "Cq")

Dato_muestra2
## # A tibble: 1 × 2
##   Well       Cq
##   <chr>   <dbl>
## 1 Muestra  13.1

Valor Ct

Ct_muestra1 <- Dato_muestra1$Cq

Ct_muestra1
## [1] 11.5
Ct_muestra2 <- Dato_muestra2$Cq

Ct_muestra2
## [1] 13.1136

Valor de x (LogConc)

LogConc_calculado1 <- (Ct_muestra1-Y0)/m

LogConc_calculado1
## (Intercept) 
##   0.7505376
LogConc_calculado2 <- (Ct_muestra2-Y0)/m

LogConc_calculado2
## (Intercept) 
##   0.4035269

Valor real

Valor_real1 <- 10^LogConc_calculado1

cat("La concentración de la muestra 1 es:", round(Valor_real1,2), "pg/μL")
## La concentración de la muestra 1 es: 5.63 pg/μL
Valor_real2 <- 10^LogConc_calculado2

cat("La concentración de la muestra 2 es:", round(Valor_real2,2), "pg/μL")
## La concentración de la muestra 2 es: 2.53 pg/μL

Construcción dataframe

Datos_muestra1 <- data.frame(Concentracion_real = round(Valor_real1,2),
                            LogConc = round(LogConc_calculado1,2),
                            Cq = Ct_muestra1)

Datos_muestra1
##             Concentracion_real LogConc   Cq
## (Intercept)               5.63    0.75 11.5
Datos_muestra2 <- data.frame(Concentracion_real = round(Valor_real2,2),
                            LogConc = round(LogConc_calculado2,2),
                            Cq = Ct_muestra2)

Datos_muestra2
##             Concentracion_real LogConc      Cq
## (Intercept)               2.53     0.4 13.1136

Grafica muestra

Grafica_muestra <- Grafica_ajuste+
  geom_point(data = Datos_muestra1,
             aes(x = LogConc,
                 y = Cq),
             color = "black",
             size = 6,
             shape = 20)+
  geom_segment(aes(x = min(Datos_curva$LogConc), xend = LogConc_calculado1,
                   y = Ct_muestra1, yend = Ct_muestra1),
               linetype = "dashed",
               color = "#8689F7",
               size = 1)+
  geom_segment(aes(x = LogConc_calculado1, xend = LogConc_calculado1,
                   y = min(Datos_curva$Cq), yend = Ct_muestra1),
               linetype = "dashed",
               color = "#8689F7",
               size = 1)+
  annotate("text",
         x = LogConc_calculado1,
         y = Ct_muestra1 -0.8,
         label = paste0("[Muestra 1] =", round(Valor_real1,2), " pg/μL"),
         color = "black",
         fontface = "bold",
         hjust = -0.007,
         vjust = -1.7)+
  
  geom_point(data = Datos_muestra2,
             aes(x = LogConc,
                 y = Cq),
             color = "black",
             size = 6,
             shape = 20)+
  geom_segment(aes(x = min(Datos_curva$LogConc), xend = LogConc_calculado2,
                   y = Ct_muestra2, yend = Ct_muestra2),
               linetype = "dashed",
               color = "#8689F7",
               size = 1)+
  geom_segment(aes(x = LogConc_calculado2, xend = LogConc_calculado2,
                   y = min(Datos_curva$Cq), yend = Ct_muestra2),
               linetype = "dashed",
               color = "#8689F7",
               size = 1)+
  annotate("text",
         x = LogConc_calculado2,
         y = Ct_muestra2 -0.8,
         label = paste0("[Muestra 2] =", round(Valor_real2,2), " pg/μL"),
         color = "black",
         fontface = "bold",
         hjust = -0.007,
         vjust = -1.7)

Grafica_muestra
## Warning: Use of `Datos_curva$LogConc` is discouraged.
## ℹ Use `LogConc` instead.
## Warning in geom_segment(aes(x = min(Datos_curva$LogConc), xend = LogConc_calculado1, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.
## Warning: Use of `Datos_curva$Cq` is discouraged.
## ℹ Use `Cq` instead.
## Warning in geom_segment(aes(x = LogConc_calculado1, xend = LogConc_calculado1, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.
## Warning: Use of `Datos_curva$LogConc` is discouraged.
## ℹ Use `LogConc` instead.
## Warning in geom_segment(aes(x = min(Datos_curva$LogConc), xend = LogConc_calculado2, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.
## Warning: Use of `Datos_curva$Cq` is discouraged.
## ℹ Use `Cq` instead.
## Warning in geom_segment(aes(x = LogConc_calculado2, xend = LogConc_calculado2, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'