¿Cómo reduzco el número de puntos de datos en una serie?

11

No he estudiado estadísticas durante más de 10 años (y luego solo un curso básico), por lo que tal vez mi pregunta sea un poco difícil de entender.

De todos modos, lo que quiero hacer es reducir el número de puntos de datos en una serie. El eje x es el número de milisegundos desde el inicio de la medición y el eje y es la lectura para ese punto.

A menudo hay miles de puntos de datos, pero es posible que solo necesite unos pocos cientos. Entonces mi pregunta es: ¿cómo reduzco con precisión la cantidad de puntos de datos?

¿Cómo se llama el proceso? (Para que pueda googlearlo) ¿Hay algún algoritmo preferido (lo implementaré en C #)

Espero que tengas algunas pistas. Perdón por mi falta de terminología adecuada.


Editar: Más detalles vienen aquí:

Los datos sin procesar que obtuve son datos de frecuencia cardíaca y en forma de número de milisegundos desde el último latido. Antes de trazar los datos, calculo el número de milisegundos de la primera muestra y los bpm (latidos por minuto) en cada punto de datos (60000 / timesincelastbeat).

Quiero visualizar los datos, es decir, trazarlos en un gráfico lineal. Quiero reducir el número de puntos en el gráfico de miles a algunos cientos.

Una opción sería calcular el promedio de bpm por cada segundo en la serie, o tal vez cada 5 segundos más o menos. Eso hubiera sido bastante fácil si supiera que tendría al menos una muestra para cada uno de esos períodos (segundos de intervalos de 5 segundos).

Rob Hyndman
fuente
Olvidé esto: los puntos a lo largo del eje x vienen con espaciado variable.
No estoy seguro de entenderlo. ¿No tienes un eje y?
Oh, lo siento. Me equivoqué. Ahora lo he cambiado arriba.
También creo que necesita proporcionar un poco más de información. Por ejemplo, todavía no puedo visualizar el gráfico. ¿Cuál es tu objetivo?
OK lo siento. He agregado algunos detalles más arriba.

Respuestas:

10

Tiene dos problemas: demasiados puntos y cómo suavizar los puntos restantes.

Adelgazando su muestra

Si tiene demasiadas observaciones llegando en tiempo real, siempre podría usar un muestreo aleatorio simple para diluir su muestra. Tenga en cuenta que para que esto también sea cierto, el número de puntos debería ser muy grande.

Supongamos que tiene N puntos y solo quiere n de ellos. Luego, genere n números aleatorios a partir de una distribución discreta uniforme U (0, N-1) . Estos serían los puntos que usa.

Si desea hacer esto secuencialmente, es decir, en cada punto que decida usarlo o no, simplemente acepte un punto con probabilidad p . Entonces, si establece p = 0.01 , aceptaría (en promedio) 1 punto en cien.

Si sus datos se distribuyen de manera desigual y solo desea adelgazar regiones densas de puntos, simplemente haga que su función de adelgazamiento sea un poco más sofisticada. Por ejemplo, en lugar de p , ¿qué pasa con:

1pexp(λt)

donde es un número positivo es el tiempo transcurrido desde la última observación. Si el tiempo entre dos puntos es grande, es decir , grande , la probabilidad de aceptar un punto será uno. Por el contrario, si dos puntos están juntos, la probabilidad de aceptar un punto será .λtt1p

Deberá experimentar con los valores de y .λp

Suavizado

Posiblemente algo así como un simple esquema de tipo de promedio móvil. O podría optar por algo más avanzado como un kernel más suave (como otros sugirieron). Tendrá que tener cuidado de no suavizar demasiado, ya que supongo que una caída repentina se debe detectar muy rápidamente en su escenario.

Debería haber bibliotecas C # disponibles para este tipo de cosas.

Conclusión

Fino si es necesario, luego liso.

csgillespie
fuente
Ah, interesante, pero necesito que sea predecible, es decir, que tenga el mismo resultado cada vez que veo los datos.
En ese caso, genere los n índices de los puntos que elija y almacene esos índices.
csgillespie
O almacene la semilla en el RNG antes de tomar muestras.
Dirk Eddelbuettel
La solución de Dirk con respecto a la semilla es probablemente la mejor opción.
csgillespie
Calcular promedios por segundo está bien, pero lo que hago cuando no hay datos para un segundo específico. Supongo que podría hacer una interpolación de los segundos anteriores y posteriores, pero sería genial con algún método específico (con nombre) para esto, así que no trato de inventar algo ya inventado.
9

Bueno, creo que la palabra que estás buscando es "muestreo", pero no estoy seguro de por qué quieres hacerlo. Miles de puntos de datos no son muchos. ¿O solo busca trazar un número menor de puntos igualmente espaciados? Eso generalmente se llama "binning".

¿Tu objetivo es generar una visualización? En ese caso, es posible que desee conservar los datos en bruto, trazarlos como un diagrama de dispersión, y luego superponer algún tipo de tendencia central (línea de regresión, spline, lo que sea) para comunicar lo que sea el mensaje para llevar a casa.

¿O es su objetivo resumir numéricamente los resultados de alguna manera? ¡En ese caso, es posible que desee explicar su problema con más detalle!

Harlan
fuente
Sí, la visualización es lo que quiero. He agregado más información en la pregunta.
secundando el trazado de datos en bruto con una línea de suavizado.
JoFrhwld
thirding trazando datos sin procesar con una línea de suavizado --- Es posible que también desee trazar el cambio en BPM a lo largo del tiempo como una visualización separada.
John
5

Calcular promedios conduce a un conjunto de datos diferente que simplemente reducir la cantidad de puntos de datos. Si un latido por minuto es mucho más rápido que los otros latidos, perderá la señal a través de su proceso de suavizado.

Si resume 125-125-0-125-125 como 100 que la historia que cuentan los datos es diferente a través de su suavizado.

A veces, el corazón incluso omite los latidos y creo que es un evento interesante para el que, sin embargo, quiere ver los datos trazados de frecuencia cardíaca.

Por lo tanto, le propondría que calcule la distancia entre dos puntos con una fórmula como d=sqrt((time1-time2)^2 + (bpm1-bpm2)).

Establece una distancia mínima en su programa. Luego itera a través de sus datos y después de cada punto elimina todos los puntos siguientes para los cuales d es menor que su distancia mínima.

Como la unidad de tiempo y las ppm no son las mismas, es posible que desee pensar en cómo encontrar una manera de escalar las unidades de manera significativa. Para hacer esta tarea correctamente, debe hablar con los médicos que al final deben interpretar sus gráficos y preguntarles qué información consideran esencial.

cristiano
fuente
Publicación interesante Lo investigaré también. Probablemente tengas razón.
2

Si BPM se mantiene igual en muchas muestras (o cambia infinitamente de una manera que no le preocupa), puede truncar sus datos a un dígito significativo que realmente le interese y luego ejecutar Run Length Encoding.

Por ejemplo, en R estos datos:

0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

tiene esta salida

rle(data)
Run Length Encoding
  lengths: int [1:3] 10 15 15
  values : num [1:3] 0 1 2
russellpierce
fuente
1

No estás proporcionando suficiente información. ¿Por qué quieres reducir los puntos de datos? Unos pocos miles no son nada en estos días.

Dado que desea el mismo resultado cada vez que ve los mismos datos, tal vez quiera simplemente agrupar promedios. Tiene espaciado variable en su eje x. ¿Quizás estás tratando de hacer eso consistente? En ese caso, establecería un ancho de depósito de quizás 50 ms, o 100, y luego promediaría todos los puntos allí. Haga que el ancho del contenedor sea tan grande como sea necesario para reducir los puntos de datos al tamaño del conjunto que desea.

Realmente es una pregunta difícil de responder sin una razón por la cual te estás deshaciendo de los datos.

Juan
fuente
OK lo siento. He agregado algunos detalles más arriba.