Сократите использование памяти Pandas Concat для большого количества данных. - PullRequest
1 голос
/ 08 июня 2019

У меня есть куча (15 000+) маленьких фреймов данных, которые мне нужно объединить по столбцам, чтобы сделать один очень большой (100 000x1000) фрейм данных в пандах.У меня есть две (очевидные) проблемы: скорость и использование памяти.

Ниже приведена одна методология, которую я высоко оценил при переполнении стека.

dfList = [df1, df2, ..., df15000] #made by appending in a for loop
df_out = pd.concat(dfList, axis=1)

Это здорово для скорости,Это простой код, который легко понять.Тем не менее, он использует довольно большой объем памяти.Насколько я понимаю, функция Pandas concat работает, создавая новый большой фрейм данных, а затем копируя всю информацию, существенно удваивая объем памяти, потребляемой программой.

Как избежать таких больших накладных расходов памятис минимальным снижением скорости?

Я пытался просто добавлять столбцы один за другим к первому df в цикле for.Отлично подходит для памяти (1 + 1/15 000), ужасно для скорости.

Тогда я придумал следующее.Я заменяю список на deque и делаю конкатенацию в остальном.Он экономит память (4,1 ГБ против 5,4 ГБ при последнем запуске) при управляемом снижении скорости (здесь добавлено <30 секунд для сценария общей длины 5-6 минут), но я не могу понять, <strong>почему сохраняет ли это память?

dfDq = collections.deque()
#add all 15,000 dfs to deque
while(len(dfDq)>2):  
    dfDq.appendleft(pd.concat([dfDq.pop(), dfDq.pop(), dfDq.pop()], axis=1))
if(len(dfDq)==2): df_out = pd.concat([dfDq.pop(), dfDq.pop()], axis=1)
else: df_out=dfDq.pop()

Последний шаг этой конкатенации по-прежнему должен использовать в 2 раза больше памяти, если я правильно понимаю функцию pd.concat().Что делает эту работу?Хотя приведенные выше числа для увеличения скорости и экономии памяти относятся только к одному прогону, общая тенденция была одинаковой для многочисленных прогонов.

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

1 Ответ

1 голос
/ 08 июня 2019

Просто создайте полноразмерный DataFrame заранее:

df = pd.DataFrame(index=np.arange(0, N), columns=[...])

Тогда пишите в разделы:

col = 0
for path in paths:
    part = pd.read_csv(path)
    df.iloc[:,col:col+part.shape[1]] = part
    col += part.shape[1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...