Как рассчитать стандартное отклонение в python без использования numpy?

0

Вопрос

Я пытаюсь рассчитать стандартное отклонение в python без использования numpy или любой внешней библиотеки, за исключением math. Я хочу стать лучше в написании алгоритмов и просто делаю это в качестве "домашнего задания", совершенствуя свои навыки работы на python. Моя цель-перевести эту формулу на python, но я не получаю правильного результата.

Я использую множество скоростей, где speeds = [86,87,88,86,87,85,86]

Когда я бегу:

std_dev = numpy.std(speeds)
print(std_dev)

Я получаю: 0,903507902905. Но я не хочу полагаться на глупышку. Так...

Моя реализация заключается в следующем:

import math

speeds = [86,87,88,86,87,85,86]

def get_mean(array):
    sum = 0
    for i in array:
        sum = sum + i
    mean = sum/len(array)
    return mean

def get_std_dev(array):
    # get mu
    mean = get_mean(array)
    # (x[i] - mu)**2
    for i in array:
        array = (i - mean) ** 2
        return array
    sum_sqr_diff = 0
    # get sigma
    for i in array:
        sum_sqr_diff = sum_sqr_diff + i
        return sum_sqr_diff
    # get mean of squared differences
    variance = 1/len(array)
    mean_sqr_diff = (variance * sum_sqr_diff)
    
    std_dev = math.sqrt(mean_sqr_diff)
    return std_dev

std_dev = get_std_dev(speeds)
print(std_dev)

Теперь, когда я бегу:

std_dev = get_std_dev(speeds)
print(std_dev)

Я получаю: [0] но я ожидаю 0,903507902905

Что я здесь упускаю?

algorithm mean python standard-deviation
2021-11-23 20:46:59
5

Лучший ответ

1
speeds = [86,87,88,86,87,85,86]

# Calculate the mean of the values in your list
mean_speeds = sum(speeds) / len(speeds)

# Calculate the variance of the values in your list
# This is 1/N * sum((x - mean(X))^2)
var_speeds = sum((x - mean_speeds) ** 2 for x in speeds) / len(speeds)

# Take the square root of variance to get standard deviation
sd_speeds = var_speeds ** 0.5

>>> sd_speeds
0.9035079029052513
2021-11-23 21:10:27

Когда я бегу, я получаю 1.0.
bkleeman

Перезагрузите ядро python. Что-то, что вы сделали, испортило одну из встроенных функций.
CJR

О, не бери в голову, ты используешь python2.7, не так ли? Добавить from __future__ import division - стандартное подразделение / это неверное разделение до python 3.0, если вы не импортируете из будущего.
CJR

да, я использую 2.7. Ваше решение плюс импорт будущего подразделения сейчас работает на меня. Большое вам спасибо за помощь!
bkleeman

Пора переходить к py3, приятель.
CJR

Я довольно новичок в python, и, честно говоря, я еще не понял рифму или причину того, когда моя машина запускает py2 против py3. Мне придется с этим разобраться.
bkleeman

Многие дистрибутивы Linux поставляются с py2.7 и py3 - у вас, вероятно, есть python3 (но двоичный файл python3 вместо того, чтобы просто python). Вы также можете рассмотреть возможность использования чего-то вроде анаконды для настройки среды. py2.7 давно истек срок службы.
CJR
1

Проблема в вашем коде заключается в повторном использовании массива и возврате в середине цикла

def get_std_dev(array):
    # get mu
    mean = get_mean(array)       <-- this is 86.4
    # (x[i] - mu)**2
    for i in array:
        array = (i - mean) ** 2  <-- this is almost 0
        return array             <-- this is the value returned

Теперь давайте рассмотрим алгоритм, который вы используете. Обратите внимание, что обычно используются две формулы отклонения std. Существуют различные аргументы относительно того, какой из них верен.

sqrt(sum((x - mean)^2) / n)

или

sqrt(sum((x - mean)^2) / (n -1))

Для больших значений n используется первая формула, так как значение -1 незначительно. Первая формула может быть сведена к

sqrt(sum(x^2) /n - mean^2)

Итак, как бы вы сделали это на python?

def std_dev1(array):
   n = len(array)
   mean = sum(array) / n
   sumsq = sum(v * v for v in array)
   return (sumsq / n - mean * mean) ** 0.5
2021-11-24 06:21:59
-1

некоторые проблемы в коде, одна из них-возвращаемое значение внутри оператора for. вы можете попробовать это

def get_mean(array):
    return sum(array) / len(array)


def get_std_dev(array):
    n = len(array)
    mean = get_mean(array)
    squares_arr = []
    for item in array:
        squares_arr.append((item - mean) ** 2)
    return math.sqrt(sum(squares_arr) / n)
2021-11-23 22:06:23
-2

Этот. Тебе нужно избавиться от return внутри для петель.

def get_std_dev(array):
    # get mu
    mean = get_mean(array)
    sum_sqr_diff = 0
    # get sigma
    for i in array:
        sum_sqr_diff = sum_sqr_diff + (i - mean)**2
    # get mean of squared differences
    variance = 1/len(array)
    mean_sqr_diff = (variance * sum_sqr_diff)
    
    std_dev = math.sqrt(mean_sqr_diff)
    return std_dev
2021-11-23 20:59:12
-2

Если вы не хотите использовать numpy все в порядке, попробуйте statistics пакет на python

import statistics

st_dev = statistics.pstdev(speeds)
print(st_dev)

или, если вы все еще готовы использовать индивидуальное решение, я рекомендую вам использовать следующий способ, используя понимание списка вместо вашего сложного подхода с ошибками

import math

mean = sum(speeds) / len(speeds)
var = sum((l-mean)**2 for l in speeds) / len(speeds)
st_dev = math.sqrt(var)
print(st_dev)
2021-11-23 20:58:42

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................