- •Python для науки о данных: перезагрузка Ремикс популярной книги Генри Гарнера "Clojure для науки о данных", 2015
- •Об авторе оригинала книги
- •Содержание
- •Предисловие автора к оригиналу книги на Clojure
- •Статистика
- •Скачивание исходного кода примеров
- •Обследование данных
- •Исправление данных
- •Описательные статистики
- •Среднее значение
- •Интерпретация математических обозначений
- •Медиана
- •Дисперсия
- •Квантили
- •Дискретизация данных
- •Гистограммы
- •Нормальное распределение
- •Центральная предельная теорема
- •Булочник господина Пуанкаре
- •Генерирование распределений
- •Асимметрия
- •Графики нормального распределения
- •Способы сопоставительной визуализации
- •Коробчатые диаграммы
- •Интегральные функции распределения
- •Важность визуализации
- •Визуализация данных об электорате
- •Обработка столбцов
- •Добавление производных столбцов
- •Сопоставительная визуализация электоральных данных
- •Визуализация электоральных данных рф
- •Сравнительная визуализация
- •Функции массы вероятности
- •Точечные графики
- •Настройка прозрачности разброса
Статистика
"Важно не кто голосует, а кто подсчитывает голоса."
—Иосиф Сталин
В течение следующих десяти глав книги Python для науки о данных мы попытаемся проложить широкую магистраль по практической научной дисциплине — науке о данных. Правда, надо сказать, по мере продвижения мы обнаружим, что дорога эта не совсем прямая, и внимательный читатель по ходу должен заметить много тем, которые возникают повторно.
Описательные статистики используются для обобщения последовательностей чисел, и они будут в определенной мере встречаться в каждой главе этой книги. В данной главе мы заложим фундамент для последующего материала путем реализации функций на языке Python для вычисления среднего значения, медианы, дисперсии и стандартного отклонения числовой последовательности. При этом мы попытаемся избавиться от боязни интерпретации математических формул.
Как только перед нами стоит задача проанализировать данные, которые состоят из двух и более чисел, становится содержательным вопрос о том, каким образом эти числа распределены. Вы, наверное, уже слыхали такие выражения, как "длинный хвост" и "правило 80/20". Они касаются разброса чисел по диапазону. В этой главе мы продемонстрируем смысл распределений и познакомим с наиболее полезным из них: нормальным распределением.
При изучении распределений чрезвычайную важность играет наглядная и удобная визуализация данных, и для этого мы воспользуемся библиотекой Python Pandas. Мы покажем, как пользоваться ею для загрузки, преобразования и разведочного анализа реальных данных, а также начнем работать с фундаментальной библиотекой numpy для научных вычислений. Мы проведем сопоставительный анализ результатов двух общенациональных выборов — всеобщих выборов в Великобритании 2010 г. и российских выборов депутатов Государственной Думы Федерального Собрания РФ шестого созыва 2011 г. — и увидим, каким образом даже элементарный анализ может предъявить подтверждающие данные о потенциальных фальсификациях.
Скачивание исходного кода примеров
Все прилагаемые к книге примеры исходного кода размещены на веб-сайте издательства ДМК-Пресс по адресу http://www.dmk-press.ru/ либо на GitHub по адресу https://capissimo.github.io/pythonfordatascience/. Примеры исходного кода для каждой главы находится в своем собственном репозитории.
Исходный код для Главы 1, Статистика, можно скачать с https://capissimo.github.io/pythonfordatascience/ch1-statistics.
Исполнимые примеры приводятся регулярно по ходу изложения материала в каждой главе книги с целью продемонстрировать результат выполнения исходного кода, который был только что объяснен, либо с целью показать статистические принципы, которые были представлены. Все имена функций примеров начинаются с префикса ex- и нумеруются последовательно на протяжении каждой главы. Таким образом, первый выполнимый пример Главы 1, Статистика называется ex_1_1, второй — ex_1_2 и т. д.
Обследование данных
В этой главе и во многих других главах этой книги, мы будем пользоваться тремя главными библиотеками экосистемы SciPy: одноименной библиотекой SciPy Library для выполнения сложных математико-статистических расчетов, библиотекой Pandas (http://pandas.pydata.org/) для загрузки данных из разнообразных источников, управления ими и их визуализации, а также библиотекой NumPy (http://www.numpy.org/) в основном для работы с массивами и матрицами.
Все три библиотеки призваны выполненять конкретные функциональные задачи. Библиотека SciPy предоставляет пользователю фундаментальный математический функционал, NumPy предлагает большой набор функций для выполнения разнообразных математических операций на многомерных числовых массивах, тогда как библиотека Pandas предлагает удобные одно-, двух- и многомерные структуры для выполнения статистического анализа гетерогенных данных. Эта библиотека создана по образцу чрезвычайно популярной среды для анализа данных на языке R и объединяет мощь языка Python, его интерактивную оболочку REPL, и набор мощных абстракций для работы с данными. Кроме того, она позволяет оформить результаты вычислений в изображения типографского качества.
Каждая библиотека может быть отдельно включена в ваш собственный исходный код. Чтобы получить доступ к математико-статистическому функционалу, функциям для построения графиков и обработки файлов, в Ваш проект программы следует включить следующие строки:
import numpy as np
import scipy as sp
import pandas as pd
Кроме того, мы будем пользоваться встроенными в Python модулями. Так, например, модуль random позволяет генерировать случайные числа и извлекать выборки, и модуль collections содержит дополнительные структуры данных, из которых мы воспользуемся специальным словарем Counter.
В основе библиотеки Pandas лежит понятие таблицы данных, от англ. DataFrame, т.е. структуры, состоящей из строк и столбцов, или записей и полей. Если у Вас есть опыт работы с реляционными базами данных, то таблицы Pandas пожно представить, как таблицы базы данных. Каждый столбец в табличном наборе данных поименован, а каждая строка имеет одинаковое число столбцов, как и любая другая. Загрузить данные в структуру DataFrame библиотеки Pandas можно несколькими способами, и тот, которым мы воспользуемся, будет зависеть от того, в каком виде наши данные хранятся:
Если данные представлены текстовым файлом с разделением полей данных запятыми (.csv) или символами табуляции (.tsv), то мы будем использовать функцию чтения данных read_csv
Если данные представлены файлом Excel (например, файл .xls или .xlsx), то мы воспользуемся функцией чтения данных read_excel
Для любого другого источника данных (внешняя база данных, веб-сайт, буфер обмена данными, JSON-файлы, HTML-файлы и т. д.) предусмотрен ряд других функций
(REM) Помимо табличных наборов данных в библиотеке Pandas имеется еще одна популярная струтура – Series, т.е. ряд данных. Этоодномерный массив данных, необязательно числовых, которую мы тоже будем использовать. Есть еще одна реже используемая структура – Panel, т.е. панель данных, для представления трехмерных данных, однако в этой книге мы будем по большей части работать с двумерными таблицами и одномерными рядами данных.
В этой части главы в качестве источника данных используется файл Excel, поэтому для чтения данных мы воспользуемся функцией read_excel. Эта функция принимает один обязательный аргумент — файл для загрузки — и ряд необязательных аргументов, в т.ч., номер либо название листа в виде именованного аргумента. Все наши примеры имеют всего один лист, и поэтому мы будем предоставлять лишь один файловый аргумент в виде следующей строки исходного кода:
pd.read_excel('data/ch01/UK2010.xls')
Как Вы заметили выше, ради краткости мы назначили импортируемым библиотекам короткие псевдонимы. Например, в этой книге мы всегда будем обращаться к библиотеке Pandas как pd, к библиотеке NumPy как np и к библиотеке SciPy как sp.
В этой главе мы выполним загрузку данных из нескольких источников, поэтому мы создадим несколько вариантов загрузки данных. В приведенном ниже фрагменте кода мы определяем функцию загрузки данных load_uk:
def load_uk():
'''Загрузить данные по Великобритании'''
return pd.read_excel('data/ch01/UK2010.xls')
Эта функция вернет табличный набор данных DataFrame библиотеки Pandas, содержащий данные по Великобритании. Далее в этой главе, мы определим дополнительные реализации загрузки этого же и еще одного набора данных.
Первая строка электронной таблицы UK2010.xls содержит имена столбцов. Функция библиотеки Pandas read_excel резервирует их в качестве имен столбцов возвращаемого табличного набора данных. Начнем обследование данных с их проверки — атрибут табличного набора данных columns возвращает имена столбцов в виде списка, при этом адресация атрибутов осуществляется при помощи оператора точки (.):
def ex_1_1():
'''Получить имена полей таблицы данных'''
return load_uk().columns
Результатом выполнения приведенной выше функции должен быть следующий ниже список полей таблицы данных Pandas:
Index(['Press Association Reference', 'Constituency Name', 'Region',
'Election Year', 'Electorate', 'Votes', 'AC', 'AD', 'AGS', 'APNI',
...
'UKIP', 'UPS', 'UV', 'VCCA', 'Vote', 'Wessex Reg', 'WRP', 'You',
'Youth', 'YRDPL'],
dtype='object', length=144)
Это очень широкий набор данных, состоящий из 144 полей. Первые шесть столбцов в файле данных описываются следующим образом; последующие столбцы лишь распределяют число голосов по партиям:
Информация для Ассоциации прессы: число, идентифицирующее избирательный округ (представленный одним депутатом)
Название избирательного округа: стандартное название, данное избирательному округу
Регион: географический район Великобритании, где округ расположен
Год выборов: год, в котором выборы состоялись
Электорат: общее число граждан, имеющих право голоса в избирательном округе
Голосование: общее число проголосовавших
Всякий раз, когда мы сталкиваемся с новыми данными, важно потратить некоторое время на то, чтобы в них разобраться. В отсутствии подробного описания данных лучше всего начать с подтверждения наших предположений по поводу данных. Например, мы ожидаем, что этот набор данных содержит информацию о выборах 2010 г., поэтому проверим содержимое столбца года выборов Election Year.
В Pandas предусмотрен обширный функционал для горизонтального (построчного) и вертикального (постолбцового) отбора и фильтрации данных. В элементарном случае нужный столбец можно выбрать, указав его номер или имя. В этой главе мы часто будем таким способом отбирать столбцы данных из различных представлений данных:
def ex_1_2():
'''Получить значения поля "Год выборов"'''
return load_uk()['Election Year']
В результате будет выведен следующий список:
0 2010.0
1 2010.0
2 2010.0
...
646 2010.0
647 2010.0
648 2010.0
649 2010.0
650 NaN
Name: Election Year, dtype: float64
Столбец года выборов возвращается в виде последовательности значений. Полученный результат, возможно, будет нелегко интерпретировать, поскольку табличный набор данных содержит слишком много строк. Учитывая, что мы хотели бы узнать, какие уникальные значения есть в этом столбце, можно воспользоваться методом unique табличного набора данных. Одно из преимуществ использования библиотеки Pandas состоит в том, что ее полезные функции управления данными дополняют те, которые уже встроены в Python. Следующий ниже пример это показывает:
def ex_1_3():
'''Получить значения в поле "Год выборов" без дубликатов'''
return load_uk()['Election Year'].unique()
# [ 2010. nan]
Значение 2010 еще больше подкрепляет наши ожидания в отношении того, что эти данные относятся к 2010 году. Впрочем, наличие специального значения nan, от англ. not a number, т.е. не число, которое сигнализирует о пропущенных данных, является неожиданным и может свидетельствовать о проблеме с данными.
Мы еще не знаем, в скольких элементах набора данных пропущены значения, и установив их число, мы смогли бы решить, что делать дальше. Простой способ подсчитать такие пустые элементы состоит в использовании подкласса словарей Counter языка Python из модуля collections. Этот словарь трансформирует последовательность значений в коллекцию, где ключам поставлены в соответствие количества появлений элементов данных, т.е. их частоты:
def ex_1_4():
'''Рассчитать частоты в поле "Год выборов"
(количества появлений разных значений)'''
return Counter( load_uk()['Election Year'] )
# Counter({nan: 1, 2010.0: 650})
Словарь Python, как одна из основных структур данных, в которой элементам из одного множества поставлены в соответствие элементы из другого множества, в виде пар ключ-значение, реализует математическое понятие отображения в виде однозначного соответствия ключа своему значению. В других языках программирования такая коллекция носит название ассоциативного списка.
Нам не потребуется много времени, чтобы получить подтверждение, что в 2010 г. в Великобритании было 650 избирательных округов. Знание предметной области, как в этом случае, имеет неоценимое значение при проверке достоверности новых данных. Таким образом, весьма вероятно, что значение nan является посторонним, и его можно удалить. Мы увидим, как это сделать, в следующем разделе.
