2015-08-07 4 views
0

Я не могу найти способ уменьшить использование памяти для этой программы. Это моя самая эффективная реализация на сегодняшний день:Уменьшить использование памяти Pandas

columns = ['eventName', 'sessionId', "eventTime", "items", "currentPage", "browserType"] 
df = pd.DataFrame(columns=columns) 
l=[] 

for i, file in enumerate(glob.glob("*.log")): 
    print("Going through log file #%s named %s..." % (i+1, file)) 
    with open(file) as myfile: 
     l+=[json.loads(line) for line in myfile] 
     tempdata = pd.DataFrame(l) 
     for column in tempdata.columns: 
      if not column in columns: 
       try: 
        tempdata.drop(column, axis=1, inplace=True) 
       except ValueError: 
        print ("oh no! We've got a problem with %s column! It don't exist!" % (badcolumn)) 
     l = [] 
     df = df.append(tempdata, ignore_index = True) 
     # very slow version, but is most memory efficient 
     # length = len(df) 
     # length_temp = len(tempdata) 
     # for i in range(1, length_temp): 
     #  update_progress((i*100.0)/length_temp) 
     #  for column in columns: 
     #   df.at[length+i, column] = tempdata.at[i, column] 
     tempdata = 0 

print ("Data Frame initialized and filled! Now Sorting...") 
df.sort(columns=["sessionId", "eventTime"], inplace = True) 
print ("Done Sorting... Changing indices...") 
df.index = range(1, len(df)+1) 
print ("Storing in Pickles...") 
df.to_pickle('data.pkl') 

В основном, я читаю из лог-файлов JSON в панд dataframe, но функция Append является то, что является причиной проблемы. Он создает два разных объекта в памяти, что приводит к огромному использованию памяти. Кроме того, кажется, что метод .to_pickle для панд также является огромным болотом памяти, потому что самый большой всплеск в памяти - это запись в рассол. Есть ли простой способ уменьшить память? Прокомментированный код выполняет эту работу, но занимает 100-1000 раз. В настоящее время я использую 45% использования памяти при макс. Во время части .to_pickle, 30% во время чтения журналов. Но чем больше журналов, тем выше число. Спасибо за вашу помощь,

Бест, F

+0

Поиск "Inplace панда Append", я нашел это: http://stackoverflow.com/questions/18196616/append-rows-to-a-pandas-dataframe-without-making-a-new-copy – satoru

+0

Я видел это, но мой вопрос многогранен; почему часть .to_pickle занимает столько памяти !? Кроме того, если есть способ сделать это без .append, как и моя вторая медленная, но более эффективная с точки зрения памяти попытка? – furby559

ответ

2

Если вам нужно построить DataFrame вверх из кусочков, как правило, гораздо более эффективным для построения списка кадров компонентов и объединить их в один шаг, используя concat. См. Первый подход ниже.

# df = 10 rows of dummy data 

In [10]: %%time 
    ...: dfs = [] 
    ...: for _ in xrange(1000): 
    ...:  dfs.append(df) 
    ...: df_concat = pd.concat(dfs, ignore_index=True) 
    ...: 
Wall time: 42 ms 

In [11]: %%time 
    ...: df_append = pd.DataFrame(columns=df.columns) 
    ...: for _ in xrange(1000): 
    ...:  df_append = df_append.append(df, ignore_index=True) 
    ...: 
Wall time: 915 ms 
1

Этого ответ для общего панда оптимизации использования dataFrame памяти:

  1. панда нагрузка в строке столбцов как объекта типа по умолчанию. Для всех столбцов, которые имеют объект типа , пытаются присвоить тип категории к этим столбцам, передавая словарь в параметр dtypes из read_csv функции. Использование памяти значительно сокращается для столбцов с 50% или менее уникальными значениями.

  2. Pandas читает в числовых столбцах как float64 по умолчанию. Используйте pd.to_numeric to downcast float64 тип до 32 или 16, если возможно. Это снова избавит вас от памяти.

  3. Загрузить данные csv кусок на куске. Обработайте его и перейдите к следующему куску. Это можно сделать, указав значение в параметр chunk_size параметра read_csv.

Смежные вопросы