La pregunta es cómo encontrar la cantidad por la que una serie temporal ("expansión") se retrasa con respecto a otra ("volumen") cuando las series se muestrean a intervalos regulares pero diferentes intervalos.
En este caso, ambas series presentan un comportamiento razonablemente continuo, como mostrarán las figuras. Esto implica (1) que puede necesitarse poco o ningún suavizado inicial y (2) que el remuestreo puede ser tan sencillo como una interpolación lineal o cuadrática. La cuadrática puede ser ligeramente mejor debido a la suavidad. Tras el remuestreo, el desfase se encuentra maximizando la correlación cruzada como se muestra en el hilo, Para dos series de datos muestreadas con desplazamiento, ¿cuál es la mejor estimación del desplazamiento entre ellas? .
Para ilustrar podemos utilizar los datos suministrados en la pregunta, empleando R
para el pseudocódigo. Comencemos con la funcionalidad básica, la correlación cruzada y el remuestreo:
cor.cross <- function(x0, y0, i=0) {
#
# Sample autocorrelation at (integral) lag `i`:
# Positive `i` compares future values of `x` to present values of `y`';
# negative `i` compares past values of `x` to present values of `y`.
#
if (i < 0) {x<-y0; y<-x0; i<- -i}
else {x<-x0; y<-y0}
n <- length(x)
cor(x[(i+1):n], y[1:(n-i)], use="complete.obs")
}
Se trata de un algoritmo rudimentario: un cálculo basado en la FFT sería más rápido. Pero para estos datos (que implican unos 4000 valores) es suficiente.
resample <- function(x,t) {
#
# Resample time series `x`, assumed to have unit time intervals, at time `t`.
# Uses quadratic interpolation.
#
n <- length(x)
if (n < 3) stop("First argument to resample is too short; need 3 elements.")
i <- median(c(2, floor(t+1/2), n-1)) # Clamp `i` to the range 2..n-1
u <- t-i
x[i-1]*u*(u-1)/2 - x[i]*(u+1)*(u-1) + x[i+1]*u*(u+1)/2
}
Descargué los datos como un archivo CSV separado por comas y eliminé su cabecera. (La cabecera causó algunos problemas para R que no me importó diagnosticar).
data <- read.table("f:/temp/a.csv", header=FALSE, sep=",",
col.names=c("Sample","Time32Hz","Expansion","Time100Hz","Volume"))
NB Esta solución supone que cada serie de datos está en orden temporal, sin espacios en ninguno de ellos. Esto le permite utilizar índices en los valores como sustitutos del tiempo y escalar esos índices por las frecuencias de muestreo temporal para convertirlos en tiempos.
Resulta que uno o ambos instrumentos se desvían un poco con el tiempo. Es bueno eliminar esas tendencias antes de continuar. Además, como la señal de volumen se estrecha al final, deberíamos recortarla.
n.clip <- 350 # Number of terminal volume values to eliminate
n <- length(data$Volume) - n.clip
indexes <- 1:n
v <- residuals(lm(data$Volume[indexes] ~ indexes))
expansion <- residuals(lm(data$Expansion[indexes] ~ indexes)
Vuelvo a muestrear el menos -series frecuentes para obtener la mayor precisión del resultado.
e.frequency <- 32 # Herz
v.frequency <- 100 # Herz
e <- sapply(1:length(v), function(t) resample(expansion, e.frequency*t/v.frequency))
Ahora se puede calcular la correlación cruzada -por eficiencia buscamos sólo una ventana razonable de rezagos- y se puede identificar el rezago donde se encuentra el valor máximo.
lag.max <- 5 # Seconds
lag.min <- -2 # Seconds (use 0 if expansion must lag volume)
time.range <- (lag.min*v.frequency):(lag.max*v.frequency)
data.cor <- sapply(time.range, function(i) cor.cross(e, v, i))
i <- time.range[which.max(data.cor)]
print(paste("Expansion lags volume by", i / v.frequency, "seconds."))
La salida nos indica que la expansión va por detrás del volumen en 1,85 segundos. (Si los últimos 3,5 segundos de datos no estuvieran recortados, la salida sería de 1,84 segundos).
Es una buena idea comprobar todo de varias maneras, preferiblemente visualmente. Primero, la función de correlación cruzada :
plot(time.range * (1/v.frequency), data.cor, type="l", lwd=2,
xlab="Lag (seconds)", ylab="Correlation")
points(i * (1/v.frequency), max(data.cor), col="Red", cex=2.5)
A continuación, vamos a registrar las dos series en el tiempo y trazarlos juntos en los mismos ejes .
normalize <- function(x) {
#
# Normalize vector `x` to the range 0..1.
#
x.max <- max(x); x.min <- min(x); dx <- x.max - x.min
if (dx==0) dx <- 1
(x-x.min) / dx
}
times <- (1:(n-i))* (1/v.frequency)
plot(times, normalize(e)[(i+1):n], type="l", lwd=2,
xlab="Time of volume measurement, seconds", ylab="Normalized values (volume is red)")
lines(times, normalize(v)[1:(n-i)], col="Red", lwd=2)
Tiene muy buena pinta. Podemos tener una mejor idea de la calidad del registro con un gráfico de dispersión Sin embargo. Varía los colores por tiempo para mostrar la progresión.
colors <- hsv(1:(n-i)/(n-i+1), .8, .8)
plot(e[(i+1):n], v[1:(n-i)], col=colors, cex = 0.7,
xlab="Expansion (lagged)", ylab="Volume")
Buscamos que los puntos vayan y vengan a lo largo de una línea: las variaciones de ésta reflejan las no linealidades en la respuesta temporal de la expansión al volumen. Aunque hay algunas variaciones, son bastante pequeñas. Pero.., cómo estas variaciones cambian con el tiempo puede ser de cierto interés fisiológico. Lo maravilloso de la estadística, especialmente su aspecto exploratorio y visual, es cómo tiende a crear buenas preguntas y ideas junto con útiles respuestas.
0 votos
No conozco esto lo suficientemente bien como para dar una respuesta, y no estoy seguro de que esto aborde la pregunta, pero un enfoque que sincroniza las señales se llama "registro", que es un subconjunto del análisis de datos funcionales. Este tema se trata en el libro de Ramsey y Silverman sobre la FDA. La idea básica es que las señales observadas pueden estar "deformadas" (por ejemplo, si estamos interesados en la mecánica de la forma en que las personas mastican, pero tenemos datos de personas que mastican a diferentes velocidades - el eje de tiempo está "deformado" en este caso) y el registro intenta definir la señal subyacente en una escala común, "no deformada".
1 votos
¿Ha recogido ya todos sus datos? ¿Se trata de un tema piloto? Si acaba de empezar, yo estudiaría la posibilidad de separar la señal de su cinturón y utilizarla como disparador (o incluso sólo para marcar una marca de tiempo) de su registro de flujo. Normalmente, los sistemas de adquisición tienen esta capacidad con un puerto auxiliar o de disparo. Estoy seguro de que hay formas de distinguirlo simplemente usando sus datos como ha sugerido Macro, pero añadir este paso extra le quitará muchas conjeturas.
1 votos
Creo que, usted quiere estimar sólo un retraso fijo. Usted podría utilizar la correlación cruzada como se indica aquí: stats.stackexchange.com/questions/16121/
1 votos
Tal vez quieras hacer esta pregunta en dsp.SE, donde también piensan en la sincronización de las señales.
1 votos
@Thias es correcto, pero parece que primero hay que remuestrear una serie para que tengan intervalos comunes.