Algoritmos para calcular la mediana en ejecución?

18

En tamaños de ventana más pequeños, la n log nordenación podría funcionar. ¿Hay algún algoritmo mejor para lograr esto?

miku
fuente
1
Creo que este es el primer candidato que se moverá a Stack Overflow.
Posiblemente, pero necesitaría mucha más explicación sobre SO.
walkytalky
2
La mayoría de los programadores saben "mediana". (sort (array)) [length / 2] es una pista lo suficientemente grande para aquellos que olvidaron. También en su forma más básica para cada nuevo punto, solo necesita hacer una bisección / inserción en la mitad de la matriz ...
Paul
1
Reabrió
Rob Hyndman
2
Demasiado trivial para ser más que un comentario, pero el código para la mediana de 3s es solo a + b + c - max (a, b, c) - min (a, b. C). Eso funciona bien incluso si los lazos están presentes. Eso fue obvio para mí una vez que lo pensé en el código de otra persona (¿por qué él (en este caso) suma y resta para obtener una mediana ???) y algunos otros podrían tener la misma reacción. max () y min () a menudo se implementan como funciones súper rápidas. Lamentablemente, no existe tal truco en general.
Nick Cox

Respuestas:

11

Es una mala forma ordenar una matriz para calcular una mediana. Las medianas (y otros cuantiles) generalmente se calculan utilizando el algoritmo de selección rápida , con complejidad .O(norte)

También es posible que desee ver mi respuesta a una pregunta relacionada reciente aquí .

usuario603
fuente
7

Aquí hay un artículo que describe un algoritmo posible. Código fuente incluido y una aplicación bastante seria (detección de ondas gravitacionales basada en interferometría láser), por lo que puede esperar que se pruebe bien.

Łukasz Lew
fuente
1
El enlace está roto, y sin título o información del autor, es difícil encontrar lo que se refiere.
Kristopher Johnson
6

Si está dispuesto a tolerar una aproximación, existen otros métodos. Por ejemplo, una aproximación es un valor cuyo rango está dentro de una distancia (especificada por el usuario) de la mediana real. Por ejemplo, la mediana tiene un rango (normalizado) de 0.5, y si especifica un término de error del 10%, desearía una respuesta que tenga un rango entre 0.45 y 0.55.

Si tal respuesta es apropiada, existen muchas soluciones que pueden funcionar en ventanas deslizantes de datos. La idea básica es mantener una muestra de los datos de cierto tamaño (aproximadamente 1 / término de error) y calcular la mediana en esta muestra. Se puede demostrar que con alta probabilidad, independientemente de la naturaleza de la entrada, la mediana resultante satisface las propiedades que mencioné anteriormente.

Por lo tanto, la pregunta principal es cómo mantener una muestra continua de los datos de cierto tamaño, y hay muchos enfoques para eso, incluida la técnica conocida como muestreo de yacimientos. Por ejemplo, este documento: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.7136

Suresh Venkatasubramanian
fuente
4

Si mantiene una ventana de datos de longitud k como una lista doblemente ordenada, entonces, mediante una búsqueda binaria (para insertar cada elemento nuevo a medida que se desplaza en la ventana) y una matriz circular de punteros (para ubicar inmediatamente elementos que debe eliminarse), cada cambio de la ventana requiere un esfuerzo O (log (k)) para insertar un elemento, solo un esfuerzo O (1) para eliminar el elemento desplazado fuera de la ventana, y solo un esfuerzo O (1) para encontrar la mediana (porque cada vez que se inserta o elimina un elemento en la lista, puede actualizar un puntero a la mediana en el tiempo O (1)). Por lo tanto, el esfuerzo total para procesar una matriz de longitud N es O ((nk) log (k)) <= O (n log (k)). Esto es mejor que cualquiera de los otros métodos propuestos hasta ahora y no es una aproximación, es exacto.

whuber
fuente
1
¿Podría explicar cómo propone realizar una búsqueda binaria en una lista ordenada doblemente vinculada?
NPE
un 'enlace' le permite recorrer la lista en orden ordenado; el otro le permite recorrer en el orden en que aparecen los elementos. Sin embargo, no está claro cómo haría esto con punteros, como preguntas @aix.
shabbychef
2
@aix Creo que tu insinuación es correcta; Necesitaría una lista de omisión indexable, no solo una lista ordenada doblemente vinculada. La idea es tener una estructura de datos que permita la inserción de un elemento, la eliminación de un elemento y encontrar la mediana en el tiempo esperado de O (log (n)) (o mejor).
whuber
3

Como mencionó, la clasificación sería O(n·log n)por una ventana de longitud n. Hacer esta mudanza agrega otra l=vectorlengthhaciendo el costo total O(l·n·log n).

La forma más sencilla de impulsar esto es mantener una lista ordenada de los últimos n elementos en la memoria al pasar de una ventana a la siguiente. Como eliminar / insertar un elemento de / en una lista ordenada son ambos, O(n)esto generaría costos de O(l·n).

Pseudocódigo:

l = length(input)
aidvector = sort(input(1:n))
output(i) = aid(n/2)
for i = n+1:l
    remove input(i-n) from aidvector
    sort aid(n) into aidvector
    output(i) = aid(n/2)
ymihere
fuente
2

Si puede vivir con una estimación en lugar de la mediana real, el Algoritmo Remedian (PDF) es de una pasada con bajos requisitos de almacenamiento y precisión bien definida.

El remedio con base b procede calculando medianas de grupos de observaciones b, y luego medianas de estas medianas, hasta que solo quede una estimación. Este método simplemente necesita k matrices de tamaño b (donde n = b ^ k) ...

shoelzer
fuente
0

Usé esta biblioteca RunningStats C ++ en una aplicación incrustada. Es la biblioteca de estadísticas de ejecución más simple que he encontrado hasta ahora.

Desde el enlace:

El código es una extensión del método de Knuth y Welford para calcular la desviación estándar en una pasada a través de los datos. Calcula asimetría y curtosis también con una interfaz similar. Además de solo requerir una pasada a través de los datos, el algoritmo es numéricamente estable y preciso.

Chris K
fuente
¿Esa página dice algo sobre la mediana?
musiphil