Использование Pandas для изучения вашего набора данных

17 мая, 2020

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

Оглавление

  • Настройка вашей среды
  • Использование библиотеки Pandas
  • Знакомство с вашими данными
    • Отображение типов данных
    • Отображение базовой статистики
    • Изучение вашего набора данных
  • Знакомство со структурами данных Pandas
    • Понимание объектов серии
    • Понимание объектов DataFrame
  • Доступ к элементам серии
    • Использование оператора индексации
    • Использование .loc и .iloc
  • Доступ к элементам DataFrame
    • Использование оператора индексации
    • Использование .loc и .iloc
  • Запрос вашего набора данных
  • Группировка и агрегация ваших данных
  • Манипуляции с колоннами
  • Указание типов данных
  • Очистка данных
    • Недостающие значения
    • Неверные значения
    • Несоответствующие значения
  • Объединение нескольких наборов данных
  • Визуализация вашей Pandas DataFrame
  • Вывод

У вас есть большой набор данных, который полон интересных идей, но вы не знаете с чего начать? Ваш начальник попросил вас сгенерировать некоторую статистику из него, но ее не так просто извлечь? Это именно те случаи, когда Pandas и Python могут вам помочь! С помощью этих инструментов вы сможете разрезать большой набор данных на управляемые части и получить представление об этой информации.

В этом уроке вы узнаете, как:

  • Рассчитать метрики о ваших данных
  • Выполнять основные запросы и агрегации
  • Обнаруживать и обрабатывать неверные данные, несоответствия и пропущенные значения
  • Визуализировать свои данные с графиками

Вы также узнаете о различиях между основными структурами данных, которые используют Pandas и Python. 

Настройка вашей среды

Есть несколько вещей, которые вам понадобятся, чтобы начать работу с этим руководством. Во-первых, знакомство со встроенными структурами данных Python, особенно списками и словарями . Для получения дополнительной информации, проверьте списки и кортежи в Python и словари в Python .

Еще, что вам нужно, это библиотека Pandas, которую вы можете установить с помощью pip :

$ python -m pip install pandas

Вы также можете использовать менеджер пакетов Conda :

$ conda install pandas

Если вы используете дистрибутив Anaconda , тогда вам не нужно никаких дополнительных действий! Anaconda уже поставляется с установленной библиотекой Pandas.

Примеры в этом руководстве были протестированы с Python 3.7 и Pandas 0.25.0, но они также должны работать в более старых версиях.

Давайте начнем!

Использование библиотеки Pandas

Теперь, когда вы установили Pandas, пришло время взглянуть на набор данных. В этом руководстве вы проанализируете результаты NBA, предоставленные FiveThirtyEight, в файле CSV размером 17 МБ . Создайте скрипт download_nba_all_elo.py для загрузки данных:

import requests

download_url = "https://raw.githubusercontent.com/fivethirtyeight/data/master/nba-elo/nbaallelo.csv"
target_csv_path = "nba_all_elo.csv"

response = requests.get(download_url)
response.raise_for_status()    # Check that the request was successful
with open(target_csv_path, "wb") as f:
    f.write(response.content)
print("Download ready.")

Когда вы выполните скрипт, он сохранит файл nba_all_elo.csv в вашем текущем рабочем каталоге.

Примечание. Вы также можете использовать веб-браузер для загрузки файла CSV.

Однако наличие варианта загрузки имеет несколько преимуществ:

  • Вы можете сообщить, где вы получили свои данные.
  • Вы можете повторить загрузку в любое время! Это особенно удобно, если данные часто обновляются.
  • Вам не нужно делиться файлом CSV размером 17 МБ с вашими коллегами. Обычно достаточно поделиться скриптом загрузки.

Теперь вы можете использовать библиотеку Pandas для просмотра ваших данных:

>>> import pandas as pd
>>> nba = pd.read_csv("nba_all_elo.csv")
>>> type(nba)
<class 'pandas.core.frame.DataFrame'>

Здесь вы следуете соглашению об импорте Pandas в Python с pd псевдонимом. Затем вы используете .read_csv() для чтения в вашем наборе данных и сохранить его как DataFrame объект в переменной nba.

Примечание. Ваши данные не в формате CSV? Не беспокойтесь! Библиотека Pandas предоставляет несколько аналогичных функций , таких как read_json()read_html() и read_sql_table(). Чтобы узнать, как работать с этими форматами файлов, ознакомьтесь с разделом Чтение и запись файлов с помощью Pandas или обратитесь к документации .

Вы можете увидеть, сколько данных nbaсодержит:

>>> len(nba)
126314
>>> nba.shape
(126314, 23)

Вы используете встроенную функцию Python len() для определения количества строк. Вы также используете .shape атрибут, DataFrame чтобы увидеть его размерность . Результатом является кортеж, содержащий количество строк и столбцов.

Теперь вы знаете, что в вашем наборе данных 126 314 строк и 23 столбца. Но как вы можете быть уверены, что набор данных действительно содержит статистику баскетбола? Вы можете взглянуть на первые пять строк .head():

>>> nba.head()

Если вы используете Jupyter, вы увидите такой результат:

Панды DataFrame .head ()

Если ваш экран не очень большой, ваш вывод, вероятно, не будет отображать все 23 столбца. Где-то посередине вы увидите столбец с эллипсами ( ...), указывающий на отсутствующие данные.  Вы можете настроить Pandas для отображения всех 23 столбцов следующим образом:

>>> pd.set_option("display.max.columns", None)

Несмотря на то, что все столбцы видны, вам, вероятно, не понадобится шесть десятичных знаков! Измените на два:

>>> pd.set_option("display.precision", 2)

Чтобы убедиться, что вы успешно изменили параметры, вы можете выполнить .head() снова или вы можете отобразить последние пять строк .tail():

>>> nba.tail()

Теперь вы должны увидеть все столбцы, и ваши данные должны показать два десятичных знака:

Панды DataFrame .tail ()

Вы можете открыть некоторые дополнительные возможности .head() и .tail() с помощью небольшого упражнения. Можете ли вы напечатать последние три строки вашего DataFrame? Ниже решение:

Вот как распечатать последние три строки nba:

>>> nba.tail(3)

Ваш вывод должен выглядеть примерно так:

Pandas DataFrame .tail () с параметром

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

Подобно стандартной библиотеке Python, функции в Pandas также имеют несколько необязательных параметров. Всякий раз, когда вы сталкиваетесь с примером, который выглядит актуально, но немного отличается от вашего варианта использования, ознакомьтесь с официальной документацией . Скорее всего, вы найдете решение, настроив некоторые дополнительные параметры!

Знакомство с вашими данными

Вы импортировали файл CSV с библиотекой Pandas Python и впервые просмотрели содержимое вашего набора данных. До сих пор вы видели только размер вашего набора данных и его первые и последние несколько строк. Далее вы узнаете, как более систематически проверять ваши данные .

Отображение типов данных

Первым шагом в ознакомлении с вашими данными является обнаружение различных типов данных, которые они содержат. Хотя вы можете поместить что-либо в список, столбцы DataFrame содержат значения определенного типа данных. Когда вы сравните структуры данных Pandas и Python, вы увидите, что такое поведение делает Pandas намного быстрее!

Вы можете отобразить все столбцы и их типы данных с помощью .info():

>>> nba.info()

Это даст следующий результат:

Панды DataFrame .info ()

Вы увидите список всех столбцов в вашем наборе данных и тип данных, содержащихся в каждом столбце. Здесь вы можете увидеть типы данных int64float64 и object. Pandas использует библиотеку NumPy для работы с этими типами. Позже вы познакомитесь с более сложным categorical типом данных, которого реализует библиотека Pandas.

Тип данных object является «универсальным для столбцов, которые Pandas не распознает как какой-либо другой конкретный тип». На практике это часто означает, что все значения в столбце являются строками.

Хотя вы можете хранить произвольные объекты Python в object типе данных, вы должны знать о недостатках этого. Странные значения в object столбце могут нанести ущерб производительности Pandas и ее совместимости с другими библиотеками. Для получения дополнительной информации ознакомьтесь с официальным руководством по началу работы .

Отображение базовой статистики

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

>>> nba.describe()

Эта функция показывает некоторую базовую описательную статистику для всех числовых столбцов:

Pandas DataFrame .describe ()

.describe() по умолчанию анализируются только числовые столбцы, но вы можете указать другие типы данных, если используете include параметр:>>>

>>> import numpy as np
>>> nba.describe(include=np.object)

.describe() не будет пытаться вычислить среднее или стандартное отклонение для object столбцов, поскольку они в основном содержат текстовые строки. Тем не менее, он все равно будет отображать некоторую статистику:

Pandas DataFrame .describe () с помощью include = np.object

Взгляните на team_id и fran_id столбцы. Ваш набор данных содержит 104 различных идентификатора команды, но только 53 различных идентификатора франшизы. Кроме того, самый частый идентификатор команды это BOS, но самый частый идентификатор франшизы это Lakers. Как это возможно? Вам нужно будет изучить свой набор данных немного больше, чтобы ответить на этот вопрос.

Изучение вашего набора данных

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

>>> nba["team_id"].value_counts()
BOS    5997
NYK    5769
LAL    5078
...
SDS      11
>>> nba["fran_id"].value_counts()
Name: team_id, Length: 104, dtype: int64
Lakers          6024
Celtics         5997
Knicks          5769
...
Huskies           60
Name: fran_id, dtype: int64

Кажется, что названная команда "Lakers" сыграла 6024 игры, но только 5078 из них были сыграны Лос-Анджелес Лейкерс. Узнайте, кто другая "Lakers" команда:>>>

>>> nba.loc[nba["fran_id"] == "Lakers", "team_id"].value_counts()
LAL    5078
MNL     946
Name: team_id, dtype: int64

Действительно, Миннеаполис Лейкерс ( "MNL") сыграли 946 игр. Вы даже можете узнать, когда они играли в эти игры:>>>

>>> nba.loc[nba["team_id"] == "MNL", "date_game"].min()
'1/1/1949'
>>> nba.loc[nba["team_id"] == "MNL", "date_game"].max()
'4/9/1959'
>>> nba.loc[nba["team_id"] == "MNL", "date_game"].agg(("min", "max"))
min    1/1/1949
max    4/9/1959
Name: date_game, dtype: object

Вы узнали, почему команда Boston Celtics "BOS" сыграла больше всего игр в наборе данных. Давайте немного разберем их историю. Узнайте, сколько очков набрали Boston Celtics за все матчи, содержащиеся в этом наборе данных. Решение:

Аналогично агрегатам функций .min() и .max() , вы также можете использовать .sum():>>>

>>> nba.loc[nba["team_id"] == "BOS", "pts"].sum()
626484

Бостон Селтикс набрал в общей сложности 626,484 балла.

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

Знакомство со структурами данных Pandas

В то время как DataFrame предоставляет функции, которые могут казаться довольно интуитивными, базовые концепции немного сложнее понять. По этой причине вы отложите в сторону огромный NBA DataFrame и создадите несколько небольших объектов Pandas с нуля.

Понимание объектов серии

Основная структура данных Python – это список , который также является хорошей отправной точкой для знакомства с pandas.Series объектами. Создайте новый Series объект на основе списка:

>>> revenues = pd.Series([5555, 7000, 1980])
>>> revenues
0    5555
1    7000
2    1980
dtype: int64

Вы использовали список [5555, 7000, 1980] для создания Series объекта с именем revenuesSeries объект состоит из двух компонентов:

  1. Последовательность значений
  2. Последовательность идентификаторов, которые являются индексом

Вы можете получить доступ к этим компонентам с .values и .index, соответственно:

>>> revenues.values
array([5555, 7000, 1980])
>>> revenues.index
RangeIndex(start=0, stop=3, step=1)

revenues.values возвращает значения в Series, тогда как revenues.index возвращает позиционный индекс.

Примечание. Если вы знакомы с NumPy , вам может быть интересно отметить, что значения Series объекта на самом деле являются n-мерными массивами:

>>> type(revenues.values)
<class 'numpy.ndarray'>

Если вы не знакомы с NumPy, вам не о чем беспокоиться! Вы можете исследовать все входы и выходы своего набора данных с помощью библиотеки Pandas. 

Хотя Pandas опирается на NumPy, существенная разница заключается в их индексации . Как и массив NumPy, у Pandas Series также есть целочисленный индекс, который неявно определен. Этот неявный индекс указывает положение элемента в Series.

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

>>> city_revenues = pd.Series(
...     [4200, 8000, 6500],
...     index=["Amsterdam", "Toronto", "Tokyo"]
... )
>>> city_revenues
Amsterdam    4200
Toronto      8000
Tokyo        6500
dtype: int64

Здесь индекс представляет собой список названий городов, представленных строками. Возможно, вы заметили, что в словарях Python также используются строковые индексы, и это полезная аналогия, о которой следует помнить! Вы можете использовать блоки кода выше, чтобы различать два типа Series:

  1. revenues: Series ведет себя как список Python , потому что он имеет только позиционное индекс.
  2. city_revenues: Seriesдействует как словарь Python, потому что он имеет позиционный и меточный индекс.

Вот как создать индекс Series с меткой из словаря Python:>>>

>>> city_employee_count = pd.Series({"Amsterdam": 5, "Tokyo": 8})
>>> city_employee_count
Amsterdam    5
Tokyo        8
dtype: int64

Ключи словаря становятся индексом, а значения словаря являются Series значениями.

Так же, как словари, Series , поддерживает ключевые слова .keys()и in:

>>> city_employee_count.keys()
Index(['Amsterdam', 'Tokyo'], dtype='object')
>>> "Tokyo" in city_employee_count
True
>>> "New York" in city_employee_count
False

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

Понимание объектов DataFrame

Хотя Series является довольно мощной структурой данных, она имеет свои ограничения. Например, вы можете хранить только один атрибут на ключ. Как вы видели с nba набором данных, который содержит 23 столбца, библиотека Pandas может предложить больше со своим DataFrame. Эта структура данных представляет собой последовательность Series объектов, имеющих общий индекс.

Если вы следовали Series примерам, то у вас уже должны быть два Series объекта с городами в качестве ключей:

  1. city_revenues
  2. city_employee_count

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

>>> city_data = pd.DataFrame({
...     "revenue": city_revenues,
...     "employee_count": city_employee_count
... })
>>> city_data
           revenue  employee_count
Amsterdam     4200             5.0
Tokyo         6500             8.0
Toronto       8000             NaN

Обратите внимание, как Pandas заменила недостающее employee_count значение для Торонто NaN.

Новый DataFrame индекс представляет собой объединение двух Series индексов:

>>> city_data.index
Index(['Amsterdam', 'Tokyo', 'Toronto'], dtype='object')

Как и SeriesDataFrame также хранит свои значения в массиве NumPy:

>>> city_data.values
array([[4.2e+03, 5.0e+00],
       [6.5e+03, 8.0e+00],
       [8.0e+03,     nan]])

Вы также можете сослаться как на 2 измерения оси DataFrame:

>>> city_data.axes
[Index(['Amsterdam', 'Tokyo', 'Toronto'], dtype='object'),
 Index(['revenue', 'employee_count'], dtype='object')]
>>> city_data.axes[0]
 Index(['Amsterdam', 'Tokyo', 'Toronto'], dtype='object')
>>> city_data.axes[1]
 Index(['revenue', 'employee_count'], dtype='object')

Ось, отмеченная 0, является индексом строки , а ось, отмеченная 1, является индексом столбца . Эту терминологию важно знать, потому что вы столкнетесь с несколькими DataFrame методами, которые принимают axis параметр.

DataFrame также представляет собой словарную структуру данных, поэтому она также поддерживает .keys() и in. Однако для DataFrame они относятся не к индексу, а к столбцам:

>>> city_data.keys()
Index(['revenue', 'employee_count'], dtype='object')
>>> "Amsterdam" in city_data
False
>>> "revenue" in city_data
True

Вы можете увидеть эти концепции в действии с большим набором данных NBA. Содержит ли он столбец с именем "points", или он был назван "pts"? Чтобы ответить на этот вопрос, отобразите индекс и оси nba набора данных, затем посмотрите ниже для решения:

Т.к вы не указали индекс столбца , когда вы читаете в файле CSV, Pandas было назначено RangeIndex на DataFrame:

>>> nba.index
RangeIndex(start=0, stop=126314, step=1)

nba как и все DataFrame объекты, имеет две оси:

>>> nba.axes
[RangeIndex(start=0, stop=126314, step=1),
 Index(['gameorder', 'game_id', 'lg_id', '_iscopy', 'year_id', 'date_game',
        'seasongame', 'is_playoffs', 'team_id', 'fran_id', 'pts', 'elo_i',
        'elo_n', 'win_equiv', 'opp_id', 'opp_fran', 'opp_pts', 'opp_elo_i',
        'opp_elo_n', 'game_location', 'game_result', 'forecast', 'notes'],
       dtype='object')]

Вы можете проверить наличие столбца с помощью .keys():

>>> "points" in nba.keys()
False
>>> "pts" in nba.keys()
True

Колонка называется "pts", а не "points".

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

Доступ к элементам серии

В предыдущем разделе вы создали Pandas Series на основе списка Python и сравнили две структуры данных. Вы видели, как Series объект похож на списки и словари несколькими способами. Еще одно сходство в том, что вы также можете использовать оператор индексации ( []Series.

Вы также узнаете, как использовать два специфичных для Pandas метода доступа:

  1. .loc
  2. .iloc

Вы увидите, что эти методы доступа к данным могут быть гораздо более удобочитаемыми, чем оператор индексации.

Использование оператора индексации

Напомним, что a Series имеет два индекса:

  1. Позиционный или неявный индекс , который всегдаRangeIndex
  2. Метка или явный индекс , который может содержать любые хешируемые объекты

Затем снова посетите city_revenues объект:

>>> city_revenues
Amsterdam    4200
Toronto      8000
Tokyo        6500
dtype: int64

Вы можете легко получить доступ к значениям в Series как с меткой, так и с позиционными индексами:>>>

>>> city_revenues["Toronto"]
8000
>>> city_revenues[1]
8000

Вы также можете использовать отрицательные индексы и части, как если бы вы использовали список:

>>> city_revenues[-1]
6500
>>> city_revenues[1:]
Toronto    8000
Tokyo      6500
dtype: int64
>>> city_revenues["Toronto":]
Toronto    8000
Tokyo      6500
dtype: int64

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

Использование .loc и .iloc

Оператор индексирования ([]) удобен, но есть предостережение. Что делать, если метки тоже цифры? Скажем, вам нужно работать с таким Series объектом:

>>> colors = pd.Series(
...     ["red", "purple", "blue", "green", "yellow"],
...     index=[1, 2, 3, 5, 8]
... )
>>> colors
1       red
2    purple
3      blue
5     green
8    yellow
dtype: object

colors[1] вернется? Для позиционного индекса colors[1] есть "purple". Однако, если вы идете по индексу метки, то colors[1] имеется в виду "red".

Хорошая новость в том, что вам не нужно это понимать! Вместо этого, чтобы избежать путаницы, библиотека Pandas предоставляет два метода доступа к данным:

  1. .loc относится к метке индекса .
  2. .iloc относится к позиционному индексу .

Эти методы доступа к данным гораздо более читабельны:

>>> colors.loc[1]
'red'
>>> colors.iloc[1]
'purple'

colors.loc[1] возвращает "red" элемент с меткой 1. А colors.iloc[1] возвращает "purple"элемент с индексом 1.

На следующем рисунке показано, к каким элементам .loc и .iloc относятся:

Серия панд iloc vs loc

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

Проще иметь в виду различие между .loc и .iloc чем выяснить, что вернет оператор индексации. Даже если вы знакомы со всеми особенностями оператора индексации, может быть опасно предполагать, что все, кто читает ваш код, также усвоили эти правила!

Примечание. В дополнение к тому, что с путаницей Series с числовыми метками оператор индексации, Python имеет некоторые недостатки производительности . Совершенно нормально использовать его в интерактивных сессиях для специального анализа, но для производственного, кода предпочтительнее использовать методы доступа к данным .loc и .iloc

.loc и .ilocтакже поддерживает функции, которые вы ожидаете от операторов индексирования, такие как нарезка. Однако эти методы доступа к данным имеют важное различие. Пока .iloc исключает закрывающий элемент, .loc включает его. Посмотрите на этот блок кода:

>>> # Return the elements with the implicit index: 1, 2
>>> colors.iloc[1:3]
2    purple
3      blue
dtype: object

Если сравнить этот код на картинке выше, то вы можете увидеть , что colors.iloc[1:3] возвращает элементы с позиционными индексами от 1 и 2. Закрывающая позиция "green" с позиционным индексом 3 исключается.

С другой стороны, .loc включает закрывающий элемент:

>>> # Return the elements with the explicit index between 3 and 8
>>> colors.loc[3:8]
3      blue
5     green
8    yellow
dtype: object

Этот блок кода говорит, чтобы вернуть все элементы с индексом метки между 3 и 8. Здесь закрывающий элемент "yellow" имеет индекс метки 8 и включен в выходные данные.

Вы также можете передать отрицательный позиционный индекс .iloc:

>>> colors.iloc[-2]
'green'

Вы начинаете с конца Series и возвращаете второй элемент.

Примечание. Раньше существовал .ix индексатор, который пытался угадать, следует ли применять индексирование по позициям или по меткам в зависимости от типа данных индекса. Поскольку это вызвало много путаницы, оно устарело с версии 0.20.0 Pandas.

Настоятельно рекомендуется не использовать.ix для индексации. Вместо этого всегда используйте .loc для индексации меток и .iloc позиционной индексации. Для получения более подробной информации обратитесь к Руководству пользователя Pandas .

Вы можете использовать блоки кода выше, чтобы различать два Series поведения:

  1. Вы можете использовать .iloc по Series аналогии с использованием [] в списке .
  2. Вы можете использовать .loc по Series аналогии с использованием [] в словаре .

Обязательно помните об этих различиях при доступе к элементам ваших Series объектов.

Доступ к элементам DataFrame

Поскольку объект DataFrame состоит из Series объектов, вы можете использовать те же инструменты для доступа к его элементам. Важное отличие является дополнительным измерением из DataFrame. Вы будете использовать оператор индексации для столбцов, методов доступа .loc и .iloc строк.

Использование оператора индексации

Если вы считаете DataFrame словарь со значениями Series, то имеет смысл получить доступ к его столбцам с помощью оператора индексации:

>>> city_data["revenue"]
Amsterdam    4200
Tokyo        6500
Toronto      8000
Name: revenue, dtype: int64
>>> type(city_data["revenue"])
pandas.core.series.Series

Здесь вы используете оператор индексирования для выбора столбца с меткой "revenue".

Если имя столбца является строкой, то вы также можете использовать доступ в стиле атрибутов с точечной нотацией:

>>> city_data.revenue
Amsterdam    4200
Tokyo        6500
Toronto      8000
Name: revenue, dtype: int64

city_data["revenue"]и city_data.revenue вернёт тот же вывод.

Есть одна ситуация, когда доступ к DataFrame элементам с точечной нотацией может не работать или может привести к неожиданностям. Это когда имя столбца совпадает с именем DataFrame атрибута или метода:

>>> toys = pd.DataFrame([
...     {"name": "ball", "shape": "sphere"},
...     {"name": "Rubik's cube", "shape": "cube"}
... ])
>>> toys["shape"]
0    sphere
1      cube
Name: shape, dtype: object
>>> toys.shape
(2, 2)

Операция индексирования toys["shape"] возвращает правильные данные, но операция в стиле атрибутаtoys.shape по- прежнему возвращает форму DataFrame. Вы должны использовать доступ к атрибуту только в интерактивных сеансах или для операций чтения. Вы не должны использовать его для производственного кода или для манипулирования данными (например, для определения новых столбцов).

Использование .loc и .iloc

Аналогично Series,  DataFrame также предоставляет .loc и .iloc методы доступа к данным . Помните, .loc использует метку а .iloc позиционный индекс:>>>

>>> city_data.loc["Amsterdam"]
revenue           4200.0
employee_count       5.0
Name: Amsterdam, dtype: float64
>>> city_data.loc["Tokyo": "Toronto"]
        revenue employee_count
Tokyo   6500    8.0
Toronto 8000    NaN
>>> city_data.iloc[1]
revenue           6500.0
employee_count       8.0
Name: Tokyo, dtype: float64

Каждая строка кода выбирает другую строку из city_data:

  1. city_data.loc["Amsterdam"] выбирает строку с индексом метки "Amsterdam".
  2. city_data.loc["Tokyo": "Toronto"] выбирает строки с индексами меток от "Tokyo" до "Toronto". Помните, .loc это включено.
  3. city_data.iloc[1] выбирает строку с позиционным индексом 1, который является "Tokyo".

Хорошо, вы использовали .loc и .iloc на небольших структурах данных. Теперь пришло время потренироваться с чем-то большим! Используйте метод доступа к данным, чтобы отобразить предпоследнюю строку nba набора данных. Затем посмотрите решение:

Строки второго до последнего является строка с позиционным индексом из -2. Вы можете отобразить его с помощью .iloc:

>>> nba.iloc[-2]
gameorder               63157
game_id          201506170CLE
lg_id                     NBA
_iscopy                     0
year_id                  2015
date_game           6/16/2015
seasongame                102
is_playoffs                 1
team_id                   CLE
fran_id             Cavaliers
pts                        97
elo_i                 1700.74
elo_n                 1692.09
win_equiv             59.2902
opp_id                    GSW
opp_fran             Warriors
opp_pts                   105
opp_elo_i             1813.63
opp_elo_n             1822.29
game_location               H
game_result                 L
forecast              0.48145
notes                     NaN
Name: 126312, dtype: object

Вы увидите вывод как Series объект.

Для DataFrame, методы доступа к данным, .loc и .ilocтакже принимают второй параметр. В то время как первый параметр выбирает строки на основе индексов, второй параметр выбирает столбцы. Вы можете использовать эти параметры вместе, чтобы выбрать подмножество строк и столбцов из вашего DataFrame:>>>

>>> city_data.loc["Amsterdam": "Tokyo", "revenue"]
Amsterdam    4200
Tokyo        6500
Name: revenue, dtype: int64

Обратите внимание, что вы разделяете параметры запятой ( ,). Первый параметр "Amsterdam" : "Tokyo," говорит, чтобы выбрать все строки между этими двумя метками. Второй параметр идет после запятой и говорит, чтобы выбрать "revenue" столбец.

Пришло время увидеть ту же конструкцию в действии с большим nba набором данных. Выберите все игры между ярлыками 5555 и 5559. Вас интересуют только названия команд и оценки, так что выбирайте и эти элементы. Затем посмотрите ниже, чтобы увидеть решение:

Сначала определите, какие строки вы хотите видеть, затем перечислите соответствующие столбцы:

>>> nba.loc[5555:5559, ["fran_id", "opp_fran", "pts", "opp_pts"]]

Вы используете .loc для индекса метки и запятой (,) для разделения ваших двух параметров.

Вы должны увидеть небольшую часть вашего довольно большого набора данных:

Панды DataFrame .loc

Вывод намного легче читать!

С помощью таких методов доступа к данным, как .loc и .iloc, вы можете выбрать только то, что нужно в вашем DataFrame, чтобы ответить на вопросы о вашем наборе данных.

Запрос вашего набора данных

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

>>> current_decade = nba[nba["year_id"] > 2010]
>>> current_decade.shape
(12658, 23)

У вас все еще есть все 23 столбца, но ваш новый DataFrame состоит только из строк, где значение в "year_id" столбце больше, чем 2010.

Вы также можете выбрать строки, в которых определенное поле не равно нулю:

>>> games_with_notes = nba[nba["notes"].notnull()]
>>> games_with_notes.shape
(5424, 23)

Это может быть полезно, если вы хотите избежать пропущенных значений в столбце. Вы также можете использовать .notna() для достижения той же цели.

Вы даже можете получить доступ к значениям типа object данных str и выполнять строковые методы для них:>>>

>>> ers = nba[nba["fran_id"].str.endswith("ers")]
>>> ers.shape
(27797, 23)

Вы используете .str.endswith() для фильтрации вашего набора данных и нахождения всех игр, где заканчивается имя домашней команды на "ers".

Вы можете объединить несколько критериев и запросить свой набор данных. Чтобы сделать это, обязательно поставьте каждый в круглые скобки и используйте логические операторы | и & разделите их.

Примечание: Операторы andor&& и || не будет работать здесь. Если вам интересно, почему, то ознакомьтесь с разделом о том, как библиотека Python Pandas использует логические операторы в Python Pandas: хитрости и особенности, которые вы, возможно, не знаете .

Выполните поиск игр в Балтиморе, где обе команды набрали более 100 очков. Чтобы увидеть каждую игру только один раз, вам нужно исключить дубликаты:>>>

>>> nba[
...     (nba["_iscopy"] == 0) &
...     (nba["pts"] > 100) &
...     (nba["opp_pts"] > 100) &
...     (nba["team_id"] == "BLB")
... ]

Здесь вы используете nba["_iscopy"] == 0 для включения только записи, которые не являются копиями.

Ваш вывод должен содержать пять событийных игр:

Pandas DataFrame запрос с несколькими критериями

Попробуйте создать другой запрос с несколькими критериями. Весной 1992 года обеим командам из Лос-Анджелеса пришлось сыграть домашнюю игру на другом корте. Запросите ваш набор данных, чтобы найти эти две игры. Обе команды имеют идентификатор, начиная с "LA". Посмотрите ниже, чтобы увидеть решение:

Вы можете использовать, .str чтобы найти идентификаторы команд, которые начинаются с "LA", и вы можете предположить, что такая необычная игра будет иметь некоторые заметки:

>>> nba[
...     (nba["_iscopy"] == 0) &
...     (nba["team_id"].str.startswith("LA")) &
...     (nba["year_id"]==1992) &
...     (nba["notes"].notnull())
... ]

Ваш вывод должен показать две игры в день 5/3/1992:

Запрос Pandas DataFrame с несколькими критериями: решение упражнения

Хорошая находка!

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

Группировка и агрегация ваших данных

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

А Series имеет более двадцати различных методов для расчета описательной статистики. Вот некоторые примеры:

>>> city_revenues.sum()
18700
>>> city_revenues.max()
8000

Первый метод возвращает сумму city_revenues, а второй возвращает максимальное значение. Есть и другие методы, которые вы можете использовать, например, .min() и .mean().

Помните, столбец в DataFrame действительно является Series объектом. По этой причине вы можете использовать эти же функции в столбцах nba:

>>> points = nba["pts"]
>>> type(points)
<class 'pandas.core.series.Series'>
>>> points.sum()
12976235

DataFrame может иметь несколько столбцов, что открывает новые возможности для агрегации, такие как группировка :

>>> nba.groupby("fran_id", sort=False)["pts"].sum()
fran_id
Huskies           3995
Knicks          582497
Stags            20398
Falcons           3797
Capitols         22387
...

По умолчанию Pandas сортирует групповые ключи во время вызова .groupby(). Если не хотите сортировать, то sort=False. Этот параметр может привести к повышению производительности.

Вы также можете группировать по нескольким столбцам:

>>> nba[
...     (nba["fran_id"] == "Spurs") &
...     (nba["year_id"] > 2010)
... ].groupby(["year_id", "game_result"])["game_id"].count()
year_id  game_result
2011     L              25
         W              63
2012     L              20
         W              60
2013     L              30
         W              73
2014     L              27
         W              78
2015     L              31
         W              58
Name: game_id, dtype: int64

Вы можете практиковать эти основы с помощью упражнения. Взгляните на воинов Золотого штата 2014-15 сезона ( year_id: 2015). Сколько побед и поражений они забили в регулярном сезоне и в плей-офф? Ниже ответ:

Сначала вы можете сгруппировать по "is_playoffs" полю, а затем по результату:

>>> nba[
...     (nba["fran_id"] == "Warriors") &
...     (nba["year_id"] == 2015)
... ].groupby(["is_playoffs", "game_result"])["game_id"].count()
is_playoffs  game_result
0            L              15
             W              67
1            L               5
             W              16

is_playoffs=0 показывает результаты для регулярного сезона, и is_playoffs=1 показывает результаты для плей-офф.

В приведенных выше примерах вы только поверхностно рассмотрели функции агрегации, которые доступны вам в библиотеке Python Pandas. Чтобы увидеть больше примеров их использования, ознакомьтесь с Pandas GroupBy: ваше руководство по группированию данных в Python .

Манипуляции с колоннами

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

Создайте копию своего оригинала DataFrame для работы:

>>> df = nba.copy()
>>> df.shape
(126314, 23)

Вы можете определить новые столбцы на основе существующих:

>>> df["difference"] = df.pts - df.opp_pts
>>> df.shape
(126314, 24)

Здесь вы использовали "pts" и "opp_pts" столбцы , чтобы создать новый под названием "difference". Этот новый столбец имеет те же функции, что и старые:

>>> df["difference"].max()
68

Здесь вы использовали функцию агрегирования, .max() чтобы найти наибольшее значение вашего нового столбца.

Вы также можете переименовать столбцы вашего набора данных. Кажется, что "game_result" и "game_location" слишком многословны, так что давай теперь переименовать их сейчас:>>>

>>> renamed_df = df.rename(
...     columns={"game_result": "result", "game_location": "location"}
... )
>>> renamed_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 126314 entries, 0 to 126313
Data columns (total 24 columns):
gameorder      126314 non-null int64
...
location       126314 non-null object
result         126314 non-null object
forecast       126314 non-null float64
notes          5424 non-null object
difference     126314 non-null int64
dtypes: float64(6), int64(8), object(10)
memory usage: 23.1+ MB

Обратите внимание, что есть новый объект renamed_df. Как и несколько других методов обработки данных, по умолчанию .rename() возвращает новый DataFrame. Если вы хотите , манипулировать оригинал DataFrame непосредственно, .rename() также предоставляет inplace параметр , который можно установить в True.

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

>>> df.shape
(126314, 24)
>>> elo_columns = ["elo_i", "elo_n", "opp_elo_i", "opp_elo_n"]
>>> df.drop(elo_columns, inplace=True, axis=1)
>>> df.shape
(126314, 20)

Помните, что вы добавили новый столбец "difference" в предыдущем примере, в результате чего общее количество столбцов было равно 24. Когда вы удаляете четыре столбца Elo, общее количество столбцов уменьшается до 20.

Указание типов данных

Когда вы создаете новый DataFrame, вызывая конструктор или читая CSV-файл, Pandas назначает тип данных каждому столбцу на основе его значений. Хотя он довольно неплохо работает, он не идеален. Если вы выбрали правильный тип данных для ваших столбцов заранее, то вы можете значительно улучшить производительность вашего кода.

Еще раз взглянем на столбцы nba набора данных:

>>> df.info()

Вы увидите тот же вывод, что и раньше:

Панды DataFrame .info ()

Десять из ваших столбцов имеют тип данных object. Большинство этих object столбцов содержат произвольный текст, но есть также некоторые кандидаты для преобразования типов данных . Например, посмотрите на date_game столбец:

>>> df["date_game"] = pd.to_datetime(df["date_game"])

Здесь вы используете, .to_datetime() чтобы указать все игровые даты как datetime объекты.

Другие столбцы содержат более структурированный текст. game_location колонка может иметь только три различных значения:

>>> df["game_location"].nunique()
3
>>> df["game_location"].value_counts()
A    63138
H    63138
N       38
Name: game_location, dtype: int64

Какой тип данных вы бы использовали в реляционной базе данных для такого столбца? Вы, вероятно, не используете varchar тип, а скорее enum. Pandas предоставляет categorical тип данных для той же цели:

>>> df["game_location"] = pd.Categorical(df["game_location"])
>>> df["game_location"].dtype
CategoricalDtype(categories=['A', 'H', 'N'], ordered=False)

categorical Данные имеют несколько преимуществ перед неструктурированным текстом. Когда вы указываете categorical тип данных, вы упрощаете проверку и сохраняете массу памяти, поскольку Pandas будет использовать уникальные значения только для внутреннего использования. Чем выше отношение общих значений к уникальным, тем больше экономия места.

Запускайте df.info() снова. Вы должны увидеть, что изменение game_location типа данных с object на categorical уменьшило использование памяти.

Примечание. Тип categorical данных также предоставляет доступ к дополнительным методам через средство доступа .cat . Чтобы узнать больше, ознакомьтесь с официальными документами .

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

Найдите минутку, чтобы практиковать это сейчас. Найдите другой столбец в nba наборе данных, который имеет общий тип данных, и преобразуйте его в более конкретный. Блок кода ниже, с потенциальным решением:

game_result может принимать только два разных значения:

>>> df["game_result"].nunique()
2
>>> df["game_result"].value_counts()
L    63157
W    63157

Для повышения производительности вы можете преобразовать его в categorical столбец:

>>> df["game_result"] = pd.Categorical(df["game_result"])

Вы можете использовать, df.info() чтобы проверить использование памяти.

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

Очистка данных

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

Недостающие ценности

Задумывались ли вы, почему .info() показывает, сколько ненулевых значений содержит столбец? Причина в том, что это жизненно важная информация. Нулевые значения часто указывают на проблему в процессе сбора данных. Они могут сделать несколько методов анализа, таких как различные виды машинного обучения , трудными или даже невозможными.

Когда вы осмотрите nba набор данных nba.info(), вы увидите, что он довольно аккуратный. Только столбец notes содержит нулевые значения для большинства его строк:

Панды DataFrame .info ()

Эти выходные данные показывают, что notes столбец имеет только 5424 ненулевых значения. Это означает, что более 120 000 строк вашего набора данных имеют нулевые значения в этом столбце.

Иногда самый простой способ справиться с записями, содержащими пропущенные значения, – это игнорировать их. Вы можете удалить все строки с пропущенными значениями, используя .dropna():

>>> rows_without_missing_data = nba.dropna()
>>> rows_without_missing_data.shape
(5424, 23)

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

Вы также можете удалить проблемные столбцы, если они не имеют отношения к вашему анализу. Для этого используйте .dropna() снова и укажите axis=1 параметр:

>>> data_without_missing_columns = nba.dropna(axis=1)
>>> data_without_missing_columns.shape
(126314, 22)

Теперь результат DataFrame содержит все 126 314 игр, но не пустой notes столбец.

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

>>> data_with_default_notes = nba.copy()
>>> data_with_default_notes["notes"].fillna(
...     value="no notes at all",
...     inplace=True
... )
>>> data_with_default_notes["notes"].describe()
count              126314
unique                232
top       no notes at all
freq               120890
Name: notes, dtype: object

Здесь вы заполняете пустые notes строки строкой "no notes at all".

Неверные значения

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

Одна вещь, которую вы можете сделать, это проверить диапазоны ваших данных. Для этого .describe() достаточно удобен. Напомним, что он возвращает следующий вывод:

Pandas DataFrame .describe ()

year_id колеблется между 1947 и 2015 годами Это звучит правдоподобно.

Как насчет pts? Как минимум может быть 0? Давайте посмотрим на эти игры:

>>> nba[nba["pts"] == 0]

Этот запрос возвращает одну строку:

Pandas DataFrame запрос

Кажется, игра была утрачена. В зависимости от вашего анализа, вы можете удалить его из набора данных.

Несоответствующие ценности

Иногда значение может быть полностью реалистичным само по себе, но оно не соответствует значениям в других столбцах. Вы можете определить некоторые критерии запроса, которые являются взаимоисключающими, и убедиться, что они не встречаются вместе.

В наборе данных НБА, значения полей ptsopp_pts и game_result должны быть согласованы друг с другом. Вы можете проверить это, используя .empty атрибут:

>>> nba[(nba["pts"] > nba["opp_pts"]) & (nba["game_result"] != 'W')].empty
True
>>> nba[(nba["pts"] < nba["opp_pts"]) & (nba["game_result"] != 'L')].empty
True

К счастью, оба этих запроса возвращают пустой DataFrame.

Будьте готовы к неожиданностям всякий раз, когда вы работаете с необработанными наборами данных, особенно если они были собраны из разных источников или по сложному конвейеру. Вы можете увидеть ряды, в которых команда набрала больше очков, чем противник, но все равно не победила – по крайней мере, согласно вашему набору данных! Чтобы избежать подобных ситуаций, обязательно добавьте дополнительные методы очистки данных в свой арсенал Pandas и Python.

Объединение нескольких наборов данных

В предыдущем разделе вы узнали, как очистить грязный набор данных. Другим аспектом реальных данных является то, что они часто бывают множественными. В этом разделе вы узнаете, как собрать эти фрагменты и объединить их в один набор данных, который готов для анализа.

Ранее вы объединяли два Series объекта  DataFrame в зависимости от их индексов. Теперь вы сделаете еще один шаг и будете использовать .concat() вместе city_data с другим DataFrame. Допустим, вам удалось собрать некоторые данные еще о двух городах:

>>> further_city_data = pd.DataFrame(
...     {"revenue": [7000, 3400], "employee_count":[2, 2]},
...     index=["New York", "Barcelona"]
... )

Эта секунда DataFrame содержит информацию о городах "New York" и "Barcelona".

Вы можете добавить эти города, city_data используя .concat():

>>> all_city_data = pd.concat([city_data, further_city_data], sort=False)
>>> all_city_data
Amsterdam   4200    5.0
Tokyo       6500    8.0
Toronto     8000    NaN
New York    7000    2.0
Barcelona   3400    2.0

Теперь новая переменная all_city_data содержит значения из обоих DataFrame объектов.

Примечание. Начиная с версии Pandas 0.25.0 значение sort параметра по умолчанию равно значению True, но оно скоро изменится на False. Рекомендуется предоставить явное значение для этого параметра, чтобы гарантировать, что ваш код работает согласованно в разных версиях Pandas и Python. Для получения дополнительной информации обратитесь к Руководству пользователя Pandas .

По умолчанию concat() объединяется вместе axis=0. Другими словами, он добавляет строки. Вы также можете использовать его для добавления столбцов, указав параметр axis=1:

>>> city_countries = pd.DataFrame({
...     "country": ["Holland", "Japan", "Holland", "Canada", "Spain"],
...     "capital": [1, 1, 0, 0, 0]},
...     index=["Amsterdam", "Tokyo", "Rotterdam", "Toronto", "Barcelona"]
... )
>>> cities = pd.concat([all_city_data, city_countries], axis=1, sort=False)
>>> cities
           revenue  employee_count  country  capital
Amsterdam   4200.0             5.0  Holland      1.0
Tokyo       6500.0             8.0    Japan      1.0
Toronto     8000.0             NaN   Canada      0.0
New York    7000.0             2.0      NaN      NaN
Barcelona   3400.0             2.0    Spain      0.0
Rotterdam      NaN             NaN  Holland      0.0

Обратите внимание, как Pandas добавляет NaN для пропущенных значений. Если вы хотите объединить только города, которые появляются в обоих DataFrame объектах, то вы можете установить join параметр в inner:

>>> pd.concat([all_city_data, city_countries], axis=1, join="inner")
           revenue  employee_count  country  capital
Amsterdam     4200             5.0  Holland        1
Tokyo         6500             8.0    Japan        1
Toronto       8000             NaN   Canada        0
Barcelona     3400             2.0    Spain        0

Хотя наиболее просто объединить данные на основе индекса, это не единственная возможность. Вы можете использовать .merge() для реализации операции соединения, аналогичной той, что в SQL:>>>

>>> countries = pd.DataFrame({
...     "population_millions": [17, 127, 37],
...     "continent": ["Europe", "Asia", "North America"]
... }, index= ["Holland", "Japan", "Canada"])
>>> pd.merge(cities, countries, left_on="country", right_index=True)

Здесь вы передаете параметр, left_on="country" в .merge() чтобы указать, к какому столбцу вы хотите присоединиться. В результате получится больше, DataFrame в котором содержатся не только городские данные, но и население и континент соответствующих стран:

Панды слияния

Обратите внимание, что результат содержит только те города, в которых страна известна и отображается в объединенной DataFrame.

.merge() выполняет внутреннее соединение по умолчанию. Если вы хотите включить в результат все города, вам нужно указать how параметр:

>>> pd.merge(
...     cities,
...     countries,
...     left_on="country",
...     right_index=True,
...     how="left"
... )

С помощью этого left соединения вы увидите все города, в том числе без данных о стране:

Панды слиться левое соединение

С возвращением, Нью-Йорк и Барселона!

Визуализация вашей Pandas DataFrame

Визуализация данных – это одна из вещей, которая работает гораздо лучше в Jupyter, чем в терминале, поэтому начните с нее. Если вам нужна помощь для начала работы, ознакомьтесь с Jupyter Notebook: Введение .

Включите эту строку, чтобы показать графики прямо в блокноте:

>>> %matplotlib inline

Оба объекта Series и DataFrame имеют .plot() метод, который является оберткой matplotlib.pyplot.plot(). По умолчанию создается линейный сюжет . Представьте, сколько очков набрали Knicks за сезон:

>>> nba[nba["fran_id"] == "Knicks"].groupby("year_id")["pts"].sum().plot()

Это показывает линейный график с несколькими пиками и двумя заметными долинами в 2000 и 2010 годах:

Панда сюжетная линия

Вы также можете создавать другие типы графиков, например гистограмму :

>>> nba["fran_id"].value_counts().head(10).plot(kind="bar")

Это покажет франшизы с большинством сыгранных игр:

Pandas сюжет бар

«Лейкерс» лидируют в «Селтикс» с минимальным преимуществом, и есть еще шесть команд с количеством игр выше 5000.

Теперь попробуйте более сложное упражнение. В 2013 году Майами Хит выиграл чемпионат. Создайте круговую диаграмму, показывающую счет их побед и поражений за этот сезон. Затем посмотрите ниже:

Сначала вы определяете критерий, включающий в себя только игры Heat за 2013 год. Затем вы создаете сюжет так же, как вы видели выше:

>>> nba[
...     (nba["fran_id"] == "Heat") &
...     (nba["year_id"] == 2013)
... ]["game_result"].value_counts().plot(kind="pie")

Вот как выглядит чемпионский пирог:

Панда сюжетный пирог

Ломтик выигрышей значительно больше, чем кусочек потерь!

Иногда цифры говорят сами за себя, но часто диаграмма помогает вам донести ваши идеи. 

Вывод

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

Теперь вы можете:

  • Работа с Series и DataFrame объектами
  • Подмножеству данных с .loc.iloc и оператор индексирования
  • Отвечать на вопросы с помощью запросов, группировки и агрегации
  • Обрабатывать отсутствующие, недействительные и противоречивые данных
  • Визуализировать свой набор данных в блокноте Jupyter

Это путешествие с использованием статистики NBA только показывает, что вы можете сделать с библиотекой Pandas. Вы можете усилить свой проект с помощью трюков Pandas , изучить приемы ускорения Pandas в Python и даже погрузиться вглубь, чтобы увидеть, как Pandas работает за кулисами . Есть много других возможностей, которые вы можете открыть, так что выбирайте эти наборы данных!


Совершенствуй знания каждый день у нас в Телеграм-каналах

Вопросы, реклама — VK | Telegram