Обычно данные для анализа довольно большого объема сами по себе и при загрузке занимают от сотен мегабайт до гигабайт. Помимо этого при загрузке данных в dataframe (pandas) числовые значения не всегда получают наиболее подходящие типы, например вместо int8 назначается тип int64 из-за чего объем используемой под dataframe памяти существенно возрастает.
Приведенная в статье функция позволит быстро переопределить указанные типы в случае такой возможности и в некоторых случаях существенно сократить размер памяти под dataframe.
Далее сама функция и пример применения.
In [25]:
import pandas as pd
import numpy as np
In [26]:
def optimize_memory_usage(df, print_size=True):
# Function optimizes memory usage in dataframe.
# (RU) Функция оптимизации типов в dataframe.
# Types for optimization.
# Типы, которые будем проверять на оптимизацию.
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
# Memory usage size before optimize (Mb).
# (RU) Размер занимаемой памяти до оптимизации (в Мб).
before_size = df.memory_usage().sum() / 1024**2
for column in df.columns:
column_type = df[column].dtypes
if column_type in numerics:
column_min = df[column].min()
column_max = df[column].max()
if str(column_type).startswith('int'):
if column_min > np.iinfo(np.int8).min and column_max < np.iinfo(np.int8).max:
df[column] = df[column].astype(np.int8)
elif column_min > np.iinfo(np.int16).min and column_max < np.iinfo(np.int16).max:
df[column] = df[column].astype(np.int16)
elif column_min > np.iinfo(np.int32).min and column_max < np.iinfo(np.int32).max:
df[column] = df[column].astype(np.int32)
elif column_min > np.iinfo(np.int64).min and column_max < np.iinfo(np.int64).max:
df[column] = df[column].astype(np.int64)
else:
if column_min > np.finfo(np.float32).min and column_max < np.finfo(np.float32).max:
df[column] = df[column].astype(np.float32)
else:
df[column] = df[column].astype(np.float64)
# Memory usage size after optimize (Mb).
# (RU) Размер занимаемой памяти после оптимизации (в Мб).
after_size = df.memory_usage().sum() / 1024**2
if print_size: print('Memory usage size: before {:5.4f} Mb - after {:5.4f} Mb ({:.1f}%).'.format(before_size, after_size, 100 * (before_size - after_size) / before_size))
return df
In [30]:
def import_data_from_csv(filePath):
# Load a dataframe from csv-file and optimize its memory usage.
# (RU) Загрузка данных из csv-файла и оптимизация числовых типов для оптимизации использования памяти
df = pd.read_csv(filePath, parse_dates=True, keep_date_col=True)
# Show dataframe info before optimize.
# (RU) Показать информацию о таблице до оптимизации.
print('-' * 80)
print(df.info())
print('-' * 80)
# (RU) Оптимизация типов в dataframe.
df = optimize_memory_usage(df)
# Show dataframe info after optimize.
# (RU) Показать информацию о таблице после оптимизации.
print('-' * 80)
print(df.info())
print('-' * 80)
return df
In [31]:
df = import_data_from_csv('data.csv')
In [32]:
df.head()
Out[32]:
Видно, что при загрузке dataframe были назначены типы - float64(1) и int64(2), а после оптимизации они преобразованы в float32(1), int16(1) и int8(1).
Если Вам понравилась статья, пожалуйста, поставьте лайк, сделайте репост или оставьте комментарий. Если у Вас есть какие-либо замечания, также пишите комментарии.
Очень полезно, спасибо!
ОтветитьУдалить