2010-02-26 10 views
15

tengo un iterador de números, por ejemplo, un objeto de archivo:media y la varianza calcular con una iteración

f = open("datafile.dat") 

ahora quiero calcular:

mean = get_mean(f) 
sigma = get_sigma(f, mean) 

¿Cuál es la mejor aplicación? Supongamos que el archivo es grande y me gustaría evitar leerlo dos veces.

+0

¿Desea evitar leer el archivo dos veces o evitar iterar dos veces? – truppo

+0

No creo que nos muestre el código completo. Está pasando un archivo a 'get_mean()' donde 'fsum()' solo acepta listas de números. –

+0

¿Por qué necesita colocar una restricción para modificar la función? Si reordenaste la fórmula para la varianza, creo que puedes obtener algo como sqrt (1/(n-1) * (suma (li ** 2 para li en l) + n * mm * suma (li para li en l) + n * mm)) donde n es len (l). Es decir, si mis cálculos son correctos. Luego puede iterar una vez, calculando los términos de suma en la refactorización anterior y la media al mismo tiempo. – chradcliffe

Respuesta

11

Si desea repetir una vez, usted puede escribir su función suma:

def mysum(l): 
    s2 = 0 
    s = 0 
    for e in l: 
     s += e 
     s2 += e * e 
    return (s, s2) 

y utilizar el resultado en función de su sigma.

Editar: ahora se puede calcular la varianza de esta manera: (s2 - (s * s)/N)/N

Al tomar en cuenta el comentario de @ Adam Bowen,
tenga en cuenta que si usamos matemáticos trucos y transformamos las fórmulas originales
podemos degradar los resultados.

+13

Con esta solución, la media es 's/n' y la varianza es' s2/n - mean * mean', es decir, la media de los cuadrados menos el cuadrado de la media Sin embargo, debe tener en cuenta que el cálculo de la varianza de esta manera puede ser inexacto para n grande debido a la diferencia de escala entre s2 y e * e durante la acumulación. Desafortunadamente, esto significa que para n grande el algoritmo de dos pasos es mucho más preciso (y una mejor opción). –

+0

@ Adam Bowen, gracias. Me olvidé de mencionar eso. –

+3

Esta respuesta se menciona en [PEP 450] (http://www.python.org/dev/peps/pep-0450/) como un consejo para un enfoque ingenuo del cálculo de varianza con características de estabilidad y precisión deficientes. Vea para comparar las funciones de varianza en el módulo propuesto Python 3.4+ ['statistics'] (http://hg.python.org/cpython/file/tip/Lib/statistics.py). – badp

2

Haz una lista del iterable, o usa itertools.tee().

+1

pero ¿no tendría que guardarse todo el archivo en la memoria? porque get_sigma necesita la entrada de get_mean, en ese caso por qué no solo cargar todo el archivo en la memoria –

+0

ahora sé finalmente cómo puedo hacer Codeblock con un enlace –

+0

't1, t2 = tee (...)' no vale la pena disparo si desea consumir todo 't1' primero y todo' t2' después.En tal caso simplemente use 'list (seq)' e itere sobre eso – Kos

1

No estoy seguro de que haya muchas opciones.

Tendrá que repetir sus números dos veces en cualquier caso, ya que la desviación estándar requerirá la información media sobre cada valor.

Si tiene suficiente memoria, puede obtener acceso de E/S cargando su archivo en la memoria durante la primera iteración, pero eso es IMO.

+0

Esto es falso, según los artículos de Wikipedia citados a continuación ... – Mapio

0

usted tiene dos soluciones

  1. Haga una lista de su repetidor y el bucle tantas veces como desee. Drawback es que todo estará en la memoria, por lo que no es adecuado si su archivo es grande. simple uso de itertools.tee tampoco le ahorrará

  2. No hay otra solución, a menos , que no tienen que pasar a la producción de get_mean a get_sigma, porque en ese caso sólo pueden estar en serie, pero si se elimina esta restricción continuación, puede ejecutar ambas funciones en que utilizan hilos paralelos, y utilizar itertools.tee tener dos iteradores de un

5

creo que Nick D tiene la respuesta correcta.

Suponiendo que desea calcular tanto la media como la varianza en un barrido del archivo (y no desea realmente dos funciones que deben llamarse una después de la otra), puede recopilar la suma de los valores y de sus cuadrados y ellos usan tales sumas (junto con el número de elementos leídos) para calcular al mismo tiempo la media y la varianza.

Hay algunos problemas de estabilidad numérica, pero la idea en

http://en.wikipedia.org/wiki/Computational_formula_for_the_variance

es el ingrediente básico que necesita. Algunos detalles más están en

http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance

donde te sugiero que lea el "algoritmo Naïve".

Espero que esto ayude,

Massimo

1

ya que siento que hay buenos elementos dispersos en múltiples respuestas, me gustaría resumir:

  • Si el archivo es demasiado grande como para encaja perfectamente en la memoria, y si quiere una buena precisión en la varianza, necesita leer el archivo dos veces (con una pasada, la diferencia es la diferencia entre dos números grandes, que no es precisa debido a limitaciones de punto flotante). Tenga en cuenta que es probable que su sistema operativo proporcione alguna aceleración automática para la lectura del segundo archivo, ya que aún puede estar en la memoria RAM durante el segundo pase.

  • Si no le importa la precisión de la varianza, puede simplemente iterar una vez sobre el archivo y calcular las cantidades sugeridas por Nick D, con los detalles proporcionados en el comentario de Adam Bowen.

0

puede utilizar Map reducir en un elegante usanza

muestra es la lista que desea obtener su varianza

muestra = [a, b, c, .. .]

mean = float(reduce(lambda x,y : x+y, sample))/len(sample) 

variance = reduce(lambda x,y: x+y, map(lambda xi: (xi-mean)**2, sample))/ len(sample) 

En una línea sucinta de código:

variance = reduce(lambda x,y: x+y, map(lambda xi: (xi-(float(reduce(lambda x,y : x+y, sample))/len(sample)))**2, sample))/ len(sample) 
+0

para obtener la media no necesita todo esto: simplemente puede 'suma (muestra)/len (muestra)' y similar para la varianza. El gran punto aquí es iterar dos veces en mi * big * archivo. Mi pregunta fue: * una iteración * –

+0

¡Uy! - sí, tienes razón. Pero es un buen pretexto para usar funciones lambda =) – Juan

Cuestiones relacionadas