[R-es] ajuste a curva e interpolación 
    Argel Gastélum Arellánez 
    argel.gastelum en gmail.com
       
    Jue Ene 27 05:52:23 CET 2011
    
    
  
El 26/01/11 16:58, David escribió:
> Hola Carlos, probaré con nls
>
> En efecto, se trata de un conjunto de datos de absorción obtenidos en el espectrofotómetro. En estos análisis, el kit trae unas muestras de las cuales se conoce la concentración del producto a investigar, lo que permite construir una curva estandar. Con esta curva, y a partir de los datos del espectrofotómetro, se trata de calcular la concentración del producto en muestras desconocidas.
>
> Matemáticamente no sé por qué el fabricante recomienda esta curva (sigmoidal de 4 parámetros, no lineal), pero tampoco es lo que realmente me interesa. Lo que necesito saber es si con R puedo realizar estos calculos
>
> 1.- construir la curva estandar con datos XY de absorción/concentración
> 2.- interpolar los datos de absorción(Y) para obtener los datos de concentración(X)
>
> No sé si era esto a lo que te referías. Muchas gracias.
>
> David
>
> --- El mié, 26/1/11, Carlos Ortega<coforfe en gmail.com>  escribió:
>
> De: Carlos Ortega<coforfe en gmail.com>
> Asunto: Re: [R-es] ajuste a curva e interpolación
> Para: "David"<dmenor1 en yahoo.es>
> CC: R-help-es en r-project.org
> Fecha: miércoles, 26 de enero, 2011 18:27
>
> Hola David,
> De tu correo, tan sólo he entendido que te haría falta una solución en R que te permitiera ajustar un conjunto de puntos. Sí eso existe, y como dices que utilizas una curva sigmoidad de 4 parámetros, es no-lineal, la solución en R se llama "nls()".
>
> A partir de este punto, el que sea una curva sigmoidal, el que se pueda ajustar con 4 o más/menos parámetros, dependerá de si puedes/quieres darnos más detalles: típicos resultados de un ELISA, incluso un conjunto de datos de muestra, o una referencia válida a la que podamos acceder para ver si esta solución es la válida.
>
> En general, si te quieres beneficiar de la ayuda que desde esta lista se te pueda prestar, el planteamiento que hagas de tu problema específico tienes que abstraerlo a ideas en lo posible de fácil digestión. De otro modo, tan sólo podrá ayudarte, en el mejor de los casos, un colega de campo/problema. 
>
> Saludos,Carlos Ortega
> www.qualityexcellence.eswww.datanalytics.com/blog
>
> 2011/1/26 David<dmenor1 en yahoo.es>
>
> Hola, quisiera saber qué paquete de R utilizar para calcular los datos de concentración de un ELISA, a partir de los datos del espectrofotómetro y los valores para construir una curva estandar
>
>
>
> el fabricante sugiere realizar el ajuste con una curva sigmoidal de 4 parámetros.
>
>
>
> Gracias
     Hola David, qué tal. De acuerdo con tu descripción, creo que lo que 
quieres es hacer algo como el código que pego abajo, seguramente se 
podrá adaptar a las necesidades de tu trabajo. Espero te sirva.
     Saludos.
--
     Argel.
#--------------------------------------------------------
# AJUSTE DEL MODELO LOGÍSTICO A CRECIMIENTO BACTERIANO.
# DATOS:
# Tiempo (h).
T <- c(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 30)
# Densidad óptica.
DO <- c(0.0530, 0.0557, 0.0785, 0.1360, 0.1906, 0.2465, 0.2536, 0.4107, 
0.4606, 0.4498, 0.4294, 0.4119, 0.4285, 0.4093)
# Estimación inicial de parámetros (para no estar adivinando):
K.inicial <- 1.01*max(DO)
K.inicial
C.inicial <- (K.inicial/DO[1])-1
C.inicial
N.para.MU.inicial <- DO[length(DO)]
N.para.MU.inicial
T.para.MU.inicial <- T[length(T)]
T.para.MU.inicial
MU.inicial <- 
(log((-1+(K.inicial/N.para.MU.inicial))/C.inicial))/(-T.para.MU.inicial)
MU.inicial
# Crear el marco de datos:
Datos <- data.frame(x=T,  y=DO)
# Realizar el ajuste no lineal de la curva logística a los datos:
fit <-  nls(y  ~  K/(1+C*(exp(-MU*T))),  Datos, start = list (K = 
K.inicial, C = C.inicial, MU = MU.inicial))
fit
summary(fit)
# Suma de cuadrados de la regresión (o suma de cuadrados de los residuos):
SC.reg <- fit$m$deviance()
SC.reg
# Suma de cuadrados totales:
SC.tot <- sum((DO[1:length(DO)]-mean(DO))^2)
SC.tot
# Error estándar de la regresión (o desviación estándar de la regresión):
Sy.x <- summary(fit)$sigma
Sy.x
# Coeficiente de determinación (asumiéndolo sólo como una aproximación 
lineal):
R.cuadrada <- 1-(SC.reg/SC.tot)
R.cuadrada
# Estimar los intervalos de confianza al 95 % (usar la librería "nlrwr" 
(nonlinear regression with R)):
library(nlrwr)
IC95 <- confint2(fit)
IC95
# Graficar los resultados:
Coeficientes <- coef(fit)
Coeficientes
K <- (as.vector(Coeficientes))[1]
C <- (as.vector(Coeficientes))[2]
MU <- (as.vector(Coeficientes))[3]
K
C
MU
Logistica <- function(x){K/(1+C*(exp(-MU*x)))}
# Esta función también se puede usar para hacer predicciones puntuales, 
por ejemplo:
Logistica(x=10)
plot(x=T, y=DO)
points(x=c(0:30), Logistica(c(0:30)), type="l")
# ¿Bandas de confianza y de predicción? Esto al parecer aplica la 
aproximación lineal al problema de obtener las bandas de confianza
se.fit.confianza <- sqrt(apply(fit$m$gradient(),1,function(x) 
sum(vcov(fit)*outer(x,x))))
se.fit.prediccion <- sqrt((se.fit.confianza^2)+(summary(fit)$sigma)^2)
matplot(
     T,
     cbind(
         predict(fit)+outer(se.fit.confianza, qnorm(
         c(.5, .025,.975))),
         (predict(fit)+outer(se.fit.prediccion, qnorm(
         c(.5, .025,.975))))[,-1]
     ),
     type="l",
     lty=c(1,2,2,3,3),
     col=c("black", "blue", "blue", "brown", "brown"),
     xlab="Tiempo (h)",
     ylab="Densidad Óptica a 600 nm",
     main="Ajuste No Lineal del Modelo Logístico a Crecimiento Bacteriano"
)
points(T, DO)
legend(
     "bottomright",
     legend=c(
         "Datos",
         "Regresión No Lineal",
         paste(
             "DO =", round(K, 4), "/ ( 1 +", round(C, 4),
             "e^( -", round(MU, 4), "T ))"
         ),
         "Banda de Confianza",
         "Banda de Predicción"
     ),
     col=c("black", "black", NA, "blue", "brown"),
     lty=c(NA, 1, NA, 2, 3),
     pch=c(21, NA, NA, NA, NA)
)
# Para graficar sólo la banda de confianza:
matplot(
     T,
     predict(fit)+outer(se.fit.confianza,qnorm(c(.5, .025,.975))),
     type="l",
     lty=c(1,2,2),
     col=c("black", "blue", "blue"),
     xlab="Tiempo (h)",
     ylab="Densidad Óptica a 600 nm"
)
points(T, DO)
# Para graficar sólo la banda de predicción:
matplot(
     T,
     predict(fit)+outer(se.fit.prediccion,qnorm(c(.5, .025,.975))),
     type="l",
     lty=c(1,2,2),
     col=c("black", "brown", "brown"),
     xlab="Tiempo (h)",
     ylab="Densidad Óptica a 600 nm"
)
points(T, DO)
#--------------------------------------------------------
    
    
Más información sobre la lista de distribución R-help-es