В этой части мы попрактикуемся в расчётах среднего, медианы и стандартного отклонения с помощью Python (а точнее, библиотеки pandas). Но перед этим начнём разбираться в синтаксисе языка — рассмотрим основные типы данных и научимся выполнять с ними базовые операции.
Стандартные типы данных
Для анализа данных мы будем использовать Python. Если он у вас ещё не установлен — советуем прерваться и сперва почитать вот эту инструкцию. В ней мы рассказываем, как установить его и сопутствующие библиотеки под вашу операционную систему. Если всё ок — давайте продолжать.
Чтобы работать с данными, их необходимо прочитать и сохранить в памяти как объект подходящего типа под именем, которое мы называем переменной. Мы уже говорили о переменных раньше, и важно не путать использование этого термина в статистике и в программировании.
🔍 Напомним: в программировании переменная — это имя для хранимых в оперативной памяти компьютера данных, по которому мы можем обращаться к ним неоднократно.
Попробуем создать переменную для числа 10.
>>> a = 10
Здесь а
— имя переменной, =
— оператор присваивания, а 10
— значение переменной. В Python тип данных, который соответствует целым числам, называется integer
(целочисленный). Теперь мы можем при необходимости обращаться к данным, которые содержит эта переменная.
>>> print(a)
10
>>> a + 10
20
Переменная может содержать и текстовые данные. Этот тип данных называется string (строка). Для создания мы используем:
>>> c = 'Name'
>>> print(c)
Name
Переменная может содержать сразу несколько элементов. Такой тип данных называется list (список). В Python список может хранить в качестве элементов любой тип данных: строки, числа или даже списки. Чтобы создать список, мы присваиваем одной переменной несколько объектов, перечисленных в квадратных скобках.
>>> b = [1, 5, 10]
>>> print(b)
[1, 5, 10]
Списки поддерживают операцию индексирования. Это значит, что мы можем обращаться к отдельным элементам списка по их порядковым номерам. Обратите внимание, что первый элемент имеет индекс 0
, второй — 1
и так далее. Это связано с тем, что в программировании отсчёт ведётся с нуля, а не с единицы.
>>> print(b[0])
1
Последний из типов данных, который мы упомянем в этом параграфе, — это вещественные числа. Обычно в языках программирования они записываются в форме десятичных дробей с некоторым ограниченным числом знаков после запятой в дробной части. Если в результате вычисления получается число, которое выходит за пределы этого числа знаков, то оно записывается в округлённом виде.
Например, результат деления 2 на 3 должен быть бесконечной периодической дробью, однако в Python он будет записан и выведен на экран следующим образом:
>>> 2 / 3
0.6666666666666666
Из курса алгебры мы можем помнить, что более точная запись ответа выглядит как 0.(6), где (6) фиксирует периодическую часть дроби. Именно необходимость манипулировать дробями с ограниченной точностью приводит к тому, что мы различаем типы данных для целых и вещественных чисел.
Стандартные типы данных в Python:
Описание |
Имя в Python |
Пример |
Целое число |
integer |
3 |
Вещественное число |
float |
3.22 |
Строка |
string |
qwerty |
Логический тип |
bool |
True |
Мы упомянули в таблице логический тип, который может принимать только два значения True
и False
. Они могут быть получены в результате выполнения как логических операций, так и операций сравнения.
Мы уже упоминали, что с переменными можно выполнять операции, и даже выполняли некоторые из них: получали элемент списка по индексу и складывали числа. Знак сложения в выражении f = d + e называется оператором.
Оператор — это символ, который выполняет операцию с переменными.
Составим перечень и сразу отсортируем его по приоритету выполнения:
Уровень |
Категория |
Операторы |
7 (в первую очередь) |
Возведение в степень |
** |
6 |
Умножение |
*, /, //, % |
5 |
Сложение |
+, – |
4 |
Сравнение |
==, !=, <=, >=, >, < |
3 |
Логическое НЕ |
not |
2 |
Логическое И |
and |
1 |
Логическое ИЛИ |
or |
Приведём несколько примеров выполнения операций с помощью операторов. Обратите внимание, что при использовании операторов сравнения и логических операторов в качестве результата мы получаем логический тип данных (bool).
>>> 1 + 23
24
>>> 2 >= 3
False
>>> True and False
False
Датафреймы
Все типы данных и действия с ними, которые мы описали в предыдущем пункте, доступны любым пользователям языка Python. Это так называемая стандартная библиотека, которая содержит самые базовые возможности языка. Однако она может быть расширена с помощью дополнительных библиотек, которые предоставляются другими разработчиками. Зачастую они не связаны с командой, которая развивает сам язык программирования. Обычно библиотека содержит расширения, позволяющие решать конкретный тип задач, например работу с данными или веб-разработку.
🔍 Библиотека — это набор типов данных, функций и методов.
Так как стандартные возможности Python по работе с табличными данными ограничены, то для этого нам нужна дополнительная библиотека. Она называется pandas. Эта библиотека позволяет читать табличные данные, совершать с ними преобразования, вычислять статистические параметры, а также служит основой для библиотек, которые содержат реализации более сложных методов анализа.
Сама Pandas не содержит данных — их нужно откуда-то взять. Мы подготовили тестовый набор с данными о пассажирах «Титаника» — скачайте его отсюда и положите в папку с проектом (это важно!).
Далее: чтобы использовать библиотеку, нам нужно импортировать её, то есть сделать доступной для использования:
>>> import pandas as pd
Здесь мы после ключевого слова import
указываем название библиотеки, а после ключевого слова as
задаём псевдоним для неё. Если псевдоним не используется, то библиотека добавляется под своим собственным названием. Для pandas принято использовать псевдоним pd. С помощью ключевого слова import
мы можем загрузить любую библиотеку.
Для открытия скачанного файла с данными о пассажирах «Титаника» мы используем следующую инструкцию:
>>> df = pd.read_csv('titanic.csv')
df
— это имя переменной, в которой будут храниться наши данные. pd
указывает на то, из какой библиотеки берётся метод, read_csv()
— название метода. А в скобках мы указываем параметры, которые дополнительно определяют поведение метода.
Если уже знаете, что такое метод и функция, то можете спокойно пропустить этот кусок. А если нет — смотрите. Выше мы приводили пример: складывали числа 1 и 23 — и Python возвращал нам ответ (24). Представьте: нам нужно складывать не только указанные числа, а вообще любые положительные целые числа. И не один раз, а несколько. Каждый раз писать выражение утомительно, поэтому можно вынести операцию сложения в функцию.
Вот как это сделать:
>>> def sum_two_numbers(a, b):
>>> result = a + b
>>> return result
Это описание функции. Когда мы её вызовем, то вместо чисел a и b подставятся переданные нами аргументы. Смотрите:
>>> sum_1 = sum_two_numbers(1, 5)
>>> print(sum_1)
6
Вот что тут произошло:
- объявили переменную (sum_1);
- вызвали функцию с переданными аргументами sum_two_numbers(1, 5);
- записали результат выполнения функции в переменную;
- вывели значение переменной в консоль.
Преимущество функции — мы можем вызывать её сколь угодно много раз, меняя аргументы:
>>> sum_1 = sum_two_numbers(1, 5)
>>> print(sum_1)
6
>>> sum_2 = sum_two_numbers(100, 10)
>>> print(sum_2)
110
>>> sum_3 = sum_two_numbers(-3, 6)
>>> print(sum_3)
3
С функцией разобрались. Теперь расскажем о методе. Если объяснять максимально коротко и на пальцах, то метод — это функция, но внутри библиотеки.
Пока нам достаточно этого определения. Теперь вернёмся к pandas.
Аргумент метода read_csv('titanic.csv')
– путь до файла с данными, который нас интересует. Так как в нашем примере он лежит в рабочей папке, то мы можем ограничиться только его названием. Если файл находится в отличном от рабочей директории месте, то необходимо прописать абсолютный путь к файлу. Например, так:
>>> df = pd.read_csv('C:/Users/User/Projects/Titanic/titanic.csv')
Чтобы узнать, что именно в вашем случае является рабочей директорией, можно использовать следующий код:
>>> import os
>>> os.getcwd()
'C:/Users/User/Projects/Titanic/'
После загрузки данных мы создали объект с типом данных, который называется датафрейм (DataFrame). Его нет в стандартной библиотеке, но он доступен в pandas.
🔍 Датафрейм — тип данных, используемый в библиотеке pandas для работы с табличными данными. Аналогичные типы данных доступны в других библиотеках и в других языках.
Ближайшей аналогией датафрейма будет таблица данных: датафрейм состоит из колонок и строк, где в колонках указаны переменные, а в строках – значения, соответствующие каждой переменной.
Для начала давайте немного исследуем наши данные, а заодно изучим несколько полезных команд.
Получить первые десять строк датафрейма. В качестве параметра указывается число строк, которые необходимо вывести:
>>> df.head(10)
Узнать названия колонок, их количество, тип данных в них, количество наблюдений:
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Name 891 non-null object
4 Sex 891 non-null object
5 Age 714 non-null float64
6 SibSp 891 non-null int64
7 Parch 891 non-null int64
8 Ticket 891 non-null object
9 Fare 891 non-null float64
10 Cabin 204 non-null object
11 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
Узнать базовые описательные статистики (максимальное и минимальное значение, среднее значение, стандартное отклонение) для колонок, которые содержат числовые данные (float
или int
):
>>> df.describe()
Получить информацию о количестве строк и колонок:
>>> df.shape
(891, 12)
Обратите внимание, что круглые скобки после этой команды не ставятся. В одном из следующих параграфов расскажем, почему так, — сейчас это не главное.
После того как мы составили первое впечатление о датафрейме, мы можем начать исследовать его. Разберём три задачи, которые могут перед нами стоять на этом этапе работы с данными:
- фильтровать датафрейм, то есть выбрать определенный диапазон значений по одной или нескольким переменным. Например, мы можем захотеть посмотреть на данные только по людям старше 35 лет;
- получить базовые описательные статистики для интересующих нас переменных, а не датафрейма в частности. Например, мы хотим узнать средний возраст мужчин или медианную стоимость билетов в первый класс.
Фильтрация датафрейма
Начнем с фильтрации датафрейма. Попробуем увидеть единственную колонку, содержащую информацию о возрасте.
>>> df['Age']
0 22.0
1 38.0
2 26.0
3 35.0
4 35.0
...
886 27.0
887 19.0
888 NaN
889 26.0
890 32.0
Name: Age, Length: 891, dtype: float64
Можно использовать другой способ: df.Age
. Здесь мы обращаемся к колонке как к атрибуту. Результат будет таким же, но он работает только в том случае, если в названии колонки нет пробелов. В дальнейшем мы будем использовать первый способ записи.
Допустим, мы можем выбрать несколько колонок, например класс и возраст. В таком случае наш код должен выглядеть следующим образом:
>>> df[['Pclass', 'Age']]
Обратите внимание на две открывающие и две закрывающие квадратные скобки. Внешняя пара квадратных скобок — это способ указать на колонку или колонки. Внутренняя пара квадратных скобок создаёт список, который содержит нужные колонки.
Если мы хотим получить доступ к определённым строкам нашего датафрейма, то можем использовать следующую инструкцию:
>>> df[0:5]
Обратите внимание, что нумерация в датафрейме начинается с 0, а не 1, так же как в списках, поэтому инструкция df[1:19] выдала бы нам результат, в котором отсутствует первый элемент.
Когда мы работаем с большим датафреймом, то для переменных, которые описываются номинальной шкалой, нам может быть важно понять, из каких значений она состоит. Для этого мы можем использовать метод unique()
. Так, например, можно узнать, какое значение может принимать наблюдение в колонке Pclass
— или, говоря проще, какие классы были на «Титанике».
>>> df['Pclass'].unique()
array([3, 1, 2])
Помимо этого, нам может быть важно узнать количество наблюдений, соответствующих каждому значению параметра класс
. То есть сколько людей ехало на «Титанике» в каждом классе. Для этого используем следующую инструкцию:
>>> df['Pclass'].value_counts()
3 491
1 216
2 184
Name: Pclass, dtype: int64
Теперь мы знаем, что в первом классе ехало 216 человек. Метод value_counts
может быть уточнён с помощью параметра так, чтобы мы не просто узнали количество людей в каждом классе, но и увидели пропорции. Для этого добавим к нашей записи дополнительный аргумент:
>>> df['Pclass'].value_counts(normalize=True)
3 0.551066
1 0.242424
2 0.206510
Name: Pclass, dtype: float64
Теперь мы знаем не только количество, но и пропорцию пассажиров в разных классах. Так, чуть больше 55% людей на корабле было из третьего класса.
Мы знаем, что колонка с информацией о классе содержит всего три значения: 1, 2, 3. Они соответствуют первому, второму и третьему классу билетов. Если мы захотим узнать среднюю стоимость билета в первом классе, то сначала нам необходимо отфильтровать наблюдения, относящиеся к первому классу. О том, как узнать среднее, мы поговорим чуть позже.
>>> df[df['Pclass'] == 1]
Можем сохранить в отдельный датафрейм этот результат:
>>> df_class_1 = df[df['Pclass'] == 1]
Такой способ работает для числовых переменных. Оператор ==
может быть заменен на <
, >
и другие операторы равенства и сравнения, если мы хотим получить значения, которые больше или меньше определённого значения. Мы можем использовать операторы равенства и для текстовых значений:
>>> df[df['Sex'] == 'male']
Наконец, последнее, что нам осталось научиться делать, — использовать сразу несколько условий для выбора части датафрейма. Предположим, что мы хотим изучить женщин из третьего класса. То есть нам необходимо задать два условия: класс должен быть третьим, а пол — женским. Мы можем объединить несколько условий:
>>> df[(df['Pclass'] == 3) & (df['Sex']=='female')]
Круглые скобки вокруг каждого из отдельных условий обязательны. Еще в pandas используются другие символы для некоторых логических операторов.
Таблица различий между стандартной библиотекой и pandas:
Название |
Стандартная библиотека |
Pandas |
Логическое НЕ |
not |
|
Логическое И |
and |
|
Логическое ИЛИ |
or |
| |
Итак, к текущему моменту мы научились:
- фильтровать нужные нам колонки и строки;
- узнавать значения переменных в той или иной колонке;
- оценивать количество уникальных значений в колонке — как пропорционально, так и количественно.
Описательные статистики
Теперь посмотрим, что мы можем сказать о данных, используя самые простые приёмы описательной (дескриптивной) статистики: среднее, медиану и стандартное отклонение. Большая часть статистик, о которых мы говорили, реализована в пакете pandas. У нас нет необходимости вычислять их вручную, используя базовый функционал Python.
Общий принцип здесь такой:
- указываем датафрейм;
- выбираем интересующую нас колонку (в примере ниже это стоимость билета);
- отмечаем значение, которое хотим получить.
>>> df['Fare'].mean()
32.204207968574636
>>> df['Fare'].median()
14.4542
Помимо среднего и медианы есть и другие методы. Например, мы можем узнать максимальное и минимальное значение:
>>> df['Age'].max()
80.0
>>> df['Age'].min()
0.42
Или узнать сумму всех значений в какой-то колонке, например сумму стоимости всех билетов:
>>> df['Fare'].sum()
28693.9493
Чтобы вычислить стандартное отклонение, применим такую функцию:
>>> df['Age'].std()
14.526497332334042
Отличная работа! Вот вы и научились использовать на практике все статистики из прошлого параграфа.
Мы подготовили несколько задач для самостоятельной работы — переходите к ним, чтобы закрепить знания. Но сперва советуем взглянуть на небольшой гайд о том, как пользоваться системой проверки заданий.
В разделе №3 мы снова поговорим о данных — научимся различать выборку и генеральную совокупность и узнаем, а заодно познакомимся с самыми важными статистическими тестами.