Эта статья является частью серии «Наука о данных с нуля — могу ли я, чтобы я могла».

Нажмите здесь, чтобы перейти к предыдущей статье/лекции «A7: NumPy (практические упражнения)

✅ Предложение:Откройте новый блокнот Jupyter и введите код, читая эту статью. Делать — это учиться, и да, «ПОЖАЛУЙСТА, прочитайте комментарий, он очень полезен…. .!»

Панды: главное

Добро пожаловать в основы панд!

Pandas — это современный инструмент/библиотека в экосистеме Python для Data Science. Эта высокопроизводительная и простая в использовании библиотека с открытым исходным кодом является обязательным навыком для любого специалиста по данным. Благодаря концепции открытого исходного кода, которая удобно объединила единомышленников, чтобы посвятить свое драгоценное время и энергию, они сделали панд доступными для всех сегодня!

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

  • Структуры данных Pandas: (Серии, DataFrame и как получить из них необходимые данные — индексирование и выбор)
  • Иерархическая индексация
  • Очистка данных, подготовка и обработка недостающих данных
  • Обработка данных: слияние/объединение, объединение/объединение
  • Агрегация данных и GroupBy

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

Начнем со структур данных pandas.

Структуры данных панд:

Series и DataFrame — это две рабочие лошадки в пандах.
Давайте сначала поговорим о сериях:

Ряд:

Серия — это одномерный объект, похожий на массив, который содержит значения и массив меток, связанных со значениями. Серии могут содержать данные любого типа (например, целые числа, строки, числа с плавающей запятой, объекты Python…) и могут быть проиндексированы с помощью меток (меток осей).

(Серия похожа на массив NumPy — на самом деле она построена поверх объекта массива NumPy) Серия может содержать любой произвольный объект Python.

Давайте приступим к практике и изучим концепции Series на примерах:

Мы можем создать серию, используя список, массив numpy или словарь
Давайте создадим эти объекты и преобразуем их в серию панды!

Серии с использованием списков
Давайте создадим списки Python, один из которых будет содержать метки, а другой — данные.

Итак, у нас есть два объекта списка Python:

  • my_labels - список строк, и
  • my_data - список чисел

Мы можем использовать pd.Series (базовый метод в пандах, начинающийся с заглавной S), чтобы преобразовать объект списка Python в серию панд.

✅:Если вы нажмете <Shift+tab>, из документации вы заметите, что Series может принимать самые разные параметры, в данный момент мы сосредоточимся на данных и индексе.

Давайте рассмотрим только параметр data и посмотрим, как он работает!

Обратите внимание, что «0 1 2» — это автоматически сгенерированный индекс для элементов в ряду с данными «100 200 300».

Мы можем указать значения индекса и получить соответствующие данные/значения, используя эти индексы.
Давайте передадим my_labels в серию как индекс.

Серии с использованием массивов NumPy
Давайте создадим массив NumPy из my_data, а затем из этого массива

Обратите внимание, мы снова получили столбец индекса «0 1 2», давайте передадим наши собственные значения индекса!

Серия с использованием словаря:

Обратите внимание на разницу: если мы передаем dictionary в pd.Series, панды будут принимать ключи как index/labels и values в качестве данных.

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

Создание серии типа int с использованием arange().

Ну, по умолчанию это int64 типов, однако мы можем создать серию, если тип int32. Позвольте мне сделать это двумя способами.

ser2 — тип с плавающей запятой, мы можем создать новую серию типов int, например. ser3 из ser2. Давай сделаем это. Помните, что по умолчанию int равно int64.

В случае, если вы просто хотите проверить тип данных вашей серии, используйте dtype.

Что, если мы создадим объект Series с integers от 1 до 5 и float 6.0.

  • Каким будет тип данных Series?
  • Что если вместо float вставить string '6'?
  • Можете ли вы преобразовать серию в тип int?

Давайте попробуем это с кодом.

Обратите внимание на разницу в dtype!

Что, если у нас есть какая-то строка вместо 6. Например, «s»

Что нужно сделать: создайте серию с данными [1, 2, 3, 6., 'foo']. Какой тип данных у серии?

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

Получение данных из серии:

Индексы — ключевая вещь, которую нужно понять в Series. Панды используют эти индексы (числа или имена) для быстрого поиска информации. (Индекс работает так же, как хеш-таблица или словарь).

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

Теперь у нас есть три серии ser1, ser2 & ser3. Вы можете распечатать их все, чтобы посмотреть, как они выглядят, я проверю один из них, ser1.

Чтобы получить информацию для серии, мы можем просто передать индекс, и он вернет значение, связанное с этим индексом. (похоже на словарь, верно?)

Во всех наших сериях ser1, ser2 и ser3 индексами являются названия городов, которые представляют собой строки. Возьмем значения некоторых городов из этих рядов. Помните, что названия городов (индексы) чувствительны к регистру, calgary не совпадает с Calgary.

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

Основные операции над сериями обычно основаны на индексе.
Например, если мы хотим добавить ser1 + ser2, он пытается сопоставить операцию на основе индекса. Для Calgary, Montreal и Vancouver он добавляет значения, тогда как для Toronto он не может найти совпадение и помещает туда NaN. (Торонто – это 700 – это ser1, где ser2 его нет, поэтому присвоение значения Торонто в дополнение к операции сложения ser1 и ser2 вводит в заблуждение)

Теперь давайте добавим ser4 и ser3 сейчас.

Если вы сравните ser4 и ser3, вы ожидаете еще NaN после их добавления.

Итак, из приведенных выше операций мы узнали, что значения, найденные в ряду, будут складываться для их соответствующего индекса, с другой стороны, если нет совпадения, значение отображается как NaN (не число), что считается в pandas, чтобы отмечать отсутствующие значения или значения NA.

Теперь давайте продолжим и рассмотрим некоторые полезные встроенные функции methods и attributes в сериях.

isnull(): обнаруживает отсутствующие данные и возвращает True для отсутствующих точек данных.

notnull(): обнаруживает существующие (ненулевые) значения и возвращает True, если значение не равно нулю.

Что ж, гораздо лучше знать, сколько точек данных отсутствует и/или сколько точек данных ненулевые. Очень просто использовать sum() вместе с isnull() и/или notnull().
Давайте еще раз попробуем ser5.

head(), tail(): чтобы просмотреть небольшую выборку объекта Series или DataFrame (мы скоро узнаем DataFrame), мы используем head() и tail() методов.
Количество отображаемых элементов/точек данных по умолчанию равно 5, но мы можем указать другое число. ‹shift+tab›, чтобы просмотреть документацию.

axes: возвращает список меток оси строки (индекс).

values: возвращает список значений/данных.

size: возвращает количество элементов (размер) в серии.

empty: True, если серия пуста.

Итак, на данный момент это все о Series, давайте продолжим и поговорим о DataFrame, второй рабочей лошадке панд.

Датафрейм:

  • Очень простой способ представить себе DataFrame — это "группа рядов вместе, например, если они имеют один и тот же индекс".
  • DataFrame – это прямоугольная таблица (двумерная структура данных с метками), которая содержит упорядоченный набор столбцов, каждый из которых может относиться к разным типам данных (числовым, строковым, логическим , и т.д).
  • DataFrame имеет индексы строк и столбцов, подумайте об электронной таблице! Без сомнения, это наиболее часто используемая структура данных от pandas.

Давайте двигаться дальше и изучать DataFrame на примерах:

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

  • Создайте две метки или индексы: row_label и col_label
  • Создайте двумерную матрицу 10x10, используя встроенные методы numpy, arange() и reshape()
  • Создайте DataFrame, используя индексы и матрицу

СОВЕТ. Используйте <TAB> для автозаполнения и <shift + TAB> для документации.

  • df — это наш первый dataframe, верно!
  • c1 до c10 — столбцы, а r1 до r10 — строки в df.
  • Каждый столбец на самом деле является pandas Series, имеющим общий индекс, метки строк.

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

Захват столбцов из фрейма данных:

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

  • Вы заметили, что вывод выше выглядит как Series, верно?
  • Еще одна вещь, на которую следует обратить внимание: возвращенные Series имеют те же index, что и DataFrame.

Давайте проверим type одного столбца (Series) из df.

Мы можем получить более одного столбца, просто передав список нужных нам столбцов!

✅ СОВЕТ: нажмите <TAB> после df., вы увидите ряд доступных методов для фрейма данных. Тем не менее, это хорошо для этого один раз!

Полезно знать:
df.<name_of_the_column> (например, df.c1, df.c2 в приведенном выше кадре данных) также можно использовать для захвата одного столбца, однако на данном этапе это не рекомендуется. Может быть столбец с именем, содержащим более одного слова и разделенным пробелом, например. <product name>, мы не можем получить такие столбцы с помощью этого метода и должны передать имя столбца в виде строки в квадратных скобках.

Давайте попробуем получить столбец из нашего фрейма данных df с помощью оператора dot ..

Добавление нового столбца в фрейм данных:

pandas кадры данных очень удобны. Мы можем удобно добавить новый столбец в наш фрейм данных. Давайте добавим столбец с именем c1+c2, добавив два существующих столбца с помощью простого оператора +!

Удаление столбца из фрейма данных:

Мы можем удалить любой столбец из фрейма данных, используя метод drop().

Несколько важных параметров, которые нам нужно учитывать в drop():

  • label: имя столбца, которое нам нужно передать, если нам нужно удалить более одного столбца, это должен быть список имен столбцов.
  • axis: значение по умолчанию — 0, которое относится к строкам, чтобы удалить столбец, нам нужно передать axis = 1.
  • inplace: по умолчанию False, что предотвращает постоянное изменение. Нам нужно пройти True для постоянного изменения. Inplace очень полезен, он гарантирует, что мы не удаляем/удаляем какой-либо столбец по ошибке. Если мы не передадим этот параметр, столбец не будет удален из фрейма данных.

Хотите узнать больше, используйте <Shift+tab> для изучения документации.

Просто быстро проверьте, сколько столбцов и строк у нас есть в нашем фрейме данных, df. Здесь мы можем использовать атрибут shape!

Итак, у нас есть 10 строк и 11 столбцов в нашем фрейме данных df, «c1+c2» — это 11-й столбец, который мы добавили выше. Давайте удалим этот столбец.
Помните: если мы не передадим inplace = True, изменение не будет постоянным. Попробуйте сами, не проходя inplaceи увидите разницу.

Напоминание. Чтобы удалить столбец, вы должны сообщить пандам, установив inplace = True (по умолчанию inplace = False). pandas щедр и не хочет, чтобы мы потеряли информацию по какой-либо ошибке.

Захват строк из фрейма данных:

Захват строки отличается от захвата столбцов из фрейма данных. Если вы думаете, что можете использовать df['r1'] для захвата строки 'r1', это неверно и возвращает KeyError: 'r1'.

Чтобы получить или получить строку, нам нужно использовать loc и iloc.

  • loc: доступ к строкам по label(s)/name(s).
  • iloc: использование строки index location.

Давайте используем loc для получения двух строк r2 и r3. Для этого нам нужно передать список [r2, r3] внутри квадратных скобок.

Итак, r1 и r2 — это метки, их соответствующие местоположения индекса — 1 и 2 (помните, что индекс начинается с 0), давайте теперь используем местоположения индекса с iloc. Это легко, даже если наш индекс помечен.

Захват одного элемента из кадра данных:

Вспомните свой класс линейной алгебры, работающий с матрицами. Чтобы получить один элемент, вам нужно его местоположение, [row, col], правильно!

Захват подмножества фрейма данных:

Мы можем получить подмножество, передав [[list of required rows],[list of required columns]] в наборе квадратных скобок.

Условный выбор или маскирование:

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

Давайте попробуем захватить все значения в df, которые больше 5.

Обратите внимание, что мы получаем True во всех местах, где выполняется условие (df>5)! Подобно логической маскировке numpy, нам нужно создать маску, и они используют эту маску для соответствующего захвата значений. Мы получим NaN, где условие False.

Попробуем создать другую маску "mask_df_div_3==0" для значений, которые делятся на 3 (df % 3 == 0). Нам нужны значения, в которых условие выполнено (True), и NaN, где оно равно False.

Полезно знать:
Использование такой операции (см. выше) для всего фрейма данных не является распространенным явлением, поскольку они могут добавить много NaN или отсутствующих данных. Обычно мы используем их в столбцах или строках вместо фильтрации.

Что, если мы хотим получить все строки, для которых значения больше 11 в столбце c1. Все строки на основе условия для любого столбца. Начнем с проверки, где требуемое условие не выполняется и возвращает False в столбце c1. Затем мы работаем со всем фреймом данных df, хорошо!

Итак, нам не нужны строки r1 и r2 в нашем выборе, так как условие False.

Давайте отфильтруем строки на основе условия для значений столбца (c1>11).

Что ж, если мы хотим сохранить результаты в новом фрейме данных, мы действительно можем создать новый фрейм данных на основе нашего условного выбора result = df[df['c1']>11].
Давайте создадим фрейм данных result и будем работать с ним, это просто!

Обратите внимание, что после операции выбора/фильтрации положение индекса для строк изменяется. В приведенном выше примере r3 теперь получил 0index. Именно здесь loc и iloc имеют значение, и мы предпочитаем захватывать строки (если требуется), используя их метки в loc.

Например, мы все еще можем получить r3 и r5 с их метками, не зная их местоположения индекса из кадра данных result.

В случае, если мы все еще заинтересованы в захвате, скажем, r3 и r5, используя iloc, нам нужно знать их индексные позиции.

Мы видим, что r3 получил индекс 0, а r5 получил индекс 2. Мы можем использовать [0,2] в iloc для захвата соответствующих строк.

Хорошо, чтобы немного попрактиковаться, давайте возьмем все строки из нашего исходного фрейма данных df, которые имеют значение 70 в столбце c1.

Двигаясь вперед, вспомните свое понимание условных операторов из раздела Python. Мы можем легко комбинировать несколько условий, используя операторы &, |.
Давайте попробуем!

  • фильтровать кадр данных df для значений меньше 30 в c1 & меньше 50 в c2.
  • фильтровать кадр данных df для значений меньше 30 в c1 | меньше 50 в c2.

Примечание: and и or не будут работать, нам нужно использовать & и |, см. объяснение ниже после нескольких ячеек.

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

*ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Это «неоднозначное» означает, что True работает только для одного логического значения одновременно «True и False». Вместо этого нам нужно использовать «&». ('|' вместо or)
Попробуйте использовать приведенный выше код, используя вместо этого 'and, or, чтобы увидеть!'
Операторы 'and, or' путаются с сериями True/False и вызывают ошибку!

Надеюсь, вы хорошо разобрались с DataFrames на данном этапе. Давайте двигаться дальше и изучим пару полезных встроенных методов для DataFrames. Мы рассмотрим больше позже в следующих статьях!

reset_index(): это сбросит индекс нашего фрейма данных на числовой индекс (который является индексом по умолчанию), существующий индекс r1 на r10 для нашего фрейма данных df) будет новым столбец.

set_index(): учтите, мы считаем, что существующий столбец в нашем фрейме данных может быть полезным индексом, и мы хотим установить этот столбец в качестве индекса. Этот метод полезен для этой цели!
Пожалуйста, посмотрите код ниже и внимательно прочитайте комментарии.

Что ж, мы можем думать о new_index как о хорошем индексе и использовать set_index() для создания нового индекса. (inplace должен мне Trueдля постоянного изменения)

head(), tail(): пока наш фрейм данных 'df' содержит только 10 строк. Что, если строк будет много? head() и tail() — это полезные методы (похожие на Series выше), чтобы увидеть первые и последние 5 строк (по умолчанию) в качестве образца нашего фрейма данных.

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

describe(): очень удобный и один из предпочтительных методов создания описательной или сводной статистики, которая обобщает центральную тенденцию, дисперсию и форму распределения набора данных, за исключением NaN значений.
Обратите внимание, что в описании учитываются только числовые столбцы.

Отличная работа, ребята! На данный момент это было все о Series и DataFrame. Мы рассмотрим другие важные концепции в следующих статьях.

Похлопайте и поделитесь этой статьей в своих контактах, возможно, кто-то изо всех сил пытается изучить эти понятия.

Удачи!

Увидимся на следующей лекции на тему A9: Иерархическое индексирование (многоиндексирование) и обработка отсутствующих данных”.

Примечание. Полный курс, включая видеолекции и блокноты Jupyter, доступен по следующим ссылкам:

О докторе Джунаиде Кази:

Доктор. Джунаид Кази— предметный специалист, консультант по науке о данных и машинному обучению. Он является тренером по профессиональному развитию, наставником, автором и приглашенным спикером. С ним можно связаться для консультационных проектов и/или обучения профессионального развития через LinkedIn или через ScienceAcademy.ca.