В этой части мы попрактикуемся в расчётах среднего, медианы и стандартного отклонения с помощью 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)

head

Узнать названия колонок, их количество, тип данных в них, количество наблюдений:

>>> 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()

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']]

two

Обратите внимание на две открывающие и две закрывающие квадратные скобки. Внешняя пара квадратных скобок — это способ указать на колонку или колонки. Внутренняя пара квадратных скобок создаёт список, который содержит нужные колонки.

Если мы хотим получить доступ к определённым строкам нашего датафрейма, то можем использовать следующую инструкцию:

>>> df[0:5]

five

Обратите внимание, что нумерация в датафрейме начинается с 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]

single

Можем сохранить в отдельный датафрейм этот результат:

>>> df_class_1 = df[df['Pclass'] == 1]

Такой способ работает для числовых переменных. Оператор == может быть заменен на <, > и другие операторы равенства и сравнения, если мы хотим получить значения, которые больше или меньше определённого значения. Мы можем использовать операторы равенства и для текстовых значений:

>>> df[df['Sex'] == 'male']

single

Наконец, последнее, что нам осталось научиться делать, — использовать сразу несколько условий для выбора части датафрейма. Предположим, что мы хотим изучить женщин из третьего класса. То есть нам необходимо задать два условия: класс должен быть третьим, а пол — женским. Мы можем объединить несколько условий:

>>> df[(df['Pclass'] == 3) & (df['Sex']=='female')]

two

Круглые скобки вокруг каждого из отдельных условий обязательны. Еще в 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 мы снова поговорим о данных — научимся различать выборку и генеральную совокупность и узнаем, а заодно познакомимся с самыми важными статистическими тестами.

Отмечайте параграфы как прочитанные чтобы видеть свой прогресс обучения

Вступайте в сообщество хендбука

Здесь можно найти единомышленников, экспертов и просто интересных собеседников. А ещё — получить помощь или поделиться знаниями.
Вступить
Сообщить об ошибке
Предыдущий параграф2.2. Прямые распределения
Следующий параграф3.1. Выборка и генеральная совокупность. Табличные данные