¿Por qué numpy std () da un resultado diferente a matlab std ()?


87

Intento convertir el código de matlab a numpy y descubrí que numpy tiene un resultado diferente con la función std.

en matlab

std([1,3,4,6])
ans =  2.0817

en numpy

np.std([1,3,4,6])
1.8027756377319946

¿Esto es normal? ¿Y cómo debo manejar esto?

Respuestas:


145

La función NumPy np.stdtoma un parámetro opcional ddof: "Delta grados de libertad". Por defecto, esto es 0. Configúrelo en 1para obtener el resultado de MATLAB:

>>> np.std([1,3,4,6], ddof=1)
2.0816659994661326

Para agregar un poco más de contexto, en el cálculo de la varianza (de la cual la desviación estándar es la raíz cuadrada), generalmente dividimos por el número de valores que tenemos.

Pero si seleccionamos una muestra aleatoria de Nelementos de una distribución más grande y calculamos la varianza, la división por Npuede conducir a una subestimación de la varianza real. Para solucionar este problema, podemos reducir el número por el que dividimos ( los grados de libertad ) a un número menor que N(normalmente N-1). El ddofparámetro nos permite cambiar el divisor por la cantidad que especifiquemos.

A menos que se indique lo contrario, NumPy calculará el estimador sesgado para la varianza ( ddof=0, dividiendo por N). Esto es lo que desea si está trabajando con la distribución completa (y no con un subconjunto de valores que se han elegido al azar de una distribución más grande). Si se proporciona el ddofparámetro, NumPy divide por N - ddof.

El comportamiento predeterminado de MATLAB stdes corregir el sesgo de la varianza de la muestra dividiendo por N-1. Esto elimina parte (pero probablemente no todo) del sesgo en la desviación estándar. Es probable que esto sea lo que desea si está utilizando la función en una muestra aleatoria de una distribución más grande.

La buena respuesta de @hbaderts brinda más detalles matemáticos.


4
Agregaré que en Matlab, std([1 3 4 6],1)es equivalente al valor predeterminado de NumPy np.std([1,3,4,6]). Todo esto se explica con bastante claridad en la documentación de Matlab y NumPy, por lo que recomiendo encarecidamente que el OP se asegure de leerlos en el futuro.
Horchler

En algún momento, este estándar ha cambiado: np.std () = np.std (ddof = 1), aunque la documentación dice que np.std () debería tener el valor predeterminado ddof = 0 ...
ColinMac

61

La desviación estándar es la raíz cuadrada de la varianza. La varianza de una variable aleatoria Xse define como

definición de varianza

Por tanto, un estimador de la varianza sería

estimador sesgado

donde muestra promediodenota la media muestral. Para la selección aleatoria xi, se puede demostrar que este estimador no converge a la varianza real, sino a

estimador imparcial

Si selecciona muestras al azar y estima la media y la varianza de la muestra, tendrá que utilizar un estimador corregido (insesgado)

estimador imparcial

que convergerá a sigma al cuadrado. El término de corrección n-1también se denomina corrección de Bessel.

Ahora, de forma predeterminada, MATLABs stdcalcula el estimador insesgado con el término de corrección n-1. Sin embargo, NumPy (como explicó @ajcr) calcula el estimador sesgado sin término de corrección por defecto. El parámetro ddofpermite establecer cualquier término de corrección n-ddof. Al establecerlo en 1, obtiene el mismo resultado que en MATLAB.

De manera similar, MATLAB permite agregar un segundo parámetro w, que especifica el "esquema de pesaje". El valor predeterminado,, w=0da como resultado el término de corrección n-1(estimador insesgado), mientras que para w=1, solo se utiliza n como término de corrección (estimador sesgado).


2
En la fórmula del estimador corregido, el factor n (dentro de la suma) no debería estar presente.
Frunobulax

3
La intuición detrás del término n-1 en la varianza: ya usó sus muestras para estimar la media que usará para aproximar la varianza. Esto introduce una correlación y, por lo tanto, ddof debe ser 1.
Matthias

@Frunobulax He arreglado el error tipográfico para la posteridad. Lo que sucedió en la ecuación original fue que el límite superior de la suma no se representaba correctamente. En lugar de nir en la parte superior de la notación de suma, entró en la suma.
rayryeng

4

Para las personas que no son buenas con las estadísticas, una guía simplista es:

  • Incluya ddof=1si está calculando np.std()una muestra tomada de su conjunto de datos completo.

  • Asegúrese de ddof=0que está calculando np.std()para la población completa

El DDOF se incluye para las muestras con el fin de contrarrestar el sesgo que puede ocurrir en los números.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.