¿Cuál es un buen algoritmo para estimar la mediana de un gran conjunto de datos de lectura única?

48

Estoy buscando un buen algoritmo (es decir, cómputo mínimo, requisitos mínimos de almacenamiento) para estimar la mediana de un conjunto de datos que es demasiado grande para almacenar, de modo que cada valor solo se pueda leer una vez (a menos que almacene explícitamente ese valor). No hay límites en los datos que se puedan suponer.

Las aproximaciones están bien, siempre que se conozca la precisión.

Cualquier puntero?

PeterR
fuente
44
Quizás, preguntar por Stackoverflow puede obtener mejores respuestas.
2
@Srikant:> es un área de investigación bastante activa en estadística :) La solución más cercana a los límites teóricos inferiores en términos de almacenamiento implica también algunas construcciones de probabilidad bastante inteligentes. En general, me sorprendió cuando lo vi por primera vez hace un par de meses; Hay más estadísticas aquí de lo que parece.
user603

Respuestas:

6

¿Podría agrupar el conjunto de datos en conjuntos de datos mucho más pequeños (digamos 100 o 1000 o 10,000 puntos de datos) Si luego calculó la mediana de cada uno de los grupos. Si hiciera esto con suficientes conjuntos de datos, podría trazar algo así como el promedio de los resultados de cada uno de los conjuntos más pequeños y esto, ejecutando suficientes conjuntos de datos más pequeños convergen en una solución 'promedio'.

Ian Turner
fuente
Esto es interesante, ¡y en dónde podrían entrar algunos consejos estadísticos! Suponga que en total tengo (digamos) 500,000 puntos iid y miro grupos de (digamos) 1,000 de ellos, y calculo la mediana de cada grupo. Ahora tengo 500 medianas. ¿Existe alguna teoría que me permita calcular un intervalo de confianza para la mediana general basada en estas 500 medianas?
PeterR
44
Entonces, según un colega perdido hace mucho tiempo, el mejor enfoque parece ser Chiranjeeb Buragohain y Subhash Suri. Cuantiles en corrientes. cs.ucsb.edu/~suri/psdir/ency.pdf También me gusta el enfoque de Ian, ya que estas medianas de conjuntos de datos más pequeños convergerán en una distribución normal, y así puedo formar intervalos de conf para las medianas.
PeterR
10

¿Qué tal algo como un procedimiento de binning? Suponga (con fines ilustrativos) que sabe que los valores están entre 1 y 1 millón. Configure N contenedores, de tamaño S. Entonces, si S = 10000, tendría 100 contenedores, correspondientes a los valores [1: 10000, 10001: 20000, ..., 990001: 1000000]

Luego, recorre los valores. En lugar de almacenar cada valor, simplemente incremente el contador en el contenedor apropiado. Usando el punto medio de cada bin como una estimación, puede hacer una aproximación razonable de la mediana. Puede escalar esto a una resolución tan fina o gruesa como desee cambiando el tamaño de los contenedores. Estás limitado solo por la cantidad de memoria que tienes.

Dado que no sabe qué tan grandes pueden llegar a ser sus valores, simplemente elija un tamaño de contenedor lo suficientemente grande como para que no se le agote la memoria, utilizando algunos cálculos rápidos al final del sobre. También puede almacenar los contenedores escasamente, de modo que solo agregue un contenedor si contiene un valor.

Editar:

El enlace que proporciona ryfm da un ejemplo de esto, con el paso adicional de usar los porcentajes acumulativos para estimar con mayor precisión el punto dentro de la papelera mediana, en lugar de solo usar puntos medios. Esta es una buena mejora.

Chrisamiller
fuente
El problema con el enfoque de binning es que no tenemos un buen límite superior para los datos, por lo que el punto medio para el bin más grande tendría que ser enorme. Por lo tanto, necesitaríamos una gran cantidad de bins (no hay suficiente memoria para eso), o tener bins bastante amplios (lo que conduciría a una respuesta bastante inexacta). Y los datos no son muy escasos.
PeterR
Dado que solo está interesado en la mediana, ¿por qué no podría ampliar los contenedores en valores más altos de su variable?
russellpierce
drknexus, porque no sabemos cuál debería ser el contenedor más grande.
PeterR
¿Tienes alguna intuición sobre cuál será el rango? Si está bastante seguro de que más de la mitad de las respuestas estarán por debajo del número N, puede hacer que su último contenedor sea tan grande como desee. Tal vez su último contenedor tenga todos los números mayores de 1 billón, ¿sería lo suficientemente alto? Con la cantidad de memoria en los sistemas modernos, puede almacenar MUCHOS contenedores y lograr una resolución bastante alta. En términos de estructuras de datos, no estamos hablando de nada elegante y memoria intensiva aquí.
Chrisrisler
¿Alguna intuición? si. Y su enfoque podría funcionar en general. Sin embargo, en este caso no podemos tener mucha memoria / cálculo. Es en una aplicación de red donde el dispositivo puede ver decenas de miles de elementos por segundo, y queda MUY poco procesamiento para este propósito. No es el escenario ideal / típico, lo sé, ¡pero eso es lo que lo hace interesante!
PeterR
9

Te redirijo a mi respuesta a una pregunta similar . En pocas palabras, es un algoritmo de lectura única, 'sobre la marcha' con peor complejidad de caso para calcular la mediana (exacta).O(n)

usuario603
fuente
8

El algoritmo Rivest-Tarjan-Selection (a veces también llamado algoritmo de mediana de medianas) le permitirá calcular el elemento mediano en tiempo lineal sin ningún tipo de clasificación. Para conjuntos de datos grandes, esto puede ser bastante más rápido que la clasificación logarítmica lineal. Sin embargo, no resolverá su problema de almacenamiento de memoria.

Robby McKilliam
fuente
2

Nunca he tenido que hacer esto, así que esto es solo una sugerencia.

Veo dos (otras) posibilidades.

Datos medios

  1. Cargue la mitad de los datos y ordene
  2. A continuación, lea los valores restantes y compárelos con la lista ordenada.
    1. Si el nuevo valor es mayor, deséchelo.
    2. de lo contrario, coloque el valor en la lista ordenada y elimine el valor más grande de esa lista.

Distribución muestral

La otra opción es utilizar una aproximación que implique la distribución de muestreo. Si sus datos son normales, entonces el error estándar para n moderado es:

1.253 * sd / sqrt (n)

Para determinar el tamaño de n con el que estaría contento, ejecuté una simulación rápida de Montecarlo en R

n = 10000
outside.ci.uni = 0
outside.ci.nor = 0
N=1000
for(i in 1:N){
  #Theoretical median is 0
  uni = runif(n, -10, 10)
  nor  = rnorm(n, 0, 10)

  if(abs(median(uni)) > 1.96*1.253*sd(uni)/sqrt(n))
    outside.ci.uni = outside.ci.uni + 1

  if(abs(median(nor)) > 1.96*1.253*sd(nor)/sqrt(n))
    outside.ci.nor = outside.ci.nor + 1
}

outside.ci.uni/N
outside.ci.nor/N

Para n = 10000, el 15% de las estimaciones medias uniformes estaban fuera del IC.

csgillespie
fuente
3
El conjunto de datos es potencialmente demasiado grande para leerlo en la mitad ... es en un contexto de red donde el dispositivo que realiza el procesamiento puede ver decenas de miles de elementos por segundo, y probablemente tenga suficiente memoria para almacenar solo unos pocos cientos. Además, los datos definitivamente no son gaussianos. De hecho, no se ajusta bien a ninguna de las distribuciones comunes.
PeterR
1

Aquí hay una respuesta a la pregunta hecha en stackoverflow: https://stackoverflow.com/questions/1058813/on-line-iterator-algorithms-for-estimating-statistical-median-mode-skewness/2144754#2144754

La actualización iterativa mediana + = eta * sgn (muestra - mediana) parece que podría ser un camino a seguir.

Comunidad
fuente
1
pero entonces, ¿cómo elegir eta y qué significa esto estadísticamente? es decir, ¿cómo formar intervalos de confianza para la mediana a partir de este resultado?
PeterR
@PeterR, oye, ¿cuál es la solución final que usaste?
Aakash Goel
1

El Algoritmo Remedian (PDF) proporciona una estimación mediana 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
1

Si los valores que está utilizando están dentro de un cierto rango, digamos 1 a 100000, puede calcular eficientemente la mediana en un número extremadamente grande de valores (digamos, billones de entradas), con un cubo entero (este código tomado de BSD con licencia ea -utils / sam-stats.cpp)

class ibucket {
public:
    int tot;
    vector<int> dat;
    ibucket(int max) {dat.resize(max+1);tot=0;}
    int size() const {return tot;};

    int operator[] (int n) const {
        assert(n < size());
        int i;
        for (i=0;i<dat.size();++i) {
            if (n < dat[i]) {
                return i;
            }
            n-=dat[i];
        }
    }

    void push(int v) {
        assert(v<dat.size());
        ++dat[v];
        ++tot;
    }
};


template <class vtype>
double quantile(const vtype &vec, double p) {
        int l = vec.size();
        if (!l) return 0;
        double t = ((double)l-1)*p;
        int it = (int) t;
        int v=vec[it];
        if (t > (double)it) {
                return (v + (t-it) * (vec[it+1] - v));
        } else {
                return v;
        }
}
Erik Aronesty
fuente
Además, esto puede extenderse al uso de un número finito de contenedores para medianas en tiempo real, etc.
Erik Aronesty