Архив рубрики ~Лента новостей~

Почему вам следует прекратить писать циклы в Pandas

Почему вам следует прекратить писать циклы в Pandas

Как мыслить в столбик, писать более быстрый код и, наконец, использовать Pandas как профессионал.

Делиться

NOVOSTI
Создано с помощью Gemini AI

Ладно, признаюсь честно: когда я только начинал использовать Pandas, я постоянно писал циклы вот такого типа:

 for i in range(len(df)): if df.loc[i, "sales"] > 1000: df.loc[i, "tier"] = "high" else: df.loc[i, "tier"] = "low"

Это сработало. И я подумал: «Ну, это же здорово, правда?»
Оказалось… не совсем так.

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

Как только я начал мыслить в столбчатом формате , всё изменилось. Код стал короче. Выполнение ускорилось. И внезапно я почувствовал, что Pandas создан именно для того, чтобы помогать мне, а не замедлять меня.

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

 import pandas as pd df = pd.DataFrame({ "product": ["A", "B", "C", "D", "E"], "sales": [500, 1200, 800, 2000, 300] })

Выход:

 product sales 0 A 500 1 B 1200 2 C 800 3 D 2000 4 E 300

Наша цель проста: пометить каждую строку как high , если объем продаж превышает 1000, и как low в противном случае.

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

Метод циклов, с которого я начал

Вот цикл, который я использовал, когда учился:

 for i in range(len(df)): if df.loc[i, "sales"] > 1000: df.loc[i, "tier"] = "high" else: df.loc[i, "tier"] = "low" print(df)

В результате получается следующее:

 product sales tier 0 A 500 low 1 B 1200 high 2 C 800 low 3 D 2000 high 4 E 300 low

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

Такой подход не масштабируется — то, что работает нормально при 5 строках, замедляется при 50 000 строках.

Что еще более важно, это заставляет вас мыслить как новичок — строка за строкой — а не как профессиональный пользователь Pandas.

Замеры времени зацикливания (момент, когда я понял, что оно медленное)

Когда я впервые запустил свой цикл на этом крошечном наборе данных, я подумал: «Ничего страшного, он достаточно быстрый». Но потом я задумался… а что, если бы у меня был набор данных большего размера?

Поэтому я попробовал:

 import pandas as pd import time # Make a bigger dataset df_big = pd.DataFrame({ "product": ["A", "B", "C", "D", "E"] * 100_000, "sales": [500, 1200, 800, 2000, 300] * 100_000 }) # Time the loop start = time.time() for i in range(len(df_big)): if df_big.loc[i, "sales"] > 1000: df_big.loc[i, "tier"] = "high" else: df_big.loc[i, "tier"] = "low" end = time.time() print("Loop time:", end - start)

Вот что у меня получилось:

 Loop time: 129.27328729629517

Это 129 секунд .

Более двух минут уходит только на то, чтобы пометить строки как "high" или "low" .

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

Почему так медленно?

Цикл заставляет Pandas:

  • Получите доступ к каждой строке по отдельности.
  • Выполнять логику на уровне Python для каждой итерации
  • Обновляйте DataFrame по одной ячейке за раз.

Иными словами, это превращает высокооптимизированный столбцовый механизм в усовершенствованный обработчик списков на Python.

А библиотека Pandas создана не для этого.

Решение в одну строчку (и момент, когда всё стало ясно)

После просмотра 129 секунд я понял, что должен быть способ получше.
Поэтому вместо перебора строк я попробовал выразить правило на уровне столбцов :

«Если объем продаж превышает 1000, указывайте высокую маркировку. В противном случае — низкую».

Вот и всё. Таково правило.

Вот векторизованная версия:

 import numpy as np import time start = time.time() df_big["tier"] = np.where(df_big["sales"] > 1000, "high", "low") end = time.time() print("Vectorized time:", end - start)

И каков результат?

 Vectorized time: 0.08

Дайте этому осмыслиться.

Зацикленная версия: 129 секунд
Векторизованная версия: 0,08 секунды

Это более чем в 1600 раз быстрее .

Что только что произошло?

Ключевое различие заключается в следующем:

Цикл обрабатывал DataFrame построчно . Векторизованная версия обрабатывала весь столбец sales за одну оптимизированную операцию .

Когда вы пишете:

 df_big["sales"] > 1000

В Python библиотека Pandas не проверяет значения по одному. Сравнение выполняется на более низком уровне (с помощью NumPy), в скомпилированном коде, по всему массиву.

Затем np.where() применяет метки за один эффективный проход.

Вот незаметное, но существенное изменение:

Вместо того чтобы спрашивать:

«Что мне делать с этим спором?»

Вы спрашиваете:

«Какое правило применяется к этой колонке?»

Вот где проходит грань между начинающими и профессиональными пандами.

В этот момент я подумал, что «перешёл на новый уровень». Но потом обнаружил, что могу сделать это ещё проще.

А потом я открыл для себя булево индексирование.

После замера времени векторизованной версии я почувствовал себя довольно гордым. Но затем меня осенило еще одно.

Для этого мне даже не нужен np.where() .

Вернемся к нашему небольшому набору данных:

 df = pd.DataFrame({ "product": ["A", "B", "C", "D", "E"], "sales": [500, 1200, 800, 2000, 300] })

Наша цель остается прежней:

Если объем продаж превышает 1000, пометьте каждую строку high , в противном случае — low .

С помощью np.where() мы написали:

 df["tier"] = np.where(df["sales"] > 1000, "high", "low")

Это чище и быстрее. Гораздо лучше, чем зацикливание.

Но вот что действительно изменило мое представление о Pandas:
Вот эта строчка…

 df["sales"] > 1000

…уже возвращает нечто невероятно полезное.

Давайте посмотрим:

Выход:

 0 False 1 True 2 False 3 True 4 False Name: sales, dtype: bool

Это логический ряд.

Pandas оценила состояние всего столбца сразу.

Нет циклов. Нет условий if . Нет построчной логики.

Программа сгенерировала полную маску значений True/False за один раз.

Булево индексирование ощущается как сверхспособность.

А вот тут начинается самое интересное.

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

 df[df["sales"] > 1000]

И Pandas мгновенно предоставляет вам:

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

 df["tier"] = "low" df.loc[df["sales"] > 1000, "tier"] = "high"

По сути, я говорю:

  • Предположим, что все показатели "low" .
  • Изменять значения следует только в тех строках, где объем продаж превышает 1000.

Вот и все.

И вдруг я перестаю думать:

«Для каждой строки проверьте значение…»

Я думаю:

«Начните с значения по умолчанию. Затем примените правило к подмножеству».

Этот сдвиг едва заметен, но он меняет всё.

Освоившись с булевыми масками, я начал задумываться:

Что произойдет, если логика не будет такой простой, как «больше 1000»? Что, если мне понадобятся пользовательские правила?

Именно там я открыл для себя apply() . И поначалу мне показалось, что это идеальное сочетание преимуществ обеих функций.

Разве apply() недостаточно хорош?

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

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

Естественно, я начал писать что-то подобное:

 df["tier"] = df["sales"].apply( lambda x: "high" if x > 1000 else "low" )

А что на первый взгляд?

Выглядит отлично.

  • Нет цикла for
  • Ручная индексация отсутствует
  • Легко читается

Создается впечатление, что это профессиональное решение.

Но вот чего я тогда не понимал:

apply() по-прежнему выполняет код Python для каждой отдельной строки.
Это просто скрывает цикл.

При использовании:

df["sales"].apply(lambda x: ...)

Pandas по-прежнему:

  • Взяв каждое значение
  • Передача его в функцию Python
  • Возвращаем результат
  • Повторяйте это для каждой строки.

Да, это чище, чем цикл for . Но с точки зрения производительности? Это гораздо ближе к циклу, чем к настоящей векторизации.

Это стало для меня своего рода откровением. Я понял, что заменяю видимые циклы невидимыми.

Итак, когда следует использовать apply() ?

  • Если логику можно выразить с помощью векторизованных операций, то следует использовать именно их.
  • Если это можно выразить с помощью булевых масок, сделайте это.
  • Если для этого абсолютно необходима собственная логика на Python, используйте apply() .
    Другими словами:

Сначала векторизуйте. Используйте apply()only в случае крайней необходимости.
Не потому, что apply() плохая функция. А потому что Pandas работает быстрее и чище, когда вы мыслите столбцами, а не построчными функциями.

Заключение

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

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

  • Построчный подход не масштабируется.
  • Скрытые циклы в Python не масштабируются.
  • Правила на уровне столбцов это делают.

Вот где проходит настоящая грань между использованием Pandas на уровне новичка и профессионала.

Итак, вкратце:

Прекратите спрашивать, что делать с каждой строкой. Начните спрашивать, какое правило применяется ко всему столбцу.

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

Ибрагим Салами. Все материалы от Ибрагима Салами.

Источник: towardsdatascience.com

Оцените материал:

Поделиться
Понравилась статья? Расскажите другим
ВКонтакте
Читайте также
Новости робототехники General Intuition собирает 320 миллионов долларов на использовании данных видеоигр для обучения роботов Архив рубрики ~Обо всем~ Основатель Xprize утверждает, что «люди ведут себя лучше, когда за ними наблюдают». Новости робототехники На фоне бурного роста числа роботов Amazon, Proteus прокладывает новый путь вперед. Новости робототехники Роботакси проезжают километры только для того, чтобы их помыли и зарядили; этот новый стартап хочет это исправить. Архив рубрики ~Коротко из Telegram~ В Кабардино-Балкарии готовят ИИ-видеонаблюдение RedVideo Учёные Кабардино-Балкарского госуниверситета им. Х.М…. Архив рубрики ~Коротко из Telegram~ Новый лидер в области искусственного интеллекта? SenseNovaAI — скоростная нейронная… Архив рубрики ~Коротко из Telegram~ Платформы превратят в КПП для бизнеса Правительство продолжает обвешивать закон… Архив рубрики ~Коротко из Telegram~ По итогам I квартала 2026 года численность работников ИТ-отрасли достигла… Архив рубрики ~Коротко из Telegram~ ☀️ Model Context Protocol (MCP) сделал ещё один шаг к… Архив рубрики ~Коротко из Telegram~ ⁉️ Разработчики представили технологию, которая позволяет голосовым AI-агентам определять эмоции… Архив рубрики ~Обо всем~ Обещать меньше, делать больше? Ознакомьтесь с автомобилем Slate стоимостью 24 950 долларов. Архив рубрики ~Идей копилка~ Мобильный сервис ремонта электроники на дому: как начать с нуля и зарабатывать 80–150 тысяч в месяц Новости робототехники Глубокое погружение в физический искусственный интеллект и стратегию робототехники. Рука с Дрю Генри. Архив рубрики ~Коротко из Telegram~ PlanitlyAI — ИИ который за секунды сгенерит план отпуска. Даете… Новости робототехники General Intuition собирает 320 миллионов долларов на использовании данных видеоигр для обучения роботов Архив рубрики ~Обо всем~ Основатель Xprize утверждает, что «люди ведут себя лучше, когда за ними наблюдают». Новости робототехники На фоне бурного роста числа роботов Amazon, Proteus прокладывает новый путь вперед. Новости робототехники Роботакси проезжают километры только для того, чтобы их помыли и зарядили; этот новый стартап хочет это исправить. Архив рубрики ~Коротко из Telegram~ В Кабардино-Балкарии готовят ИИ-видеонаблюдение RedVideo Учёные Кабардино-Балкарского госуниверситета им. Х.М…. Архив рубрики ~Коротко из Telegram~ Новый лидер в области искусственного интеллекта? SenseNovaAI — скоростная нейронная… Архив рубрики ~Коротко из Telegram~ Платформы превратят в КПП для бизнеса Правительство продолжает обвешивать закон… Архив рубрики ~Коротко из Telegram~ По итогам I квартала 2026 года численность работников ИТ-отрасли достигла… Архив рубрики ~Коротко из Telegram~ ☀️ Model Context Protocol (MCP) сделал ещё один шаг к… Архив рубрики ~Коротко из Telegram~ ⁉️ Разработчики представили технологию, которая позволяет голосовым AI-агентам определять эмоции… Архив рубрики ~Обо всем~ Обещать меньше, делать больше? Ознакомьтесь с автомобилем Slate стоимостью 24 950 долларов. Архив рубрики ~Идей копилка~ Мобильный сервис ремонта электроники на дому: как начать с нуля и зарабатывать 80–150 тысяч в месяц Новости робототехники Глубокое погружение в физический искусственный интеллект и стратегию робототехники. Рука с Дрю Генри. Архив рубрики ~Коротко из Telegram~ PlanitlyAI — ИИ который за секунды сгенерит план отпуска. Даете…

Оставить комментарий