Как я могу рассчитать дисперсию списка в python?
Если у меня есть список вроде этого:
results=[-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439,
0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
Я хочу рассчитать дисперсию этого списка в Python, который является средним квадратом различий от среднего.
Как я могу это сделать? Доступ к элементам в списке для выполнения вычислений сбивает меня с толку за квадратные различия.
Ответы
Ответ 1
Вы можете использовать встроенную функцию numpy var
:
import numpy as np
results = [-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439,
0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
print(np.var(results))
Это дает вам 28.822364260579157
Если - по какой-либо причине - вы не можете использовать numpy
и/или вы не хотите использовать встроенную функцию для него, вы также можете вычислить его "вручную", используя, например, понимание списка:
# calculate mean
m = sum(results) / len(results)
# calculate variance using a list comprehension
var_res = sum((xi - m) ** 2 for xi in results) / len(results)
который дает вам идентичный результат.
Если вас интересует стандартное отклонение, вы можете использовать numpy.std:
print(np.std(results))
5.36864640860051
@Серж Баллеста очень хорошо объяснил разницу между дисперсией n
и n-1
. В numpy вы можете легко установить этот параметр, используя опцию ddof
; по умолчанию это 0
, поэтому для случая n-1
вы можете просто сделать:
np.var(results, ddof=1)
Решение "от руки" приведено в ответе @Serge Ballesta.
Оба подхода дают 32.024849178421285
.
Вы можете установить параметр также для std
:
np.std(results, ddof=1)
5.659050201086865
Ответ 2
Ну, есть два способа определения дисперсии. У вас есть дисперсия n, которую вы используете, когда у вас есть полный набор, и дисперсия n-1, которую вы используете, когда у вас есть образец.
Разница между 2 заключается в том, является ли значение m = sum(xi) / n
реальным средним значением или является ли оно просто приближением к среднему значению.
Пример1: вы хотите узнать среднюю высоту учащихся в классе и его дисперсию: ok, значение m = sum(xi) / n
- это реальное среднее значение, а формулы, заданные Cleb, являются ok (дисперсия n).
Пример2: вы хотите узнать средний час, с которого автобус проходит на остановке автобуса и его дисперсию. Вы отмечаете час в течение месяца и получаете 30 значений. Здесь значение m = sum(xi) / n
является лишь приближением реального среднего и что приближение будет более точным с большим количеством значений. В этом случае наилучшим приближением для фактической дисперсии является дисперсия n-1
varRes = sum([(xi - m)**2 for xi in results]) / (len(results) -1)
Хорошо, это не имеет ничего общего с Python, но оно оказывает влияние на статистический анализ, и вопрос помечен statistics и variance
Примечание. Обычно статистические библиотеки, такие как numpy, используют дисперсию n для того, что они называют var
или variance
, а дисперсия n-1 для функции, которая дает стандартное отклонение.
Ответ 3
Начиная с Python 3.4
, стандартная библиотека поставляется с функцией variance
(выборочная дисперсия или дисперсия n-1) в составе модуля statistics
:
from statistics import variance
# data = [-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439, 0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
variance(data)
# 32.024849178421285
Р opulation дисперсия (или дисперсия п) может быть получена с использованием pvariance
функции:
from statistics import pvariance
# data = [-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439, 0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
pvariance(data)
# 28.822364260579157
Также обратите внимание, что если вы уже знаете среднее значение вашего списка, функции variance
и pvariance
принимают второй аргумент (соответственно xbar
и mu
), чтобы сэкономить пересчет среднего значения выборки (которая является частью вычисления дисперсии).
Ответ 4
Numpy действительно самый элегантный и быстрый способ сделать это.
Я думаю, что фактический вопрос касался того, как получить доступ к отдельным элементам списка, чтобы сделать такой расчет самостоятельно, поэтому ниже примера:
results=[-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439,
0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]
import numpy as np
print 'numpy variance: ', np.var(results)
# without numpy by hand
# there are two ways of calculating the variance
# - 1. direct as central 2nd order moment (https://en.wikipedia.org/wiki/Moment_(mathematics))divided by the length of the vector
# - 2. "mean of square minus square of mean" (see https://en.wikipedia.org/wiki/Variance)
# calculate mean
n= len(results)
sum=0
for i in range(n):
sum = sum+ results[i]
mean=sum/n
print 'mean: ', mean
# calculate the central moment
sum2=0
for i in range(n):
sum2=sum2+ (results[i]-mean)**2
myvar1=sum2/n
print "my variance1: ", myvar1
# calculate the mean of square minus square of mean
sum3=0
for i in range(n):
sum3=sum3+ results[i]**2
myvar2 = sum3/n - mean**2
print "my variance2: ", myvar2
дает вам:
numpy variance: 28.8223642606
mean: -3.731599805
my variance1: 28.8223642606
my variance2: 28.8223642606
Ответ 5
У Numpy есть метод, который сделает это за вас, и это самый простой способ. Или вы можете написать свою собственную функцию.
import numpy as np
np.var(a)
ИЛИ ЖЕ
def find_variance(a):
n = len(a)
mean = sum(a)/n
diff_sq = [None] * n
for i in range(n):
diff_sq[i] = (a[i] - mean) ** 2
return sum(diff_sq)/n
Ответ 6
Используя python, вот несколько способов сделать это:
import statistics as st
n = int(input())
data = list(map(int, input().split()))
Подход1 - с помощью функции
variance = st.pvariance(data)
Подход 2: использование базовой математики
mean = sum(data)/n
variance = sum([((x - mean) ** 2) for x in X]) / n
print("{0:0.1f}".format(variance))
Замечания:
-
variance
рассчитывает дисперсию выборки населения -
pvariance
рассчитывает дисперсию всего населения
Ответ 7
Правильный ответ - использовать один из пакетов, таких как NumPy, но если вы хотите использовать свой собственный пакет и делать это постепенно, есть хороший алгоритм, который имеет более высокую точность. Смотрите эту ссылку https://www.johndcook.com/blog/standard_deviation/
Я перенес свою реализацию Perl на Python. Пожалуйста, укажите проблемы в комментариях.
Mklast = 0
Mk = 0
Sk = 0
k = 0
for xi in results:
k = k +1
Mk = Mklast + (xi - Mklast) / k
Sk = Sk + (xi - Mklast) * ( xi - Mk)
Mklast = Mk
var = Sk / (k -1)
print var
Ответ
>>> print var
32.0248491784
Ответ 8
import numpy as np
def get_variance(xs):
mean = np.mean(xs)
summed = 0
for x in xs:
summed += (x - mean)**2
return summed / (len(xs))
print(get_variance([1,2,3,4,5]))
из 2.0
a = [1,2,3,4,5]
variance = np.var(a, ddof=1)
print(variance)