Рубрики
Без рубрики

Статистика с нуля с Python

Обзор, этот пост – глава 5 в продолжении моего освещения науки о данных от Scratc … Tagged с помощью Python, Data Science, машинного обучения.

Обзор

Этот пост является главой 5 в продолжении моего освещения Наука данных с нуля Джоэл Грус .

Следует отметить, что все, что освещается в этом посте, может быть сделано более целесообразно и эффективно в таких библиотеках, как Numpy а также Статистический модуль в Python Анкет

Основная ценность этой книги, и, по продлению, этот пост, на мой взгляд, является акцентом на обучение Как примитивы Python можно использовать для создания инструментов с нуля. Вот визуальный предварительный просмотр:

В частности, мы рассмотрим, как конкретные особенности языка питона, а также функции, которые мы создали в предыдущем посте на линейная алгебра (См. Также Матрицы ) может использоваться для создания инструментов, используемых для Опишите Данные и отношения в рамках данных (AKA Статистика ).

Я думаю, что это довольно круто. Надеюсь, вы согласитесь.

Пример данных

Эта глава продолжает повествование о вас как о вновь нанятом ученых данных в DataScienster, социальной сети для ученых данных, и ваша задача – описывать Сколько друзей в этой социальной сети. У нас два списки из float работать с. Мы будем работать с num_friends сначала, затем Daily_minutes потом.

Я хотел, чтобы этот пост был автономным, и для того, чтобы сделать это, нам придется читать в большем, чем среднем список из Поплавки Анкет Альтернативой будет получить данные непосредственно из книги github Repo (statistics.py)

num_friends = [100.0,49,41,40,25,21,21,19,19,18,18,16,15,15,15,15,14,14,13,13,13,13,12,12,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]

daily_minutes = [1,68.77,51.25,52.08,38.36,44.54,57.13,51.4,41.42,31.22,34.76,54.01,38.79,47.59,49.1,27.66,41.03,36.73,48.65,28.12,46.62,35.57,32.98,35,26.07,23.77,39.73,40.57,31.65,31.21,36.32,20.45,21.93,26.02,27.34,23.49,46.94,30.5,33.8,24.23,21.4,27.94,32.24,40.57,25.07,19.42,22.39,18.42,46.96,23.72,26.41,26.97,36.76,40.32,35.02,29.47,30.2,31,38.11,38.18,36.31,21.03,30.86,36.07,28.66,29.08,37.28,15.28,24.17,22.31,30.17,25.53,19.85,35.37,44.6,17.23,13.47,26.33,35.02,32.09,24.81,19.33,28.77,24.26,31.98,25.73,24.86,16.28,34.51,15.23,39.72,40.8,26.06,35.76,34.76,16.13,44.04,18.03,19.65,32.62,35.59,39.43,14.18,35.24,40.13,41.82,35.45,36.07,43.67,24.61,20.9,21.9,18.79,27.61,27.21,26.61,29.77,20.59,27.53,13.82,33.2,25,33.1,36.65,18.63,14.87,22.2,36.81,25.53,24.62,26.25,18.21,28.08,19.42,29.79,32.8,35.99,28.32,27.79,35.88,29.06,36.28,14.1,36.63,37.49,26.9,18.58,38.48,24.48,18.95,33.55,14.24,29.04,32.51,25.63,22.22,19,32.73,15.16,13.9,27.2,32.01,29.27,33,13.74,20.42,27.32,18.23,35.35,28.48,9.08,24.62,20.12,35.26,19.92,31.02,16.49,12.16,30.7,31.22,34.65,13.13,27.51,33.2,31.57,14.1,33.42,17.44,10.12,24.42,9.82,23.39,30.93,15.03,21.67,31.09,33.29,22.61,26.89,23.48,8.38,27.81,32.35,23.84]

daily_hours = [dm / 60 for dm in daily_minutes]

Описание

num_friends Список – это список чисел, представляющих «количество друзей», у человека, например, у одного человека 100 друзей. Первое, что мы делаем, чтобы описать данные, – это создать планку с таблицей, на которой есть количество людей, у которых 100 друзей, 49 друзей, 41 друзья и так далее.

Мы импортируем Счетчик от Коллекции и импорт matplotlib.pyplot Анкет

Мы будем использовать Счетчик повернуть num_friends Список в DefaultDict (int) -Поподобные клавиши сопоставления объектов до количества. Для получения дополнительной информации, пожалуйста, обратитесь к этому Предыдущий пост на прилавках.

Как только мы используем Счетчик Коллекция, Высокопроизводительный дат контейнера , мы можем использовать такие методы, как Most_common Чтобы найти ключи с наиболее распространенными значениями. Здесь мы видим, что пять наиболее распространенных Количество друзей 6, 1, 4, 3 и 9 соответственно.

from collections import Counter

import matplotlib.pyplot as plt

friend_counts = Counter(num_friends)

# the five most common values are: 6, 1, 4, 3 and 9 friends
# [(6, 22), (1, 22), (4, 20), (3, 20), (9, 18)]
friend_counts.most_common(5) 

Чтобы продолжить заговор, мы будем использовать Друг_COUNTS Чтобы создать Понимание списка это пройдет через Friends_count и для всех Ключи От 0-101 (xs) и распечатать соответствующий ценность (Если это существует). Это становится осью Y, чтобы num_friends , который является осью X:

xs = range(101)                     # x-axis: largest num_friend value is 100
ys = [friend_counts[x] for x in xs] # y-axis
plt.bar(xs, ys)
plt.axis([0, 101, 0, 25])
plt.title("Histogram of Friend Counts")
plt.xlabel("# of friends")
plt.ylabel("# of people")
plt.show()

Вот сюжет ниже. Вы можете увидеть одного человека с 100 друзьями.

Вы также можете прочитать больше о визуализации данных здесь.

В качестве альтернативы мы могли бы генерировать простую статистику для описания данных с использованием встроенных методов Python: Лен , мин , Макс и отсортировано Анкет

num_points = len(num_friends) # number of data points in num_friends: 204
largest_value = max(num_friends) # largest value in num_friends: 100
smallest_value = min(num_friends) # smallest value in num_friends: 1

sorted_values = sorted(num_friends) # sort the values in ascending order
second_largest_value = sorted_values[-2] # second largest value from the back: 49

Центральные тенденции

Наиболее распространенный способ описания набора данных – найти его среднее , которая является суммой всех значений, разделенных на количество значений. примечание : Мы будем продолжать использовать аннотации типа. На мой взгляд, это помогает вам быть более преднамеренным и внимательным программистом Python.

from typing import List

def mean(xs: List[float]) -> float:
    return sum(xs) / len(xs)

assert 7.3333 < mean(num_friends) < 7.3334

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

Здесь мы создадим две частные функции для обеих ситуаций – равномерное и нечетное количество точек данных – при расчете медианы. Во -первых, мы отсортируем значения данных. Тогда для даже число Значения, мы найдем два средних значения и разделим их. Для нечетное число значений, мы разделим длина набора данных на 2 (то есть 50).

Наша средняя функция вернет любую из частной функции _median_even или _median_odd условно в зависимости от того, является ли длина списка чисел делится) на 2.

def _median_even(xs: List[float]) -> float:
    """If len(xs) is even, it's the average of the middle two elements"""
    sorted_xs = sorted(xs)
    hi_midpoint = len(xs) // 2   # e.g. length 4 => hi_midpoint 2
    return (sorted_xs[hi_midpoint - 1] + sorted_xs[hi_midpoint]) / 2

def _median_odd(xs: List[float]) -> float:
    """If len(xs) is odd, its the middle element"""
    return sorted(xs)[len(xs) // 2]

def median(v: List[float]) -> float:
    """Finds the 'middle-most' value of v"""
    return _median_even(v) if len(v) % 2 == 0 else _median_odd(v)

assert median([1,10,2,9,5]) == 5
assert median([1, 9, 2, 10]) == (2 + 9) / 2

Потому что медиана – это среднее значение , это не полностью зависит от каждого значения в данных. Для иллюстрации гипотетически, если у нас есть другой список num_friends2 Где у одного человека было 10 000 друзей, среднее было бы гораздо более чувствительным к этому изменению, чем медиана было бы.

num_friends2 = [10000.0,49,41,40,25,21,21,19,19,18,18,16,15,15,15,15,14,14
    ,13,13,13,13,12,12,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,9
    ,9,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7
    ,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5
    ,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3
    ,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1
    ,1,1,1,1,1,1,1,1,1,1,1,1]

mean(num_friends2)   # more sensitive to outliers: 7.333 => 55.86274509803921
median(num_friends2) # less sensitive to outliers: 6.0 => 6.0

Вы также можете использовать Квантиль Чтобы описать ваши данные. Всякий раз, когда вы слышали «x процентиль», это описание квантилей относительно 100. Фактически, медиана составляет 50 -й процентиль (где 50% данных лежит ниже этой точки, и 50% лежит выше).

Потому что Квантиль является позицией от 0-100, второй аргумент-это поплавок от 0,0 до 1,0. Мы будем использовать этот поплавок для умножения с длиной списка. Тогда мы завершим в int Для создания целочисленного индекса, который мы будем использовать на отсортированном XS, чтобы найти квантиль.

def quantile(xs: List[float], p: float) -> float:
    """Returns the pth-percentile value in x"""
    p_index = int(p * len(xs))  
    return sorted(xs)[p_index]

assert quantile(num_friends, 0.10) == 1
assert quantile(num_friends, 0.25) == 3
assert quantile(num_friends, 0.75) == 9
assert quantile(num_friends, 0.90) == 13

Наконец, у нас есть режим , который смотрит на наиболее распространенные ценности. Сначала мы используем Счетчик Метод в нашем параметре списка и, поскольку счетчик является подклассом диктат У нас есть доступ к таким методам, как значения () Чтобы найти все значения и элементы () Чтобы найти пары ключевых значений.

Мы определяем max_count Чтобы найти максимальное значение (22), функция возвращает понимание списка, которое проходит через counts.items () Чтобы найти ключ, связанный с max_count (22). Это 1 и 6, что означает двадцать два человека (режим ) имел одного или шесть друзей.

def mode(x: List[float]) -> List[float]:
    """Returns a list, since there might be more than one mode"""
    counts = Counter(x)
    max_count = max(counts.values())
    return [x_i for x_i, count in counts.items() if count == max_count]


assert set(mode(num_friends)) == {1, 6}

Потому что мы уже использовали счетчик на num_friends Ранее (см. Друг_COUNTS ), мы могли бы только что назвать most_common (2) метод для получения тех же результатов:

mode(num_friends) # [6, 1]
friend_counts.most_common(2) # [(6, 22), (1, 22)]

Дисперсия

Помимо центральных тенденций наших данных, мы также захотим понять, что это распространение или рассеяние. Инструменты для этого диапазон данных , дисперсия , стандартное отклонение и межквартильный диапазон Анкет

Диапазон – это простое значение максимального значения минус мин.

Измерения дисперсии, насколько далеко a Набор чисел от их среднего значения Анкет Что более интересно, для нашей цели, это то, как нам нужно одолжить функции, которые мы ранее построили в векторы и матрицы Сообщения для создания функции дисперсии.

Если вы посмотрите на его страницу в Википедии, дисперсия это квадратное отклонение переменной от его среднего.

Во -первых, нам нужно создать de_mean Функция, которая берет список чисел и вычитается из всех чисел в списке, среднее значение (это дает нам отклонение от среднего).

Тогда мы sum_of_squares Все эти отклонения, что означает, что мы возьмем все значения, умножаем их на себя (квадрат его), затем добавим значения (и разделим на длину списка минус один), чтобы получить дисперсию.

Напомним, что sum_of_squares это особый случай точка Функция продукта.

# variance

from typing import List

Vector = List[float]

# see vectors.py in chapter 4 for dot and sum_of_squares

def dot(v: Vector, w: Vector) -> float:
    """Computes v_1 * w_1 + ... + v_n * w_n"""
    assert len(v) == len(w), "vectors must be the same length"
    return sum(v_i * w_i for v_i, w_i in zip(v,w))

def sum_of_squares(v: Vector) -> float:
    """Returns v_1 * v_1 + ... + v_n * v_n"""
    return dot(v,v)

def de_mean(xs: List[float]) -> List[float]:
    """Translate xs by subtracting its mean (so the result has mean 0)"""
    x_bar = mean(xs)
    return [x - x_bar for x in xs]

def variance(xs: List[float]) -> float:
    """Almost the average squared deviation from the mean"""
    assert len(xs) >= 2, "variance requires at least two elements"
    n = len(xs)
    deviations = de_mean(xs)
    return sum_of_squares(deviations) / (n - 1)

assert 81.54 < variance(num_friends) < 81.55

дисперсия это sum_of_squares отклонения, которые могут быть сложно интерпретировать. Например, у нас есть num_friends со значениями в диапазоне от 0 до 100.

Что означает дисперсия 81,54?

Более распространенной альтернативой является стандартное отклонение Анкет Здесь мы берем квадратный корень дисперсии, используя Python’s Математика модуль.

Со стандартным отклонением 9,03, и мы знаем среднее значение num_friends 7.3, все ниже 7 + или 7 – 9 (0 друзей) друзей все еще В пределах стандартного отклонения среднего Анкет И мы можем проверить, запустив Друг_COUNTS что большинство людей находятся в пределах стандартного отклонения среднего значения.

С другой стороны, мы знаем, что кто -то с 20 друзьями более одного стандартного отклонения вдали от среднего.

import math

def standard_deviation(xs: List[float]) -> float:
    """The standard deviation is the square root of the variance"""
    return math.sqrt(variance(xs))

assert 9.02 < standard_deviation(num_friends) < 9.04

Однако, потому что стандартное отклонение строится на дисперсия , что зависит от иметь в виду Мы знаем, что, как и среднее, он может быть чувствителен к выбросам, мы можем использовать альтернативу, называемую межквартильный диапазон , который основан на медиана и менее чувствителен к выбросам.

В частности, межквартильный диапазон можно использовать для изучения num_friends между 25 -м и 75 -м процентилем. Большая часть людей будет иметь Около 6 друзей Анкет

def interquartile_range(xs: List[float]) -> float: 
    """Returns the difference between the 75%-ile and the 25%-ile"""
    return quantile(xs, 0.75) - quantile(xs, 0.25)

assert interquartile_range(num_friends) == 6

Теперь, когда мы опишем один список данных, мы также захотим взглянуть на потенциальную связь между двумя источниками данных. Например, у нас может быть гипотеза о том, что количество времени, затрачиваемого на социальную сеть DataScienster, каким -то образом связано с количеством друзей, которые у кого -то есть.

Далее мы рассмотрим ковариацию и корреляции.

Корреляция

Если дисперсия – это сколько сингл Набор чисел отклоняется от его среднего (то есть см. de_mean выше), затем Ковариация Измеряют, как два набора чисел варьируются от их означает. С идеей, что если они совпадают с той же суммой, то они могут быть связаны.

Здесь мы одолжим точка Производственная функция, которую мы разработали в векторы в Python сообщение.

Более того, мы рассмотрим, есть ли отношения между num_friends и Daily_minutes и Daily_hours (См. Выше).

def covariance(xs: List[float], ys: List[float]) -> float:
    assert len(xs) == len(ys), "xs and ys must have same number of elements"
    return dot(de_mean(xs), de_mean(ys)) / (len(xs) - 1)

assert 22.42 < covariance(num_friends, daily_minutes) < 22.43
assert 22.42 / 60 < covariance(num_friends, daily_hours) < 22.43 / 60

Как и в случае с дисперсией, аналогичная критика может быть сделана из Ковариация , вам нужно сделать дополнительные шаги, чтобы интерпретировать это. Например, ковариация num_friends и Daily_minutes 22,43.

Что это обозначает? Это считается прочными отношениями?

Более интуитивно понятной мерой будет Корреляция :

def correlation(xs: List[float], ys: List[float]) -> float:
    """Measures how much xs and ys vary in tandem about their means"""
    stdev_x = standard_deviation(xs)
    stdev_y = standard_deviation(ys)
    if stdev_x > 0 and stdev_y > 0:
        return covariance(xs,ys) / stdev_x / stdev_y
    else:
        return 0 # if no variation, correlation is zero

assert 0.24 < correlation(num_friends, daily_minutes) < 0.25
assert 0.24 < correlation(num_friends, daily_hours) < 0.25

Разделив стандартное отклонение обеих входных переменных, корреляция всегда находится между -1 (идеальная (анти) корреляция) и 1 (идеальная корреляция). Корреляция 0,24 является относительно слабой корреляцией (хотя то, что считается слабым, умеренным, сильным, зависит от контекста данных).

Одна вещь, которую нужно иметь в виду, это Парадокс Симпсона или когда взаимосвязь между двумя переменными меняется при учете третьего, Смешание переменная. Более того, мы должны помнить об этом клише (это клише по какой -то причине): Корреляция не подразумевает причинно -следственную связь Анкет

Резюме

Мы всего лишь пять глав, и мы можем начать понимать, как мы строим инструменты Теперь , что мы будем использовать позже. Вот визуальное резюме того, что мы рассмотрели в этом посте, и как он подключается к предыдущим сообщениям, а именно векторы , матрицы и курс аварии Python: см. настройка , функции , списки , словари и более.

Этот пост продолжает мое освещение этой книги:

Для получения дополнительного содержания в области данных, машинного обучения, R, Python, SQL и других, Найди меня в Твиттере Анкет

Оригинал: “https://dev.to/paulapivat/statistics-from-scratch-with-python-18fa”