Folium + Bokeh: низкая производительность и большое использование памяти

Я использую Folium и Bokeh вместе в блокноте Jupyter. Я перебираю фрейм данных, и для каждой строки вставляю маркер на карту Фолиума, извлекаю некоторые данные из отдельного фрейма данных, создаю диаграмму Боке из этих данных и затем встраиваю диаграмму Боке во всплывающее окно карты Фолиума в IFrame. Код выглядит следующим образом:

map = folium.Map(location=[36.710021, 35.086146],zoom_start=6)

for i in range (0,len(duty_station_totals)):

    popup_table = station_dept_totals.loc[station_dept_totals['Duty Station'] == duty_station_totals.iloc[i,0]]

    chart = Bar(popup_table,label=CatAttr(columns=['Department / Program'],sort=False),values='dept_totals',
               title=duty_station_totals.iloc[i,0] + ' Staff',xlabel='Department / Program',ylabel='Staff',plot_width=350,plot_height=350)

    hover = HoverTool(point_policy='follow_mouse')
    hover.tooltips=[('Staff','@height'),('Department / Program','@{Department / Program}'),('Duty Station',duty_station_totals.iloc[i,0])]
    chart.add_tools(hover)

    html = file_html(chart, INLINE, "my plot")

    iframe = folium.element.IFrame(html=html, width=400, height=400)

    popup = folium.Popup(iframe, max_width=400)

    marker = folium.CircleMarker(duty_station_totals.iloc[i,2],
                                radius=duty_station_totals.iloc[i,1] * 150,
                                color=duty_station_totals.iloc[i,3],
                                fill_color=duty_station_totals.iloc[i,3])

    marker.add_to(map)

    folium.Marker(duty_station_totals.iloc[i,2],icon=folium.Icon(color='black',icon_color=duty_station_totals.iloc[i,3]),popup=popup).add_to(map)


map

Этот цикл работает очень медленно и добавляет прибл. 200 МБ на использование памяти связанного процесса python 3.5 за цикл! Фактически, после запуска цикла пару раз весь мой macbook замедляется до ползучести - даже мышь отстает. Связанная карта также сильно запаздывает при прокрутке и масштабировании, и всплывающие окна открываются медленно. В случае, если это не очевидно, я довольно новичок в мире аналитики Python и веб-визуализации, так что, возможно, здесь есть что-то явно неэффективное.

Мне интересно, почему это так и есть ли лучший способ отображения диаграмм Боке во всплывающих окнах карты. Из некоторых базовых экспериментов, которые я провел, не похоже, что проблема заключается в вызовах Bar - использование памяти, кажется, действительно стремительно растет, когда я включаю звонки file_html и только хуже, как звонки folium.element.IFrame добавлены. Похоже, что происходит утечка памяти из-за увеличения использования памяти при повторном запуске того же кода.

Если у кого-то есть идеи относительно того, как добиться того же эффекта (открытие диаграмм Боке при нажатии на маркер Фолиума) более эффективным способом, я был бы очень признателен!

Обновление после некоторых экспериментов

Я шаг за шагом проходил цикл и наблюдал за изменениями в использовании памяти, поскольку добавлялось больше шагов, чтобы попытаться определить, какой фрагмент кода вызывает эту проблему. На стороне Боке, самый большой виновник, кажется, призывы к file_html() - при выполнении цикла через этот шаг он добавляет около 5 МБ использования памяти к связанному процессу Python 3.5 за цикл (цикл создает 18 диаграмм), даже если bokeh.io.curdoc().clear(),

Однако, по-видимому, большая проблема связана с Folium. выполнение всего цикла, включая создание IFrames для Folium с HTML-кодом, сгенерированным Bokeh, и маркеры карты, связанные с IFrames, увеличивают использование памяти процесса Python на 25–30 Мб за цикл.

Итак, я думаю, что это переходит к большему количеству вопросов Фолиума. Почему эта структура так интенсивно использует память и есть ли лучший способ? Кстати, сохранение полученной карты Folium в виде файла HTML с map.save('map.html') создает огромный, 22 МБ HTML-файл.

1 ответ

Есть много разных вариантов использования, и некоторые из них идут с неизбежными компромиссами. Чтобы сделать некоторые другие варианты использования очень простыми и удобными, Bokeh имеет скрытый "текущий документ" и продолжает накапливать там вещи. Для конкретного случая последовательного создания группы графиков в цикле, вы захотите вызвать bokeh.io.reset_output() между каждым, чтобы предотвратить это накопление.

Другие вопросы по тегам