Kako i zašto sam koristio Plotly (umjesto D3) za vizualizaciju svojih podataka Lollapalooze

D3.js je sjajna JavaScript knjižnica, ali ima vrlo strmu krivulju učenja. To zadaću izgradnje vrijedne vizualizacije čini nečim za što je potrebno puno truda. Ovaj dodatni napor je u redu ako vam je cilj napraviti novu i kreativnu vizualizaciju podataka, ali često to nije slučaj.

Često vam cilj može biti samo izgradnja interaktivne vizualizacije s nekim dobro poznatim tablicama . A ako niste inženjer, to može postati malo nezgodno.

Kao znanstvenici podataka, jedan od naših glavnih zadataka je manipulacija podacima. Danas je glavni alat koji za to koristim Pande (Python). Što ako ti kažem da si mogu graditi neke lijepe i interaktivnih karata za web izravno iz Vašeg pande dataframes ? Pa možete! Za to možemo koristiti Plotly .

Za zapisnik, postoje i Plotly API knjižnice za Matlab, R i JavaScript, ali ovdje ćemo se držati Python biblioteke.

Da budemo pošteni, Plotly je izgrađen na vrhu d3.js (i stack.gl). Glavna razlika između D3 i Plotly je u tome što je Plotly posebno knjižnica grafikona .

Izgradimo trakasti grafikon kako bismo upoznali kako Plotly radi.

Izrada stupčastog grafikona s plotnim

U Plotlyjevoj filozofiji postoje 3 glavna koncepta:

  • Podaci
  • Izgled
  • Lik

Podaci

Objekt Data definira što želimo prikazati na grafikonu (odnosno podatke). Definiramo zbirku podataka i specifikacije kako bismo ih prikazali kao trag . Predmet podataka može imati mnogo tragova. Zamislite linijski grafikon s dvije linije koje predstavljaju dvije različite kategorije: svaka linija je trag.

Izgled

Objekt Layout definira značajke koje nisu povezane s podacima (poput naslova, naslova osi i tako dalje). Layout također možemo koristiti za dodavanje napomena i oblika na grafikon.

Lik

Objekt Figure stvara konačni objekt za crtanje. To je objekt koji sadrži i podatke i izgled.

Iscrtane vizualizacije grade se pomoću plotly.js. To znači da je Python API samo paket za interakciju s knjižnicom plotly.js . plotly.graph_objsModul sadrži funkcije koje će generirati objekte nacrta za nas.

Ok, sada smo spremni za izgradnju trakastog grafikona:

import plotly.graph_objs as goimport pandas as pdimport plotly.offline as offline
df = pd.read_csv("data.csv")
df_purchases_by_type = df.pivot_table( index = "place", columns = "date", values = "price", aggfunc = "sum" ).fillna(0)
trace_microbar = go.Bar( x = df_purchases_by_type.columns, y = df_purchases_by_type.loc["MICROBAR"])
data = [trace_microbar]
layout = go.Layout(title = "Purchases by place", showlegend = True)
figure = go.Figure(data = data, layout = layout)
offline.plot(figure)

Napomena: u ovom članku nećemo govoriti o tome što radim s okvirima podataka. Ali ako želite post o tome, javite mi u komentarima?

U redu, prvo želimo prikazati trake jedne kategorije (mjesto zvano "MICROBAR"). Tako kreiramo podatkovni objekt (popis) s go.Bar()(tragom) koji specificira podatke za osi x i y. Trace je rječnik, a podaci su popis rječnika. Evo trace_microbarsadržaja (obratite pažnju na tipku tipke):

{'type': 'bar', 'x': Index(['23/03/2018', '24/03/2018', '25/03/2018'], dtype="object", name="date"), 'y': date 23/03/2018 0.0 24/03/2018 0.0 25/03/2018 56.0 Name: MICROBAR, dtype: float64}

U objektu Layout postavljamo naslov grafikona i parametar showlegend. Zatim umotamo podatke i izgled u sliku i pozivamo plotly.offline.plot()za prikaz grafikona. Plotly ima različite mogućnosti za prikaz ljestvica, ali ovdje ćemo se držati izvanmrežne opcije. Ovo će otvoriti prozor preglednika s našim grafikonom.

Želim sve prikazati na naslaganom trakasti grafikonu, pa ćemo stvoriti popis podataka sa svim tragovima (mjestima) koja želimo prikazati i postaviti barmodeparametar na stog .

import plotly.graph_objs as goimport pandas as pdimport plotly.offline as offline
df = pd.read_csv("data.csv")
df_purchases_by_place = df.pivot_table(index="place",columns="date",values="price",aggfunc="sum").fillna(0)
data = []
for index,place in df_purchases_by_place.iterrows(): trace = go.Bar( x = df_purchases_by_place.columns, y = place, name=index ) data.append(trace)
layout = go.Layout(, showlegend=True, barmode="stack" )
figure = go.Figure(data=data, layout=layout)
offline.plot(figure)

I to je osnova Plotlyja. Da bismo prilagodili naše grafikone, postavili smo različite parametre za tragove i izgled. Ajmo sada razgovarati o vizualizaciji Lollapalooze.

Moje iskustvo Lollapalooze

Za izdanje Lollapalooza Brazil iz 2018. sve su kupnje obavljene putem narukvice s omogućenim RFID-om. Oni šalju podatke na vašu adresu e-pošte, pa sam ih odlučio pogledati. Što možemo naučiti o meni i mojem iskustvu analizirajući kupnje koje sam obavio na festivalu?

Podaci izgledaju ovako:

  • Datum kupnje
  • sat kupovine
  • proizvod
  • količina
  • pozornica
  • mjesto gdje sam obavio kupnju

Na temelju tih podataka, odgovorimo na neka pitanja.

Kamo sam otišao tijekom festivala?

Podaci nam govore samo ime mjesta na kojem sam obavio kupnju, a festival se održao u Autódromo de Interlagos. Odavde sam uzeo kartu s etapama i upotrijebio alat za georeferenciranje s georeference.com kako bih dobio koordinate zemljopisne širine i dužine za faze.

We need to display a map and the markers for each purchase, so we will use Mapbox and the scattermapbox trace. First let’s plot only the stages to see how this works:

import plotly.graph_objs as goimport plotly.offline as offlineimport pandas as pd
mapbox_token = "" #//www.mapbox.com/help/define-access-token/
df = pd.read_csv("stages.csv")
trace = go.Scattermapbox( lat = df["latitude"], lon = df["longitude"], text=df["stage"], marker=go.Marker(size=10), mode="markers+text", textposition="top" )
data = [trace]
layout = go.Layout( mapbox=dict( accesstoken=mapbox_token, center=dict( lat = -23.701057, lon = -46.6970635 ), zoom=14.5 ) )
figure = go.Figure(data = data, layout = layout)
offline.plot(figure)

Let’s learn a new Layout parameter: updatemenus. We will use this to display the markers by date. There are four possible update methods:

  • "restyle": modify data or data attributes
  • "relayout": modify layout attributes
  • "update": modify data and layout attributes
  • "animate": start or pause an animation)

To update the markers, we only need to modify the data, so we will use the "restyle" method. When restyling you can set the changes for each trace or for all traces. Here we set each trace to be visible only when the user changes the dropdown menu option:

import plotly.graph_objs as goimport plotly.offline as offlineimport pandas as pdimport numpy as np
mapbox_token = ""
df = pd.read_csv("data.csv")
df_markers = df.groupby(["latitude","longitude","date"]).agg(dict(product = lambda x: "%s" % ", ".join(x), hour = lambda x: "%s" % ", ".join(x)))df_markers.reset_index(inplace=True)
data = []update_buttons = []
dates = np.unique(df_markers["date"])
for i,date in enumerate(dates): df_markers_date = df_markers[df_markers["date"] == date] trace = go.Scattermapbox( lat = df_markers_date["latitude"], lon = df_markers_date["longitude"], name = date, text=df_markers_date["product"]+"

"+df_markers_date["hour"], visible=False ) data.append(trace)

 visible_traces = np.full(len(dates), False) visible_traces[i] = True
 button = dict( label=date, method="restyle", args=[dict(visible = visible_traces)] ) update_buttons.append(button)
updatemenus = [dict(active=-1, buttons = update_buttons)]
layout = go.Layout( mapbox=dict( accesstoken=mapbox_token, center=dict( lat = -23.701057, lon = -46.6970635), zoom=14.5), updatemenus=updatemenus )
figure = go.Figure(data = data, layout = layout)
offline.plot(figure)

How did I spend my money?

To answer that, I created a bar chart with my spendings for food and beverage by each day and built a heatmap to show when I bought stuff. We already saw how to build a bar chart, so now let’s build a heatmap chart:

import plotly.graph_objs as goimport pandas as pdimport plotly.offline as offline
df = pd.read_csv("data.csv")
df_purchases_by_type = df.pivot_table(index="place",columns="date",values="price",aggfunc="sum").fillna(0)df["hour_int"] = pd.to_datetime(df["hour"], format="%H:%M", errors="coerce").apply(lambda x: int(x.hour))
df_heatmap = df.pivot_table(index="date",values="price",columns="hour", aggfunc="sum").fillna(0)
trace_heatmap = go.Heatmap( x = df_heatmap.columns, y = df_heatmap.index, z = [df_heatmap.iloc[0], df_heatmap.iloc[1], df_heatmap.iloc[2]] )
data = [trace_heatmap]
layout = go.Layout(title="Purchases by place", showlegend=True)
figure = go.Figure(data=data, layout=layout)
offline.plot(figure)

Which concerts did I watch?

Now let’s go to the coolest part: could I guess the concerts I attended based only on my purchases?

Ideally, when we are watching a show, we are watching the show (and not buying stuff), so the purchases should be made before or after each concert. I then made a list of each concert happening one hour before, one hour after, and according to the time the purchase was made.

Da bih saznao kojoj sam od ovih emisija prisustvovao, izračunao sam udaljenost od mjesta kupnje do svake faze. Emisije kojima sam prisustvovao trebale bi biti one s najkraćom udaljenostom do koncesija.

Kako želimo prikazati svaku podatkovnu točku, najbolji izbor za vizualizaciju je tablica. Izgradimo jedan:

import plotly.graph_objs as goimport plotly.offline as offlineimport pandas as pd
df_table = pd.read_csv("concerts_I_attended.csv")
def colorFont(x): if x == "Yes": return "rgb(0,0,9)" else: return "rgb(178,178,178)"
df_table["color"] = df_table["correct"].apply(lambda x: colorFont(x))
trace_table = go.Table( header=dict( values=["Concert","Date","Correct?"], fill=dict( color=("rgb(82,187,47)")) ), cells=dict( values= [df_table.concert,df_table.date,df_table.correct], font=dict(color=([df_table.color]))) )
data = [trace_table]
figure = go.Figure(data = data)
offline.plot(figure)

Tri koncerta su nedostajala, a četiri su bila netočna, što nam daje preciznost od 67%, a opoziv od 72%.

Sve zajedno: crtica

Imamo sve ljestvice, ali cilj je staviti ih sve na stranicu. Da bismo to učinili, koristit ćemo crticu (Plotly).

„Crtica je Python okvir za izgradnju analitičkih web aplikacija. Nije potreban JavaScript. Dash je idealan za izgradnju aplikacija za vizualizaciju podataka s vrlo prilagođenim korisničkim sučeljima u čistom Pythonu. To je posebno pogodno za sve koji rade s podacima u Pythonu. " - Plotlyjeva stranica

Dash is written on top of Flask, Plotly.js, and React.js. It works in a very similar way to the way we create Plotly charts:

import dashimport dash_core_components as dccimport dash_html_components as htmlimport plotly.graph_objs as goimport pandas as pd app = dash.Dash()
df_table = pd.read_csv("concerts_I_attended.csv").dropna(subset=["concert"])def colorFont(x): if x == "Yes": return "rgb(0,0,9)" else: return "rgb(178,178,178)"
df_table["color"] = df_table["correct"].apply(lambda x: colorFont(x))
trace_table = go.Table(header=dict(values=["Concert","Date","Correct?"],fill=dict(color=("rgb(82,187,47)"))),cells=dict(values=[df_table.concert,df_table.date,df_table.correct],font=dict(color=([df_table.color]))))
data_table = [trace_table]
app.layout = html.Div(children=[ html.Div( [ dcc.Markdown( """ ## My experience at Lollapalooza Brazil 2018 *** """.replace(' ', ''), className="eight columns offset-by-two" ) ], className="row", style=dict(textAlign="center",marginBottom="15px") ),
html.Div([ html.Div([ html.H5('Which concerts did I attend?', style=dict(textAlign="center")), html.Div('People usually buy things before or after a concert, so I took the list of concerts, got the distances from the location of the purchases to the stages and tried to guess which concerts did I attend. 8 concerts were correct and 3 were missing from a total of 12 concerts.', style=dict(textAlign="center")), dcc.Graph(id='table', figure=go.Figure(data=data_table,layout=go.Layout(margin=dict(t=30)))), ], className="twelve columns"), ], className="row")])
app.css.append_css({ 'external_url': '//codepen.io/chriddyp/pen/bWLwgP.css'})
if __name__ == '__main__': app.run_server(debug=True)

Cool right?

I hosted the final visualization here and the all the code is here.

There are some alternatives to hosting the visualizations: Dash has a public dash app hosting and Plotly also provides a web-service for hosting graphs.

Did you found this article helpful? I try my best to write a deep dive article each month, you can receive an email when I publish a new one.

I had a pretty good experience with Plotly, I’ll definitely use it for my next project. What are your thoughts about it after this overview? And what other tools do you use to build visualizations for the web? Share them in the comments! And thank you for reading! ?