Введение
Если вы занимаетесь решением проблем науки о данных и/или машинного обучения с помощью 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 играет важную роль в производительности современного программного решения. Как показано в этой статье, небольшие оптимизации, которые можно легко реализовать безопасным и надежным способом, могут существенно повысить общую производительность.