Ошибка памяти в функции стека Pandas для кадра данных ~ 200 кБ (700 x 60) - PullRequest
0 голосов
/ 10 февраля 2020

Я получаю MemoryError за наложение Pandas MultiIndexed / MultiColumned DataFrame, который я бы посчитал разумным размером. Пожалуйста, посмотрите пример воспроизводимой ошибки внизу вопроса. Ошибка возникает для размера около 700 x 60, но не возникает для кадра данных 700 x 50 и занимает около 3 с. Размеры DF меньше 0,4 МБ. Я заметил, что укладка DataFrame увеличивает размер примерно в 10 раз. Ниже приводятся некоторые выдержки из сообщения об ошибке для различных измерений DataFrame.

Кто-нибудь сталкивался с этим? Мне кажется, что размер DataFrame достаточно маленький.

При 700 x 60

  File "C:\Python27\lib\site-packages\pandas\core\reshape\reshape.py", line 517, in stack
    new_values = frame.values.ravel()
MemoryError

При 700 x 80

    return self._getbool_axis(key, axis=axis)
  File "C:\Python27\lib\site-packages\pandas\core\indexing.py", line 1520, in _getbool_axis
    raise self._exception(detail)
KeyError: MemoryError()

Минимальный рабочий пример

import sys
import time

import numpy as np
import pandas as pd

n_cols = 700   # dimensions for dataframe
n_rows = 60    # works for 50, error for ~  > 60

data = np.random.rand(n_rows,n_cols)

cols = zip(range(n_cols), [str(n) for n in range(n_cols)])  # some arbitrary columns
inds = zip(range(n_rows), [str(n) for n in range(n_rows)])  # "  "           indexes

ind_names=['intI', 'strI']  # labels for cols
col_names=['intC', 'strC']  # " "        inds

index = pd.MultiIndex.from_tuples(inds, names=ind_names)
columns = pd.MultiIndex.from_tuples(cols, names=col_names)

df = pd.DataFrame(data=data, index=index, columns=columns)  # put together a df

print(str(sys.getsizeof(df)/1000000.)+' MB')  # size before stacking

time_start = time.time()
# line below causes MemoryError if dimensions are too big
df = df.stack(level=list(range(df.columns.nlevels))).rename('value').reset_index()  # increases size
# df = df.reset_index()  # barely changes df size, very quick
print(str(sys.getsizeof(df)/1000000.)+' MB')  # size after stacking
print(time.time() - time_start)  # time to stack it
...