Share This
Связаться со мной
Крути в низ
Categories
//🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 8348c32 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Разработчик ПО (системы PDM/PLM) с 1993 года, компания "ИНТЕРМЕХ" (www.intermech.ru). В 2020-м успешно закончил курсы "Основы Data Science" (минская IT Academy) Референт-переводчик технической литературы с английского языка. Новые и малоизвестные возможности Pandas, о которых полезно знать каждому специалисту по Data Science.

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 1c72256 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Сколько раз вы говорили: «было бы здорово, если бы я мог это сделать в Pandas»?

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

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

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 217233d - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Автор Erik Mclean. Источник Pexels

1. ExcelWriter

ExcelWriter – это обобщенный класс для создания файлов Excel (с листами!) и записи в них DataFrame. Допустим, у нас есть два набора данных:

         # Загрузим два набора данных diamonds = sns.load_dataset("diamonds") tips = sns.load_dataset("tips")  # Пишем оба в один и тот же файл Excel with pd.ExcelWriter("data/data.xlsx") as writer:     diamonds.to_excel(writer, sheet_name="diamonds")     tips.to_excel(writer, sheet_name="tips")     

У класса есть дополнительные атрибуты для определения используемого формата DateTime: хотите ли вы создать новый файл Excel или изменить существующий, что делать, если лист существует и т. п. Детали см. в документации.

2. pipe

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 2ec7997 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Автор Leah Kelley. Источник Pexels

pipe – одна из лучших функций для проведения очистки данных в Pandas кратким и четким образом. Она позволяет объединять несколько пользовательских функций в одну операцию.

Для примера допустим, что у вас есть функции удаления дубликатов (remove_duplicates), удаления выбросов (remove_outliers) и кодирования категориальных признаков (encode_categoricals), каждая со своими аргументами. Вот как вы можете применить все эти функции одной операцией:

         df_preped = (diamonds.pipe(drop_duplicates).                       pipe(remove_outliers, ['price', 'carat', 'depth']).                       pipe(encode_categoricals, ['cut', 'color', 'clarity'])             )     

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

Больше полезной информации вы найдете на нашем телеграм-канале «Библиотека data scientist’а» Интересно, перейти к каналу

3. factorize

Эта функция – альтернатива LabelEncoder из Sklearn в Pandas:

         # Обратите внимание на [0] в конце diamonds["cut_enc"] = pd.factorize(diamonds["cut"])[0]  >>> diamonds["cut_enc"].sample(5)  52103    2 39813    0 31843    0 10675    0 6634     0 Name: cut_enc, dtype: int64     

В отличие от LabelEncoder‘а, factorize возвращает кортеж из двух значений: закодированный столбец и список уникальных категорий.

         codes, unique = pd.factorize(diamonds["cut"], sort=True)  >>> codes[:10] array([0, 1, 3, 1, 3, 2, 2, 2, 4, 2], dtype=int64)  >>> unique ['Ideal', 'Premium', 'Very Good', 'Good', 'Fair']     

4. explode – Бабах!

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 88a84de - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Автор Joshua Sukoff. Источник Unsplash

explode – это функция с интересным именем (взрыв). Давайте сначала посмотрим пример, а потом объясним:

         data = pd.Series([1, 6, 7, [46, 56, 49], 45, [15, 10, 12]]).to_frame("dirty")  >>> data     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 ab9d9c7 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

В столбце dirty есть две строки, в которых хранятся не единственные значения, а списки. Такие данные часто встречаются в опросах, поскольку некоторые вопросы допускают несколько ответов.

         >>> data.explode("dirty", ignore_index=True)     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 b52a768 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

explode распространяет данные из ячейки с массивоподобным значением на несколько строк. Установите ignore_index в True, чтобы сохранить числовой индекс по порядку.

5. squeeze

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 f88ca00 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Автор cottonbro. Источник Pexels

Еще одна функция с забавным именем – это squeeze (сжатие), используемая в очень редких, но надоедливых случаях. Один из таких случаев – когда запрос подмножества из DataFrame возвращает единственное значение. Рассмотрим следующий пример:

         subset = diamonds.loc[diamonds.index < 1, ["price"]]  >>> subset     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 2679b5b - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Хотя результат – всего одна ячейка, он возвращается как DataFrame. Это неудобно, поскольку вам придется еще раз использовать .loc и передать как имя столбца, так и индекс, чтобы получить цену.

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

         >>> subset.squeeze() 326     

Теперь мы получили скалярное значение. Можно также указать, какую ось нужно убрать:

         >>> subset.squeeze("columns")  # или "rows"  0    326 Name: price, dtype: int64     

Обратите внимание, что squeeze работает только с DataFrame и Series, имеющими единственное значение.

6. between

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 c4293b3 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Автор Justin Dream. Источник Pexels

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

         # Выбрать бриллианты с ценой от 3500 до 3700 долларов diamonds[diamonds["price"]       .between(3500, 3700, inclusive="neither")].sample(5)     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 3b096c3 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

7. T

У всех DataFrame есть простой атрибут T, что значит «транспонирование». Возможно, вы не будете часто его использовать, но я считаю его довольно полезным при выводе DataFrame’ов после метода describe():

         >>> boston.describe().T.head(10)     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 e57d1e0 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

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

8. Стилизатор Pandas

А вы знали, что Pandas позволяет вам задавать стили DataFrame’ов?

У них есть атрибут style, открывающий дверь к настройкам и стилям, ограниченным только вашими знаниями HTML и CSS. Я не буду рассказывать обо всем, что вы можете сделать с помощью style, покажу лишь свои любимые функции:

         >>> diabetes.describe().T.drop("count", axis=1)                  .style.highlight_max(color="darkred")     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 51fba36 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Мы выделили ячейки, содержащие максимальные значения каждого столбца. Еще один полезный стилизатор – background_gradient, присваивающий ячейкам градиентный фоновый цвет на основе их значений:

         diabetes.describe().T.drop("count", axis=1).style.background_gradient(     subset=["mean", "50%"], cmap="Reds" )     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 b5daeb6 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Это особенно полезно, если вы вызываете describe для таблицы со множеством столбцов и хотите сравнить суммарную статистику. Подробности см. в документации по стилизатору.

9. Опции Pandas

Как и в Matplotlib, в Pandas есть глобальные настройки, которые можно изменять для настройки поведения по умолчанию:

         >>> dir(pd.options) ['compute', 'display', 'io', 'mode', 'plotting']     

Эти настройки разделены на 5 модулей. Давайте посмотрим, какие настройки есть в модуле display:

         >>> dir(pd.options.display)  ['chop_threshold',  'max_columns',  'max_colwidth',  'max_info_columns',  'max_info_rows',  'max_rows',  ...  'precision',  'show_dimensions',  'unicode',  'width']     

В группе display много настроек, но я в основном использую max_columns и precision:

         # Убрать лимит на изображаемое количество столбцов pd.options.display.max_columns = None  # Показывать только 5 цйфр после запятой pd.options.display.precision = 5  # избавиться от научной нотации     

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

10. convert_dtypes

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

         sample = pd.read_csv(     "data/station_day.csv",     usecols=["StationId", "CO", "O3", "AQI_Bucket"], )  >>> sample.dtypes  StationId      object CO            float64 O3            float64 AQI_Bucket     object dtype: object  >>> sample.convert_dtypes().dtypes  StationId      string CO            float64 O3            float64 AQI_Bucket     string dtype: object     

К сожалению, метод не может разбирать даты из-за нюансов различных форматов их представления.

11. select_dtypes

Функция, которую я использую постоянно – это select_dtypes. Ее функционал очевиден из ее названия: выбор по типам данных. У нее есть параметры include и exclude, позволяющие выбрать столбцы, включая или исключая определенные типы данных. Например, можно выбрать только числовые столбцы, указав np.number:

         # Выбрать только числовые столбцы diamonds.select_dtypes(include=np.number).head()     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 54ae314 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

или, наоборот, исключить их:

         # Исключить числовые столбцы diamonds.select_dtypes(exclude=np.number).head()     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 fa01aab - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

12. mask

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 4d0e0b6 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Автор Pixabay. Источник Pexels.

Функция mask позволяет быстро заменять значения в тех ячейках, для которых выполняется определенное условие. Предположим, что у нас есть данные опроса людей от 50 до 60:

         # Create sample data ages = pd.Series([55, 52, 50, 66, 57, 59, 49, 60]).to_frame("ages")  ages     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 eb7bf70 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Мы будем считать возраст, выходящий за границы от 50 до 60 лет, ошибками ввода (таких ошибок две – 49 и 66 лет), которые заменим на NaN:

         ages.mask(cond=~ages["ages"].between(50, 60), other=np.nan)     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 1ad6427 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Таким образом, mask заменяет значения ячеек, не удовлетворяющие cond, значениями other.

13. min и max по строкам и столбцам

Хотя функции min и max широко известны, они имеют еще одно применение, полезное для особых случаев. Давайте рассмотрим следующий набор данных:

         index = ["Diamonds", "Titanic", "Iris", "Heart Disease", "Loan Default"] libraries = ["XGBoost", "CatBoost", "LightGBM", "Sklearn GB"]  df = pd.DataFrame(     {lib: np.random.uniform(90, 100, 5) for lib in libraries}, index=index )  >>> df     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 9af4813 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Этот DataFrame содержит воображаемую точность моделей, полученных в результате четырех видов градиентного бустинга на пяти различных наборах данных. Мы хотим найти лучшую точность на каждом наборе. Вот как элегантно это можно сделать с помощью max:

         >>> df.max(axis=1)  Diamonds         99.52684 Titanic          99.63650 Iris             99.10989 Heart Disease    99.31627 Loan Default     97.96728 dtype: float64     

Если вы хотите найти максимум или минимум по каждому столбцу, достаточно изменить 1 на 0.

14. nlargest и nsmallest

Иногда вам недостаточно получить максимальное или минимальное значение столбца. Вы хотите получить N максимальных (или минимальных) значений. Для этого пригодятся функции nlargest и nsmallest. Давайте выведем 5 самых дорогих и самых дешевых бриллиантов:

         diamonds.nlargest(5, "price")     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 5a54103 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

         diamonds.nsmallest(5, "price")     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 a97078f - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

15. idxmax и idxmin

Когда вы вызываете max или min для столбца, pandas возвращает максимальное или минимальное значение. Однако иногда вам нужна позиция этого значения, а не оно само. Для этого используйте функции idxmax и idxmin:

         >>> diamonds.price.idxmax() 27749  >>> diamonds.carat.idxmin() 14     

Можно также задать axis=’columns’, при этом функции будут возвращать номер индекса нужного столбца.

16. value_counts с параметром dropna=False

Для нахождения процента пропущенных значений чаще всего используется комбинация isnull и sum и деление на длину массива. Но вы можете сделать то же самое с помощью value_counts, если задать соответствующие аргументы:

         ames_housing = pd.read_csv("data/train.csv")  >>> ames_housing["FireplaceQu"].value_counts(dropna=False, normalize=True)  NaN    0.47260 Gd     0.26027 TA     0.21438 Fa     0.02260 Ex     0.01644 Po     0.01370 Name: FireplaceQu, dtype: float64     

В этом столбце 47% пустых значений (NaN).

17. clip

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 4ad2d0e - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Автор Ann H. Источник Pexels

Обнаружение и удаление выбросов часто используется в анализе данных. Функция clip позволяет очень легко найти выбросы, выходящие за пределы диапазона и заменить их предельными значениями. Давайте вернемся к примеру с возрастами людей от 50 до 60:

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 a034535 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

На этот раз мы заменим значения, выходящие за диапазон от 50 до 60, крайними значениями диапазона.

         ages.clip(50, 60)     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 71375a7 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Быстро и эффективно!

18. at_time и between_time

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

         index = pd.date_range("2021-08-01", periods=100, freq="H") data = pd.DataFrame({"col": list(range(100))}, index=index)  >>> data.head()     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 a11801f - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Функция at_time позволяет выбирать значения по заданным дате или времени. Давайте выделим все строки, соответствующие 15.00:

         data.at_time("15:00")     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 c84b218 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Здорово, правда? А теперь давайте используем between_time, чтобы выделить строки в заданном интервале времени:

         from datetime import datetime  >>> data.between_time("09:45", "12:00")     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 9438cc6 - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Заметьте, что обе функции требуют DateTimeIndex, и они работают только с временем. Если вы хотите выделить строки в определенном интервале DateTime, используйте between.

19. bdate_range

bdate_range – это функция для быстрого создания индексов TimeSeries с частотой в один бизнес-день.

         series = pd.bdate_range("2021-01-01", "2021-01-31")  # A period of one month  >>> len(series) 21     

Частота в бизнес-день часто встречается в финансовом мире. Значит, эта функция может оказаться полезной для переиндексирования существующих временных интервалов функцией reindex.

20. autocorr

Один из важнейших компонентов анализа временных последовательностей – это изучение автокорреляции переменной. Автокорреляция – это старый добрый коэффициент корреляции, но взятый по сравнению с лагом той же последовательности. Точнее, автокорреляция при lag=k вычисляется следующим образом:

1. Последовательность сдвигается k периодов времени:

         time_series = tips[["tip"]] time_series["lag_1"] = time_series["tip"].shift(1) time_series["lag_2"] = time_series["tip"].shift(2) time_series["lag_3"] = time_series["tip"].shift(3) time_series["lag_4"] = time_series["tip"].shift(4) # time_series['lag_k'] = time_series['tip'].shift(k)  >>> time_series.head()     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 c5c4def - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

2. Рассчитывается корреляция между исходным значением и каждым лагом.

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

         # Автокорреляция tip при lag_8 >>> time_series["tip"].autocorr(lag=8) 0.07475238789967077     

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

21. hasnans

Pandas предлагает метод для простой проверки, содержит ли Series какие-либо пустые значения – атрибут hasnans:

         series = pd.Series([2, 4, 6, "sadf", np.nan])  >>> series.hasnans True     

Согласно его документации, атрибут существенно ускоряет производительность. Заметьте, что он работает только для Series.

22. at и iat

Эти два метода доступа к значениям – гораздо более быстрые альтернативы loc и iloc, но с существенным недостатком: они позволяют получить или изменить только одно значение:

         # [index, label] >>> diamonds.at[234, "cut"] 'Ideal'  # [index, index] >>> diamonds.iat[1564, 4] 61.2  # Заменить 16541-ю строку столбца price >>> diamonds.at[16541, "price"] = 10000     

23. argsort

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

         tips.reset_index(inplace=True, drop=True)  sort_idx = tips["total_bill"].argsort(kind="mergesort")  # Теперь выведем значения `tips` в порядке сортировки по total_bill tips.iloc[sort_idx].head()     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 feda7ac - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

24. Метод доступа cat

Общеизвестно, что Pandas позволяет использовать встроенные функции Python на датах и строках с помощью методов доступа вроде dt или str. Кроме того, в Pandas есть специальный тип данных category для категориальных переменных, как показано ниже:

         >>> diamonds.dtypes  carat       float64 cut        category color      category clarity    category depth       float64 table       float64 price         int64 x           float64 y           float64 z           float64 cut_enc       int64 dtype: object     

Если столбец имеет тип category, над ним можно выполнять несколько специальных функций с помощью метода доступа cat. Например, давайте рассмотрим различные виды огранки бриллиантов:

         >>> diamonds["cut"].cat.categories ['Ideal', 'Premium', 'Very Good', 'Good', 'Fair']     

Есть и такие функции, как remove_categories, rename_categories и т. д.:

         diamonds["new_cuts"] = diamonds["cut"].cat.rename_categories(list("ABCDE"))  >>> diamonds["new_cuts"].cat.categories Index(['A', 'B', 'C', 'D', 'E'], dtype='object')     

Полный список функций, доступных через метод доступа cat, можно посмотреть здесь.

25. GroupBy.nth

Эта функция работает только для объектов GroupBy. После группировки она возвращает n-ю строку каждой группы:

         diamonds.groupby("cut").nth(5)     

25 vozmozhnostej pandas o kotoryh vy ne znali infa 80 20c44bf - 🐼 25 возможностей Pandas, о которых вы не знали (инфа 80%)

Заключение

Несмотря на то, что новые библиотеки вроде Dask и datatable потихоньку вытесняют Pandas благодаря их сверкающим новым возможностям для обработки огромных массивов данных, Pandas по-прежнему остается самым популярным средством манипуляции данными в экосистеме Data Science на Python.

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

Спасибо за внимание!

***

Материалы по теме

  • 📊 Инструменты дата-журналиста #1: Jupyter Notebook и библиотека Pandas
  • 🤖 Numpy, Pandas, matplotlib – необходимый минимум для старта в Machine Learning
  • 📊Django, Pandas и Chart.js для быстрой панели инструментов

  • 0 views
  • 0 Comment

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Связаться со мной
Close