En este análisis, se realiza la curva estándar de RT-PCR en tiempo real para determinar la relación entre la concentración de ADN y el valor del ciclo umbral (Cq). Se ajusta un modelo de regresión lineal y se muestra su ecuación junto con el coeficiente de determinación (\(R^2\)).
# Instalar y cargar paquetes si es necesario
if(!require(ggplot2)) install.packages("ggplot2", dependencies=TRUE)
if(!require(tidyverse)) install.packages("tidyverse", dependencies=TRUE)
if(!require(tidyverse)) install.packages("dplyr", dependencies=TRUE)
library(ggplot2,
tidyverse,
dpyr)
# Definir valores de Ct de ambas muestras
Ct_Cx <- 25.8
Ct_Tx<- 22.2
# Crear un data frame
df_ct <- data.frame(
Muestra = c("Control", "Tratamiento"),
Ct = c(Ct_Cx, Ct_Tx)
)
# Mostrar el data frame
df_ct
## Muestra Ct
## 1 Control 25.8
## 2 Tratamiento 22.2
#Datos RT-PCR (Concentración vs. Cq)
datos_rt_pcr <- data.frame(
Concentracion = c(100, 10, 1, 0.1, 0.01, 0.001), # Diluciones seriadas
Cq = c(15.2, 18.5, 22.1, 26.5, 30.3, 34.5) # Valores simulados de Ct
)
# Transformar concentración a log10
datos_rt_pcr$logConc <- log10(datos_rt_pcr$Concentracion)
datos_rt_pcr
## Concentracion Cq logConc
## 1 1e+02 15.2 2
## 2 1e+01 18.5 1
## 3 1e+00 22.1 0
## 4 1e-01 26.5 -1
## 5 1e-02 30.3 -2
## 6 1e-03 34.5 -3
# Ajustar modelo de regresión lineal
modelo_pcr <- lm(Cq ~ logConc, data = datos_rt_pcr)
modelo_pcr
##
## Call:
## lm(formula = Cq ~ logConc, data = datos_rt_pcr)
##
## Coefficients:
## (Intercept) logConc
## 22.570 -3.894
# Obtener coeficientes de la ecuación
coeficientes <- coef(modelo_pcr)
pendiente <- round(coeficientes[2], 3)
intercepto <- round(coeficientes[1], 3)
# Crear puntos de predicción para la línea ajustada
predicciones <- data.frame(logConc = seq(min(datos_rt_pcr$logConc), max(datos_rt_pcr$logConc), length.out = 100))
predicciones$Cq <- predict(modelo_pcr, newdata = predicciones)
# Obtener resumen del modelo
resumen_modelo <- summary(modelo_pcr)
resumen_modelo
##
## Call:
## lm(formula = Cq ~ logConc, data = datos_rt_pcr)
##
## Residuals:
## 1 2 3 4 5 6
## 0.41905 -0.17524 -0.46952 0.03619 -0.05810 0.24762
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 22.5695 0.1493 151.16 1.15e-08 ***
## logConc -3.8943 0.0839 -46.41 1.29e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.351 on 4 degrees of freedom
## Multiple R-squared: 0.9981, Adjusted R-squared: 0.9977
## F-statistic: 2154 on 1 and 4 DF, p-value: 1.289e-06
# Extraer el valor de R²
R2 <- resumen_modelo$r.squared
# Crear la ecuación en formato de texto
ecuacion_texto <- paste0("y = ", pendiente, "x + ", intercepto, "\nR² = ", round(R2, 4))
# Mostrar el valor de R²
cat("y = ", pendiente, "x + ", intercepto, "\nR² = ", round(R2, 4),"\n")
## y = -3.894 x + 22.57
## R² = 0.9981
# Graficar con ggplot2 e incluir la ecuación a la derecha
grafica <- ggplot(datos_rt_pcr, aes(x = logConc, y = Cq)) +
geom_point(color = "#900C3F", size = 5) + # Puntos de datos reales
geom_line(data = predicciones, aes(x = logConc, y = Cq), color = "#FFC300", size = 1.5) + # Ajuste lineal
labs(
title = "Curva Estándar de RT-PCR en Tiempo Real",
x = "Log10(Concentración de ADN [pg/µL])",
y = "Cq (Ct)",
caption = "Simulación de datos de RT-PCR"
) +
theme_classic(base_size = 15) +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
axis.title.x = element_text(face = "bold"),
axis.title.y = element_text(face = "bold")
) +
#geom_smooth(method = "lm", se = FALSE, color="#FFC300") + # Línea de regresión
annotate("text",
x = max(datos_rt_pcr$logConc) -1.5, # Posición hacia la derecha
y = min(datos_rt_pcr$Cq) + 18, # Ajustar para que no se sobreponga
label = ecuacion_texto,
size = 5, color = "#581845", 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
# Ct (Cq) observado
Ct_Control <- Ct_Cx
# Calcular log10(Concentración)
logConc_calculado_Cx <- (Ct_Control - intercepto) / pendiente
# Obtener concentración real
Conc_calculada_Cx <- 10^logConc_calculado_Cx
# Crear un data frame con el nuevo punto
nuevo_punto_Cx <- data.frame(logConc = logConc_calculado_Cx, Cq = Ct_Control)
# Mostrar resultado
cat("La concentración estimada para el control es:", round(Conc_calculada_Cx, 4), "pg/µL\n")
## La concentración estimada para el control es: 0.1481 pg/µL
interpolacion <- grafica+
geom_point(data = nuevo_punto_Cx,
aes(x = logConc, y = Cq),
color = "black",
size = 6, shape = 20) + # Nuevo punto en verde
geom_segment(aes(x = min(datos_rt_pcr$logConc),
xend = logConc_calculado_Cx,
y = Ct_Control,
yend = Ct_Control),
linetype = "dotted",
color = "#2f2d2c",
size = 1.5) + # Línea horizontal hasta el punto
geom_segment(aes(x = logConc_calculado_Cx, xend = logConc_calculado_Cx,
y = min(datos_rt_pcr$Cq), yend = Ct_Control),
linetype = "dotted",
color = "#2f2d2c",
size = 1.5)+
annotate("text",
x = logConc_calculado_Cx,
y = Ct_Control - 1,
label = paste0(" [Cx]= ",
round(Conc_calculada_Cx, 4), " pg/µL"),
color = "black", size = 5,
fontface = "bold",
hjust = -0.007, vjust = -1.7)
interpolacion
## Warning: Use of `datos_rt_pcr$logConc` is discouraged.
## ℹ Use `logConc` instead.
## Warning in geom_segment(aes(x = min(datos_rt_pcr$logConc), xend = logConc_calculado_Cx, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Did you mean to use `annotate()`?
## Warning: Use of `datos_rt_pcr$Cq` is discouraged.
## ℹ Use `Cq` instead.
## Warning in geom_segment(aes(x = logConc_calculado_Cx, xend = logConc_calculado_Cx, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Did you mean to use `annotate()`?
# Ct (Cq) observado
Ct_Tratamiento <- Ct_Tx
# Calcular log10(Concentración)
logConc_calculado_Tx <- (Ct_Tratamiento - intercepto) / pendiente
# Obtener concentración real
Conc_calculada_Tx <- 10^logConc_calculado_Tx
# Crear un data frame con el nuevo punto
nuevo_punto_Tx <- data.frame(logConc = logConc_calculado_Tx , Cq = Ct_Tx )
# Mostrar resultado
cat("La concentración estimada para el tratamiento es:", round(Conc_calculada_Tx , 4), "pg/µL\n")
## La concentración estimada para el tratamiento es: 1.2446 pg/µL
interpolacion_Tx <- interpolacion+
geom_point(data = nuevo_punto_Tx,
aes(x = logConc, y = Cq),
color = "black",
size = 6, shape = 20) + # Nuevo punto en verde
geom_segment(aes(x = min(datos_rt_pcr$logConc),
xend = logConc_calculado_Tx,
y = Ct_Tratamiento,
yend = Ct_Tratamiento),
linetype = "dotted",
color = "#2f2d2c",
size = 1.5) + # Línea horizontal hasta el punto
geom_segment(aes(x = logConc_calculado_Tx, xend = logConc_calculado_Tx,
y = min(datos_rt_pcr$Cq), yend = Ct_Tratamiento),
linetype = "dotted",
color = "#2f2d2c",
size = 1.5)+
annotate("text",
x = logConc_calculado_Tx,
y = Ct_Tratamiento - 1,
label = paste0(" [Tx]= ",
round(Conc_calculada_Tx, 4), " pg/µL"),
color = "black", size = 5,
fontface = "bold",
hjust = -0.007, vjust = -1.7)
interpolacion_Tx
## Warning: Use of `datos_rt_pcr$logConc` is discouraged.
## ℹ Use `logConc` instead.
## Warning in geom_segment(aes(x = min(datos_rt_pcr$logConc), xend = logConc_calculado_Cx, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Did you mean to use `annotate()`?
## Warning: Use of `datos_rt_pcr$Cq` is discouraged.
## ℹ Use `Cq` instead.
## Warning in geom_segment(aes(x = logConc_calculado_Cx, xend = logConc_calculado_Cx, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Did you mean to use `annotate()`?
## Warning: Use of `datos_rt_pcr$logConc` is discouraged.
## ℹ Use `logConc` instead.
## Warning in geom_segment(aes(x = min(datos_rt_pcr$logConc), xend = logConc_calculado_Tx, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Did you mean to use `annotate()`?
## Warning: Use of `datos_rt_pcr$Cq` is discouraged.
## ℹ Use `Cq` instead.
## Warning in geom_segment(aes(x = logConc_calculado_Tx, xend = logConc_calculado_Tx, : All aesthetics have length 1, but the data has 6 rows.
## ℹ Did you mean to use `annotate()`?
Comparacion <- data.frame(Condicion=c("Control", "Tratamiento"),
Concentracion= c(Conc_calculada_Cx, Conc_calculada_Tx))
Comparacion
## Condicion Concentracion
## 1 Control 0.1480876
## 2 Tratamiento 1.2445661
#Gráfica analítica
Barras <- ggplot(Comparacion, aes(x = Condicion, y = Concentracion, fill = Condicion)) +
geom_bar(stat = "identity", color = "black", width = 0.9) + # Barras con borde negro
labs(
title = "Comparación de Concentraciones",
x = "Condición",
y = "Concentración (pg/µL)"
) +
theme_classic(base_size = 14) +
scale_fill_manual(values = c("Control" = "#f8c471", "Tratamiento" = "#2980b9")) + # Colores personalizados
#geom_text(aes(label = round(Concentracion, 2)), vjust = -0.5, size = 5) + # Etiquetas de valores
scale_y_continuous(limits = c(0, (max(Comparacion$Concentracion))),
breaks = seq(0, (max(Comparacion$Concentracion)+0.2),
by = round(((max(Comparacion$Concentracion))/10),1))) + # Ajuste del eje Y
theme(
axis.title = element_text(face = "bold", size = 16), # Títulos de los ejes en negrita
axis.text = element_text(face = "bold", size = 14), # Valores de los ejes en negrita
axis.line = element_line(size = 1.5, color = "black"), # Líneas de los ejes más gruesas
legend.position = "none")
## Warning: The `size` argument of `element_line()` is deprecated as of ggplot2 3.4.0.
## ℹ Please use the `linewidth` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Barras
Porcentaje <- Comparacion %>%
mutate(Porcentaje = (Concentracion ) / Concentracion[Condicion == "Control"]) %>%
select(1,3)
Porcentaje
## Condicion Porcentaje
## 1 Control 1.000000
## 2 Tratamiento 8.404255
#Gráfica analítica
Barras2 <- ggplot(Porcentaje, aes(x = Condicion, y = Porcentaje, fill = Condicion)) +
geom_bar(stat = "identity", color = "black", width = 0.9) + # Barras con borde negro
labs(
title = "Comparación de Concentraciones",
x = "Condición",
y = "Tasa de cambio (u. a.)"
) +
theme_classic(base_size = 14) +
scale_fill_manual(values = c("Control" = "#f8c471",
"Tratamiento" = "#2980b9")) + # Colores personalizados
#geom_text(aes(label = round(Porcentaje, 2)), vjust = -0.5, size = 5) + # Corrección del nombre de columna
scale_y_continuous(limits = c(0, (max(Porcentaje$Porcentaje)+1)),
breaks = seq(0, (max(Porcentaje$Porcentaje)+1),
by = round((max(Porcentaje$Porcentaje)/10),0)))+ # Ajuste del eje Y
theme(axis.title = element_text(face = "bold",
size = 16), # Títulos de los ejes en negrita
axis.text = element_text(face = "bold",
size = 14), # Valores de los ejes en negrita
axis.line = element_line(size = 1.5,
color = "black"), # Líneas de los ejes más gruesas
legend.position = "none" ) #Quita la barra de descripción
Barras2