Πώς και γιατί χρησιμοποίησα το Plotly (αντί για το D3) για να απεικονίσω τα δεδομένα μου στο Lollapalooza

Το D3.js είναι μια καταπληκτική βιβλιοθήκη JavaScript, αλλά έχει μια πολύ απότομη καμπύλη μάθησης. Αυτό κάνει το έργο της οικοδόμησης μιας πολύτιμης οπτικοποίησης κάτι που μπορεί να απαιτήσει πολλή προσπάθεια. Αυτή η επιπλέον προσπάθεια είναι εντάξει αν ο στόχος σας είναι να κάνετε νέες και δημιουργικές απεικονίσεις δεδομένων, αλλά συχνά αυτό δεν ισχύει.

Συχνά, ο στόχος σας μπορεί να είναι απλώς να δημιουργήσετε μια διαδραστική οπτικοποίηση με μερικά γνωστά γραφήματα . Και αν δεν είστε μηχανικός front-end, αυτό μπορεί να γίνει λίγο δύσκολο.

Ως επιστήμονες δεδομένων, ένα από τα κύρια καθήκοντά μας είναι ο χειρισμός δεδομένων. Σήμερα το κύριο εργαλείο που χρησιμοποιώ είναι το Pandas (Python). Τι γίνεται αν σας πω ότι μπορείτε να δημιουργήσετε μερικά όμορφα και διαδραστικά γραφήματα για τον Ιστό απευθείας από τα πλαίσια δεδομένων του Pandas ; Λοιπόν, μπορείτε! Μπορούμε να χρησιμοποιήσουμε το Plotly για αυτό.

Προς καταγραφή, υπάρχουν επίσης Plotly API βιβλιοθήκες για Matlab, R και JavaScript, αλλά θα διατηρήσουμε τη βιβλιοθήκη Python εδώ.

Για να είμαστε δίκαιοι, το Plotly είναι χτισμένο πάνω από το d3.js (και stack.gl). Η κύρια διαφορά μεταξύ D3 και Plotly είναι ότι το Plotly είναι συγκεκριμένα μια βιβλιοθήκη χαρτών .

Ας δημιουργήσουμε ένα γράφημα ράβδων για να μάθουμε πώς λειτουργεί το Plotly.

Χτίζοντας ένα γράφημα ράβδων με γραφικά

Υπάρχουν 3 κύριες έννοιες στη φιλοσοφία του Plotly:

  • Δεδομένα
  • Διάταξη
  • Φιγούρα

Δεδομένα

Το αντικείμενο δεδομένων καθορίζει αυτό που θέλουμε να εμφανίσουμε στο γράφημα (δηλαδή τα δεδομένα). Ορίζουμε μια συλλογή δεδομένων και τις προδιαγραφές για να τα εμφανίσουμε ως ίχνος . Ένα αντικείμενο δεδομένων μπορεί να έχει πολλά ίχνη. Σκεφτείτε ένα γράφημα γραμμών με δύο γραμμές που αντιπροσωπεύουν δύο διαφορετικές κατηγορίες: κάθε γραμμή είναι ένα ίχνος.

Διάταξη

Το αντικείμενο Διάταξης ορίζει δυνατότητες που δεν σχετίζονται με δεδομένα (όπως τίτλος, τίτλοι άξονα κ.ο.κ.) Μπορούμε επίσης να χρησιμοποιήσουμε τη διάταξη για να προσθέσουμε σχολιασμούς και σχήματα στο γράφημα.

Φιγούρα

Το αντικείμενο Σχήμα δημιουργεί το τελικό αντικείμενο που θα σχεδιαστεί. Είναι ένα αντικείμενο που περιέχει δεδομένα και διάταξη.

Οι απεικονίσεις Plotly δημιουργούνται με το plotly.js. Αυτό σημαίνει ότι το API Python είναι απλώς ένα πακέτο για αλληλεπίδραση με τη βιβλιοθήκη plotly.js . Η plotly.graph_objsενότητα περιέχει τις συναρτήσεις που θα δημιουργήσουν αντικείμενα γραφημάτων για εμάς.

Εντάξει, τώρα είμαστε έτοιμοι να δημιουργήσουμε ένα γράφημα ράβδων:

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)

Σημείωση: σε αυτό το άρθρο δεν θα μιλήσουμε για το τι κάνω με τα πλαίσια δεδομένων. Αλλά αν θέλετε μια ανάρτηση σχετικά με αυτό, ενημερώστε με στα σχόλια;

Εντάξει, οπότε πρώτα θέλουμε να δείξουμε τα μπαρ μιας κατηγορίας (ένα μέρος που ονομάζεται "MICROBAR"). Έτσι δημιουργούμε ένα αντικείμενο δεδομένων (μια λίστα) με go.Bar()(ένα ίχνος) που καθορίζει τα δεδομένα για τους άξονες x και y. Το Trace είναι λεξικό και τα δεδομένα είναι μια λίστα λεξικών. Εδώ είναι τα trace_microbarπεριεχόμενα (παρατηρήστε το κλειδί τύπου):

{'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}

Στο αντικείμενο Layout, ορίζουμε τον τίτλο του γραφήματος και την παράμετρο showlegend. Στη συνέχεια, τυλίγουμε τα δεδομένα και τη διάταξη σε σχήμα και καλούμε plotly.offline.plot()για εμφάνιση του γραφήματος. Το Plotly έχει διαφορετικές επιλογές για την εμφάνιση των γραφημάτων, αλλά ας μείνουμε εδώ με την επιλογή εκτός σύνδεσης. Αυτό θα ανοίξει ένα παράθυρο προγράμματος περιήγησης με το γράφημα μας.

Θέλω να εμφανίσω τα πάντα σε ένα στοίβα στοίβα ράβδων, οπότε θα δημιουργήσουμε μια λίστα δεδομένων με όλα τα ίχνη (μέρη) που θέλουμε να εμφανίσουμε και να ρυθμίσουμε την barmodeπαράμετρο να στοιβάζονται .

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)

Και αυτό είναι τα βασικά του Plotly. Για να προσαρμόσουμε τα γραφήματά μας, ορίζουμε διαφορετικές παραμέτρους για ίχνη και διάταξη. Τώρα ας προχωρήσουμε και μιλήσουμε για την απεικόνιση Lollapalooza.

Η εμπειρία μου στο Lollapalooza

Για την έκδοση 2018 του Lollapalooza Brazil, όλες οι αγορές πραγματοποιήθηκαν μέσω βραχιολιού με δυνατότητα RFID. Στέλνουν τα δεδομένα στη διεύθυνση email σας, γι 'αυτό αποφάσισα να τα ρίξω μια ματιά. Τι μπορούμε να μάθουμε για εμένα και την εμπειρία μου αναλύοντας τις αγορές που πραγματοποίησα στο φεστιβάλ;

Έτσι φαίνεται τα δεδομένα:

  • Ημερομηνία αγοράς
  • ώρα αγοράς
  • προϊόν
  • ποσότητα
  • στάδιο
  • μέρος όπου έκανα την αγορά

Με βάση αυτά τα δεδομένα, ας απαντήσουμε σε μερικές ερωτήσεις.

Πού πήγα κατά τη διάρκεια του φεστιβάλ;

Τα δεδομένα μας λένε μόνο το όνομα της τοποθεσίας στην οποία πραγματοποίησα την αγορά και το φεστιβάλ πραγματοποιήθηκε στο Autódromo de Interlagos. Πήρα τον χάρτη με τα στάδια από εδώ και χρησιμοποίησα το εργαλείο georeferencer από το georeference.com για να λάβω τις συντεταγμένες γεωγραφικού πλάτους και μήκους για τα στάδια.

Πρέπει να εμφανίσουμε έναν χάρτη και τους δείκτες για κάθε αγορά, οπότε θα χρησιμοποιήσουμε το Mapbox και το scattermapboxίχνος. Αρχικά ας σχεδιάσουμε μόνο τα στάδια για να δούμε πώς λειτουργεί:

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)

Ας μάθουν μια νέα παράμετρο διάταξης: updatemenus. Θα το χρησιμοποιήσουμε για να εμφανίσουμε τους δείκτες κατά ημερομηνία. Υπάρχουν τέσσερις πιθανές μέθοδοι ενημέρωσης:

  • "restyle": τροποποίηση δεδομένων ή χαρακτηριστικών δεδομένων
  • "relayout": τροποποίηση χαρακτηριστικών διάταξης
  • "update": τροποποίηση δεδομένων και χαρακτηριστικών διάταξης
  • "animate": έναρξη ή παύση μιας κινούμενης εικόνας)

Για την ενημέρωση των δεικτών, χρειάζεται μόνο να τροποποιήσουμε τα δεδομένα, επομένως θα χρησιμοποιήσουμε τη "restyle"μέθοδο. Κατά την επαναφορά, μπορείτε να ορίσετε τις αλλαγές για κάθε ίχνος ή για όλα τα ίχνη. Εδώ ορίζουμε ότι κάθε ίχνος είναι ορατό μόνο όταν ο χρήστης αλλάξει την επιλογή του αναπτυσσόμενου μενού:

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)

Πώς ξόδεψα τα χρήματά μου;

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.

Για να μάθω ποια από αυτές τις εκπομπές παρακολούθησα, υπολόγισα την απόσταση από την τοποθεσία της αγοράς σε κάθε στάδιο. Οι παραστάσεις που παρακολούθησα πρέπει να είναι αυτές με τη μικρότερη απόσταση από τις παραχωρήσεις.

Καθώς θέλουμε να δείξουμε κάθε σημείο δεδομένων, η καλύτερη επιλογή για μια οπτικοποίηση είναι ένας πίνακας. Ας φτιάξουμε ένα:

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)

Τρεις συναυλίες έλειπαν και τέσσερις ήταν λανθασμένες, δίνοντας μας ακρίβεια 67% και ανάκληση 72%.

Συγκεντρώνοντας όλα: παύλα

Έχουμε όλα τα γραφήματα, αλλά ο στόχος είναι να τα συγκεντρώσουμε όλα σε μια σελίδα. Για να το κάνουμε αυτό θα χρησιμοποιήσουμε το Dash (από την Plotly).

«Το Dash είναι ένα πλαίσιο Python για τη δημιουργία αναλυτικών εφαρμογών Ιστού. Δεν απαιτείται JavaScript. Το Dash είναι ιδανικό για τη δημιουργία εφαρμογών οπτικοποίησης δεδομένων με εξαιρετικά προσαρμοσμένες διεπαφές χρήστη σε καθαρό Python. Είναι ιδιαίτερα κατάλληλο για όσους εργάζονται με δεδομένα στο Python. " - Ο ιστότοπος της Plotly

Το Dash γράφεται πάνω από το Flask, το Plotly.js και το React.js. Λειτουργεί με πολύ παρόμοιο τρόπο με τον τρόπο δημιουργίας γραφημάτων Plotly:

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)

Εντάξει, σωστά;

Φιλοξενούσα την τελική απεικόνιση εδώ και όλος ο κώδικας είναι εδώ.

Υπάρχουν κάποιες εναλλακτικές λύσεις για τη φιλοξενία των οπτικοποιήσεων: Το Dash διαθέτει δημόσια φιλοξενία εφαρμογών παύσης και το Plotly παρέχει επίσης μια διαδικτυακή υπηρεσία για φιλοξενία γραφημάτων.

Βρήκατε αυτό το άρθρο χρήσιμο; Προσπαθώ ό, τι καλύτερο μπορώ να γράφω ένα άρθρο σε βάθος κάθε μήνα, μπορείτε να λαμβάνετε ένα μήνυμα ηλεκτρονικού ταχυδρομείου όταν δημοσιεύω ένα νέο.

Είχα μια πολύ καλή εμπειρία με το Plotly, σίγουρα θα το χρησιμοποιήσω για το επόμενο έργο μου. Ποιες είναι οι σκέψεις σας για αυτό μετά από αυτήν την επισκόπηση; Και ποια άλλα εργαλεία χρησιμοποιείτε για τη δημιουργία οπτικοποιήσεων για τον Ιστό; Μοιραστείτε τα στα σχόλια! Και ευχαριστώ που διαβάσατε! ;