2016-08-24 1 views
1

Ich benutze Folium und Bokeh zusammen in einem Jupyter-Notebook. Ich durchlaufe einen Datenrahmen und füge für jede Zeile einen Marker in die Folium-Map ein, ziehe einige Daten aus einem separaten Datenrahmen, erstelle ein Bokeh-Diagramm aus diesen Daten und bette das Bokeh-Diagramm dann in das Folium-Map-Popup ein IFrame. Der Code lautet wie folgt:Folium + Bokeh: Schlechte Performance und enormer Speicherverbrauch

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 

Diese Schleife läuft extrem langsam und fügt ca. 200 MB an die Speicherauslastung des zugehörigen Python 3.5-Prozesses, pro Durchlauf der Schleife! In der Tat, nach dem Ausführen der Schleife ein paar Mal mein gesamtes Macbook verlangsamt sich zu einem Crawl - sogar die Maus ist nacheilend. Auch beim Scrollen und Zoomen ist die zugehörige Karte stark verzögert und die Popups sind langsam zu öffnen. Für den Fall, dass es nicht offensichtlich ist, bin ich ziemlich neu in der Welt der Python-Analyse und der Web-Visualisierung, also ist hier vielleicht etwas sehr ineffektiv.

Ich frage mich, warum das so ist und ob es einen besseren Weg gibt, Bokeh-Charts in den Karten-Popups erscheinen zu lassen. Aus einigen grundlegenden Experimenten, die ich getan habe, scheint es nicht, dass das Problem mit den Aufrufen zu Bar ist - die Speicherauslastung scheint wirklich in die Höhe schnellen, wenn ich Anrufe an file_html und nur schlimmer als Anrufe an folium.element.IFrame hinzugefügt werden. Scheint so, als gäbe es eine Art Speicherleck wegen der zunehmenden Speicherauslastung beim erneuten Ausführen desselben Codes.

Wenn jemand Ideen hat, wie man denselben Effekt erzielen kann (Bokeh-Diagramme öffnen sich, wenn man einen Folium-Marker anklickt), würde ich es sehr schätzen!

aktualisiert folgende einige Experimente

Ich habe für Schritt durch den Schleifenschritt laufe und beobachteten Veränderungen in der Speichernutzung als weitere Schritte in hinzugefügt werden, um zu versuchen und zu isolieren, welches Stück Code dieses Problem fährt. Auf der Bokeh-Seite scheint der größte Übeltäter die Aufrufe an file_html() zu sein - wenn die Schleife durch diesen Schritt ausgeführt wird, fügt sie dem zugeordneten python 3.5-Prozess pro Lauf (der Schleife erstellt 18 Diagramme) etwa 5 MB Speicherbelegung hinzu, auch wenn sie enthalten ist bokeh.io.curdoc().clear().

Das größere Problem scheint jedoch von Folium getrieben zu werden. Das Ausführen der gesamten Schleife einschließlich der Erstellung der Folium IFrames mit dem Bokeh-generierten HTML und den mit den IFrames verknüpften Map-Markern erhöht die Speicherauslastung des Python-Prozesses pro Lauf um 25-30mb.

Also, ich schätze, das ist eher eine Folium-Frage. Warum ist diese Struktur so speicherintensiv und gibt es einen besseren Weg? Übrigens, das Speichern der resultierenden Folium-Map als HTML-Datei mit map.save('map.html') erzeugt eine riesige 22-MB-HTML-Datei.

Antwort

0

Es gibt viele verschiedene Anwendungsfälle, und einige von ihnen kommen mit unvermeidlichen Kompromissen. Um einige andere Anwendungsfälle sehr einfach und bequem zu machen, hat Bokeh ein implizites "aktuelles Dokument" und sammelt dort Dinge an. Für den speziellen Anwendungsfall, eine Reihe von Plots sequentiell in einer Schleife zu erzeugen, möchten Sie bokeh.io.reset_output() dazwischen aufrufen, um diese Akkumulation zu verhindern.

+0

Danke für den Hinweis - aber das löst das Problem nicht vollständig. Auf der Bokeh-Seite scheint, basierend auf einigen Tests, das Erstellen der Charts selbst nicht zu viel Speicher zu benötigen (ich mache nur 18 mit dieser Schleife). es scheint, dass die Aufrufe von 'file_html()' jedoch Speicherauslastung hinzufügen, die jedoch nicht von 'bokeh.io.curdoc(). clear()' gelöscht wird. Gibt es einen besseren Weg, den zugrunde liegenden HTML-Code aus Bokeh-Charts zu erhalten? Wie auch immer, ich werde meine Frage bearbeiten, weil das Problem jetzt eher von Folium als von Bokeh bestimmt wird. –

+0

Es gibt auch 'bokeh.io.reset_output()', das wahrscheinlich in dieser Art von Szenario wahrscheinlich umfassender ist.Ich habe die Antwort aktualisiert. – bigreddot