Как я могу рассчитать дисперсию списка в Python?

Если у меня есть список, как это:

results=[-14.82381293, -0.29423447, -13.56067979, -1.6288903, -0.31632439,
          0.53459687, -1.34069996, -1.61042692, -4.03220519, -0.24332097]

Я хочу вычислить дисперсию этого списка в Python, которая является средним квадратом различий от среднего значения.

Как я могу пойти по этому поводу? Доступ к элементам в списке для выполнения вычислений сбивает меня с толку для получения квадратичных различий.

11 ответов

Решение

Вы можете использовать встроенную функцию 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

@Serge Ballesta очень хорошо объяснил разницу между дисперсией 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

Начало 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

Дисперсия популяции (или дисперсия n) может быть получена с использованием 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), чтобы сэкономить пересчет среднего значения выборки (который является частью вычисления дисперсии).

Ну, есть два способа определения дисперсии. У вас есть дисперсия n, которую вы используете, когда у вас есть полный набор, и дисперсия n-1, которую вы используете, когда у вас есть выборка.

Разница между 2 заключается в том, является ли значение m = sum(xi) / n является реальным средним значением или является лишь приблизительным значением того, каким должно быть среднее значение.

Пример 1: вы хотите знать средний рост учеников в классе и его дисперсию: хорошо, значение m = sum(xi) / n является реальным средним, и формулы, данные Клебом, в порядке (дисперсия n).

Пример 2: вы хотите знать средний час, в который автобус проезжает на автобусной остановке, и его дисперсию. Вы отмечаете час за месяц и получаете 30 значений. Здесь значение m = sum(xi) / n является лишь приближением реального среднего, и это приближение будет более точным с большим количеством значений. В этом случае наилучшим приближением для фактической дисперсии является дисперсия n-1

varRes = sum([(xi - m)**2 for xi in results]) / (len(results) -1)

Хорошо, это не имеет ничего общего с Python, но это оказывает влияние на статистический анализ, и вопрос помечается как статистика и дисперсия

Примечание: как правило, статистические библиотеки, такие как numpy, используют дисперсию n для того, что они называют var или же varianceи дисперсия n-1 для функции, которая дает стандартное отклонение.

иногда все, что я хочу сделать, это отключить свой мозг и КОПИ ВСТАВИТЬ

      import math
def get_mean_var(results):
  # calculate mean
  mean = round(sum(results) / len(results), 2)

  # calculate variance using a list comprehension
  var = round(sum((xi - mean) ** 2 for xi in results) / len(results), 2)
  return mean, var

ИСПОЛЬЗОВАНИЕ

      get_mean_var([1,3,34])

(12.67, 15.11)

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)

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

У 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

Правильный ответ - использовать один из пакетов, таких как 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

Вот мои решения

vac_nums = [0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,3,3,3]#здесь находится ваш код

      mean = sum(vac_nums)/len(vac_nums);

count=0;

for i in range(len(vac_nums)):
   variance = (vac_nums[i]-mean)**2;
   count += variance;

print (count/len(vac_nums));

Без импорта я бы использовал следующий скрипт python3:

#!/usr/bin/env python3

def createData():
    data1=[12,54,60,3,15,6,36]
    data2=[1,2,3,4,5]
    data3=[100,30000,1567,3467,20000,23457,400,1,15]

    dataset=[]
    dataset.append(data1)
    dataset.append(data2)
    dataset.append(data3)

    return dataset

def calculateMean(data):
    means=[]
    # one list of the nested list
    for oneDataset in data:
        sum=0
        mean=0
        # one datapoint in one inner list
        for number in oneDataset:
            # summing up
            sum+=number
        # mean for one inner list
        mean=sum/len(oneDataset)
        # adding a tuples of the original data and their mean to
        # a list of tuples
        item=(oneDataset, mean)
        means.append(item)

    return means

# to do: substract mean from each element and square the result
# sum up the square results and divide by number of elements
def calculateVariance(meanData):
    variances=[]
    # meanData is the list of tuples
    # pair is one tuple
    for pair in meanData:
        # pair[0] is the original data
        interResult=0
        squareSum=0
        for element in pair[0]:
            interResult=(element-pair[1])**2
            squareSum+=interResult
        variance=squareSum/len(pair[0])
        variances.append((pair[0], pair[1], variance))

    return variances





def main():
    my_data=createData()
    my_means=calculateMean(my_data)
    my_variances=calculateVariance(my_means)
    print(my_variances)

if __name__ == "__main__":
    main()

здесь вы получите распечатку исходных данных, их среднего значения и дисперсии. Я знаю, что этот подход охватывает список из нескольких наборов данных, но я думаю, что вы можете быстро адаптировать его для своих целей;)

Используя 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 рассчитывает дисперсию всего населения
Другие вопросы по тегам