Заметки
Введение
Библиотека pandas — невероятно полезный инструмент для обработки и анализа структурированных данных на языке программирования Python, который позволяет легко импортировать, манипулировать и агрегировать данные, что делает его незаменимым для задач анализа данных.
Для того чтобы начать работу с библиотекой стоит ознакомиться с  официальной документацией pandas. Полезная двустраничная шпаргалка с набором команд находится в официальной документации по ссылке - добавьте ее себе в закладки.
В этой статье я хочу сделать обзор челенджа 30 days of Pandas от LeetCode, чтобы выделить и сохранить наглядные примеры использования методов манипулирования данными и посмотреть как данные методы извлечения данных в pandas соотносятся с такими же механизмами SQL.

Обзор
Давате погрузимся в возможности библиотеки Pandas с помощью этой статьи и рассмотрим часто используемые паттерны манипулирования данными. Будем рассматривать Pandas по следующим пунктам - обзор библиотеки, сравнение SQL и темы из челленджа:
- Фильтрация данных
 - Строковые методы
 - Манипуляция данными
 - Агрегирование данных
 - Интеграция данных
 
Что такое DataFrame
Класс DataFrame в библиотеке Pandas — это мощная двумерная помеченная структура данных со столбцами, которые могут быть разных типов и которой можно манипулировать как матрицей. Он обеспечивает гибкий и эффективный способ обработки и анализа структурированных данных. Вот краткий пример создания DataFrame:
import pandas as pd
subjects_data = {'Subject': ['Mathematics', 'Computer Science', 'Literature'],
                 'Units': [4, 3, 2],
                 'Level': ['Advanced', 'Intermediate', 'Beginner']}
subjects_df = pd.DataFrame(subjects_data)
Класс DataFrame в Pandas реализует подход к взаимодействию с табличными данными. Поскольку у него есть переопределение для __getitem__, то можно использовать оператор скобок ([]), чтобы получить из него данные.
Например, можно использовать строковый ключ с именем столбца, чтобы получить его df['column'].
Внутри скобок можно помещать объекты разных типов: строка, итерируемый объект(список), срез и т.д.
Выборка и фильтрация данных
Рассмотрим выборку строк и столбцов из DataFrame.  
Выбор одного столбца с использованием операции скобок возвращающее <class 'Series'>:
subject_column = df['Subject']
# 0         Math
# 1      Physics
# 2      History
# 3    Chemistry
# Name: Subject, dtype: object
Выборка нескольких колонок как <class 'DataFrame'>:
subset_data = df[['Subject', 'Units']]
#      Subject  Units
# 0       Math      4
# 1    Physics      3
# 2    History      3
# 3  Chemistry      4
Выборка обной строки как <class 'Series'> с помощью функции loc:
Выборка значения ячейки с помощью функции at по индексу строки и названию колонки:
Различные способы получения значения ячейки по столбку и строке с помощью функций loc, iloc, at, iat:
subject = df.at[0, 'Subject']
subject = df.iat[0, 0]
subject = df.loc[0].loc['Subject']
subject = df.loc[0].iloc[0]
subject = df.loc[0].at['Subject']
subject = df.loc[0].iat[0]
# Все вызовы возвращают 'Math'
Разница между iat и at (а также loc и iloc) заключается в том, что i* функции по порядковому номеру строки в индексоной колонке, а at и loc непосредственно по значению индекса. Так как по умолчанию индексами как раз являются целые неотрицательные числа, то использование этих двух видов функций будет эквивалентно. Однако если в качестве индекса будет использоваться другие значения (например строки), то вызов таких функций будет возвращать ошибку.
После получения объекта Series со значениями строк df.loc[0], мы получаем объект, в котором имена колонок используются в качетве индексов, таким образом здесь можно использовать следущую конструкцию df.loc[0].loc[0].
Также функци .loc и .iloc можно использовать передавая в параметры слайсы:
# Здесь выбираются строки с 1 по 3 (включительно) и все столбцы
subset_df = df.loc[1:3, :]
# Выборка строк с 1 по 3 и столбцов 'Subject' и 'Difficulty'
subset_df = df.loc[1:3, ['Subject', 'Difficulty']]
Выбор строки по условию — выбор строк, в которых Units больше 3 в качестве объекта <class 'DataFrame'>
high_credit_subjects = df[df['Units'] > 3]
#      Subject  Units Difficulty
# 0       Math      4       Hard
# 3  Chemistry      4   Moderate
Выбор строки на основе нескольких условий — выбор строк, в которых Units больше 3, а Difficulty равно Hard, как объект <class 'DataFrame'>
hard_subjects = df[(df['Units'] > 3) & (df['Difficulty'] == 'Hard')]
#   Subject  Units Difficulty
# 0    Math      4       Hard
Логические операции с DataFrame
Перед тем как перейти к рассмотрению логических операций в pandas давайте подробнее рассмотрим как работает скобочный оператор [] (brackets operation) с объектами DataFrame. Логические операции со столбцами DataFrame возвращают класс Series с результатом использованной операции.
Например: после вызова этой строчки кода bool_series = df['Units'] > 3 в bool_series будет записан объект типа <class pandas.core.series.Series> со значением
И после этого мы могли бы использовать Series для фильтрации нашего DataFrame.
unit_3_df = df[df['Units'] > 3]
# или
unit_3_df = df[bool_series]
#      Subject  Units Difficulty
# 0       Math      4       Hard
# 3  Chemistry      4   Moderate
Затем мы можем применять к этим объектам обычные булевые операции как к обычной матрице.
Булевые объекты Series могут использоваться как параметры в функциях loc/iloc. 
В pandas логические операторы и логические функции используются для логических операций с DataFrame и Series. Вот краткий обзор логических операторов, обычно используемых в pandas:
&(Оператор И): объединяет два условия поэлементно и возвращает True, если оба условия истинны. напримерdf[(df['Column1'] > 5) & (df['Column2'] == 'Value')]|(Оператор ИЛИ): объединяет два условия поэлементно и возвращает True, если хотя бы одно из условий истинно. напримерdf[(df['Column1'] > 5) | (df['Column2'] == 'Value')]~(Оператор НЕ): инвертирует логические значения, возвращая True, если условие ложно. напримерdf[~(df['Column1'] > 5)]^(Оператор XOR): применяет функцию xor. напримерdf[~(df['Column1'] > 5)]isnull(),notnull()функции: например. фильтрация строк, в которыз 'Difficulty' является nullnull_difficulty_courses = df[df['Difficulty'].isnull()]isin()функцияany(),all()функции: напримерfiltered_df = df[df['Subject'].isin(['Math', 'Physics])]
Строковые функции
Для того чтобы быстро манипулировать столбцами с типом dtype="string" можно использовать различные строковые функции вместо использования вызовой .apply на DataFrame. 
Вот несколько примеров таких функци:
df['Subject'] = df['Subject'].str.capitalize()df['Subject'] = df['Subject'].str.lower()df['Subject'] = df['Subject'].str.upper()df['Subject'] = df['Subject'].str.len()df['Subject'] = df['Subject'].str.replace('$M', 'm', regex=True)df['Subject'].str.match(pattern)df['Subject'].str.contains(pattern)- больше примеров строковых функций можно найти в оффициальной документации pandas
 
Манипуляция данными
В Pandas, обновление данных в DataFrames можно производить различными способами, и вот некоторые полезные из них.
Обновление значения всех полей в столбце с помощью литерала или арифметических операций с существующими столбцами:
df['Column'] = 2df['Column'] = df['Column'] * 2
Обновление значений используя функции .at[], .iat[], .loc[] и .iloc[]. Они используются для получения и изменения значения обной ячейки в DataFrame:
df.at[0, 'Subject'] = "New Subject"df.loc[df['Column'] > 5, 'Column'] = new_value
Добавление или изменения столбцов с помощью функций .apply(), .assign(), .insert():
df['Column'] = df['Column'].apply(lambda x: function(x))применение функции к каждому элементу, столбцу или строке в DataFramedf = df.assign(NewColumn=new_values)создание или изменение столбцов с использованием уже сущестуующихdf.insert(loc=2, column='NewColumn', value=new_values)вставка нового столбца
Параметр inplace=True
Параметр inplace в pandas используется для указания, следует ли выполнять операцию изменяя существующий объект или возвращать новый. Если для параметра inplace установлено значение True, изменения вносятся непосредственно в исходный объект, а возвращается значение None. Если для параметра inplace установлено значение False (по умолчанию), возвращается новый объект с изменениями, а исходный объект остается неизменным.
Использование параметра inplace:
df.at[0, 'Column'].update(10, inplace=True)Обновление элемента используя параметр inplacedf.drop(columns='Column', inplace=True)Удаление столбцаdf['Column'].replace(to_replace=1, value=100, inplace=True)Изменение значения в существующем DataFramedf['Column'].apply(lambda x: x * 2, inplace=True)Применение функции к существующему объекту
Агрегация данных
merge groupby agg reset_index
Сравнение с SQL
...