Введение

Если вы занимаетесь решением проблем науки о данных и/или машинного обучения с помощью Python, вы, вероятно, сталкивались с Pandas, одним из наиболее распространенных пакетов для анализа данных и обработки данных для Python.

Pandas хранит данные в форме, называемой DataFrame, которая представляет собой двумерную структуру данных (например, двумерный массив), которая может содержать данные в различных форматах (числовые данные, категориальные переменные и т. д.).

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

Совет № 1: приведите категориальные переменные

Предположим, мы заполняем столбец pandas с именем color 1000 значений, которые случайным образом выбираются массивом, содержащим 6 различных значений («БЕЛЫЙ», «ЧЕРНЫЙ», «КРАСНЫЙ», «ЖЕЛТЫЙ», «СИНИЙ» и «ЗЕЛЕНЫЙ»).

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

Следующий код напечатает типы данных столбца, который мы только что определили, а также «отпечаток памяти» фрейма данных.

После запуска приведенного выше кода мы получаем результаты, показанные на следующем снимке экрана. Pandas присвоил столбцу тип данных object по умолчанию, и столбец использует около 60,4 КБ памяти.

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

Мы снова запускаем код и видим следующие результаты.

Чтоаааааааааааааааааааааа? Удивительно, но с помощью этого простого изменения нам удалось уменьшить размер нашего фрейма данных в памяти примерно на 97%.

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

Тем не менее, нет никакой гарантии уменьшения объема памяти, поскольку основным фактором, влияющим на эту оптимизацию, является количество элементов обрабатываемой переменной.

Примечание. Мощность — это количество различных значений, которые может принимать категориальная переменная (в нашем примере переменная color может принимать только 6 различных значений, поэтому ее мощность равна 6).

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

Совет № 2: Приведите переменные к типу bool (частный случай совета № 1)

Много раз в наборе данных мы можем найти «категориальные» столбцы, которые принимают только 2 дискретных значения, например «ДА» и «НЕТ» или «мужской» и «женский», и по умолчанию эти значения будут рассматриваться пандами как objects. Итак, этот совет посвящен частному случаю первого совета. Но на этот раз мы не будем приводить эти значения к category, а сопоставим их с логическими значениями (True/False). Поскольку я не вижу смысла в повторных вычислениях для этого случая, я уверен, что вы понимаете, что этот шаг окажет значительное положительное влияние на объем памяти столбца с упомянутой выше характеристикой.

Итак, предполагая, что столбец со строковыми значениями называется coin_toss и что этот столбец содержит только значения HEAD и TAILS , мы можем преобразовать столбец в логическое значение, используя код, показанный ниже.

Совет № 3: По возможности уменьшайте целые числа

Теперь предположим, что мы хотим сохранить в столбце фрейма данных pandas возраст 1000 человек. Мы заполним столбец, выбрав случайным образом целые числа в диапазоне [0,120] (поскольку возраст всегда неотрицательный, и в этом контексте крайне маловероятно наблюдать значения больше 120).

Следующий фрагмент выполняет все описанные выше действия, а затем печатает тип данных столбца и объем памяти, занимаемый набором данных.

Когда мы запускаем код, мы видим, что по умолчанию панды выбрали int64 в качестве типа данных для этого столбца, а общий объем памяти столбца составляет около 7,9 КБ.

На этом этапе давайте вспомним, что тип данных int64 может хранить до 2⁶⁴ различных значений, в то время как нам нужно хранить только 120 значений(‹ 2⁸) , которые можно безопасно хранить в 8-битном целое число. На практике это означает, что около 64 — 8 = 56 бит на строку будут совершенно бесполезны в нашем сценарии. Как вы, наверное, понимаете, это ОГРОМНАЯ трата памяти, и теперь мы посмотрим, как этого избежать.

Теперь мы понижаем этот столбец до int8 и снова печатаем объем памяти, занимаемый фреймом данных.

Ура! Понизив значение столбца до int8, нам удалось уменьшить объем памяти почти до 1/8 от предыдущей настройки.

Заключение

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