Bagaimana dan mengapa saya menggunakan Plotly (bukan D3) untuk memvisualisasikan data Lollapalooza saya

D3.js adalah pustaka JavaScript yang mengagumkan, tetapi memiliki kurva belajar yang sangat curam. Hal ini membuat tugas membangun visualisasi yang berharga menjadi sesuatu yang membutuhkan banyak usaha. Upaya ekstra ini tidak masalah jika tujuan Anda adalah membuat visualisasi data yang baru dan kreatif, tetapi seringkali bukan itu masalahnya.

Sering kali, tujuan Anda mungkin hanya untuk membangun visualisasi interaktif dengan beberapa diagram terkenal . Dan jika Anda bukan insinyur front-end, ini bisa menjadi sedikit rumit.

Sebagai ilmuwan data, salah satu tugas utama kami adalah manipulasi data. Hari ini alat utama yang saya gunakan untuk itu adalah Pandas (Python). Bagaimana jika saya memberi tahu Anda bahwa Anda dapat membuat beberapa bagan yang indah dan interaktif untuk web langsung dari kerangka data Pandas Anda ? Ya, Anda bisa! Kita bisa menggunakan Plotly untuk itu.

Sebagai catatan, ada juga Library API Plotly untuk Matlab, R dan JavaScript, tetapi kami akan tetap menggunakan library Python di sini.

Agar adil, Plotly dibangun di atas d3.js (dan stack.gl). Perbedaan utama antara D3 dan Plotly adalah bahwa Plotly secara khusus merupakan perpustakaan bagan .

Mari buat diagram batang untuk mengetahui cara kerja Plotly.

Membangun diagram batang dengan plotly

Ada 3 konsep utama dalam filosofi Plotly:

  • Data
  • Tata Letak
  • Angka

Data

Objek Data mendefinisikan apa yang ingin kita tampilkan di grafik (yaitu, data). Kami menentukan kumpulan data dan spesifikasi untuk menampilkannya sebagai jejak . Objek Data dapat memiliki banyak jejak. Pikirkan bagan garis dengan dua garis yang mewakili dua kategori berbeda: setiap garis adalah jejak.

Tata Letak

Objek Tata Letak mendefinisikan fitur yang tidak terkait dengan data (seperti judul, judul sumbu, dan sebagainya). Kita juga bisa menggunakan Layout untuk menambahkan anotasi dan bentuk ke grafik.

Angka

Objek Gambar membuat objek akhir yang akan diplot. Ini adalah objek yang berisi data dan tata letak.

Visualisasi plot dibangun dengan plotly.js. Ini berarti Python API hanyalah sebuah paket untuk berinteraksi dengan pustaka plotly.js . The plotly.graph_objsmodul berisi fungsi yang akan menghasilkan objek grafik bagi kita.

Oke, sekarang kita siap membuat diagram batang:

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)

Catatan: dalam artikel ini kita tidak akan membicarakan tentang apa yang saya lakukan dengan kerangka data. Tetapi jika Anda ingin posting tentang itu, beri tahu saya di komentar?

Oke, jadi pertama-tama kami ingin menunjukkan bilah dari satu kategori (tempat bernama "MICROBAR"). Jadi kita membuat objek data (daftar) dengan go.Bar()(jejak) menentukan data untuk sumbu x dan y. Trace adalah kamus dan data adalah daftar kamus. Berikut trace_microbarisinya (perhatikan kunci tipe):

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

Di objek Layout, kami menetapkan judul bagan dan parameter showlegend. Kemudian kami membungkus Data dan Tata Letak dalam gambar dan memanggil plotly.offline.plot()untuk menampilkan grafik. Plotly memiliki opsi berbeda untuk menampilkan grafik, tetapi mari kita tetap menggunakan opsi offline di sini. Ini akan membuka jendela browser dengan bagan kami.

Saya ingin menampilkan semuanya dalam diagram batang bertumpuk, jadi kami akan membuat daftar data dengan semua jejak (tempat) yang ingin kami tampilkan dan mengatur barmodeparameter ke tumpukan .

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)

Dan itulah dasar-dasar Plotly. Untuk menyesuaikan grafik kami, kami menetapkan parameter yang berbeda untuk jejak dan tata letak. Sekarang mari kita lanjutkan dan bicara tentang visualisasi Lollapalooza.

Pengalaman Lollapalooza saya

Untuk Lollapalooza Brazil edisi 2018, semua pembelian dilakukan melalui gelang berkemampuan RFID. Mereka mengirim data ke alamat email Anda, jadi saya memutuskan untuk memeriksanya. Apa yang bisa kita pelajari tentang saya dan pengalaman saya dengan menganalisis pembelian yang saya lakukan di festival?

Beginilah tampilan datanya:

  • Tanggal Pembelian
  • jam pembelian
  • produk
  • kuantitas
  • tahap
  • tempat saya melakukan pembelian

Berdasarkan data ini, mari kita jawab beberapa pertanyaan.

Kemana saya pergi selama festival?

Data hanya memberi tahu kami nama lokasi tempat saya melakukan pembelian, dan festival berlangsung di Autódromo de Interlagos. Saya mengambil peta dengan tahapan dari sini dan menggunakan alat georeferensi dari georeference.com untuk mendapatkan koordinat lintang dan bujur untuk tahapan tersebut.

Kita perlu menampilkan peta dan penanda untuk setiap pembelian, jadi kita akan menggunakan Mapbox dan scattermapboxjejaknya. Pertama mari kita plot hanya tahapan untuk melihat cara kerjanya:

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)

Mari kita belajar parameter Tata Letak baru: updatemenus. Kami akan menggunakan ini untuk menampilkan penanda berdasarkan tanggal. Ada empat kemungkinan metode pembaruan:

  • "restyle": memodifikasi data atau atribut data
  • "relayout": memodifikasi atribut tata letak
  • "update": memodifikasi atribut data dan tata letak
  • "animate": memulai atau menjeda animasi)

Untuk mengupdate marker, kita hanya perlu memodifikasi datanya, maka kita akan menggunakan "restyle"metode tersebut. Saat mengubah gaya, Anda dapat mengatur perubahan untuk setiap jejak atau untuk semua jejak. Di sini kami mengatur setiap jejak agar terlihat hanya ketika pengguna mengubah opsi menu tarik-turun:

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)

Bagaimana saya menghabiskan uang saya?

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.

Untuk mengetahui show mana yang saya hadiri, saya menghitung jarak dari lokasi pembelian ke tiap stage. Pertunjukan yang saya hadiri haruslah pertunjukan dengan jarak terpendek ke konsesi.

Karena kami ingin menampilkan setiap titik data, pilihan terbaik untuk visualisasi adalah tabel. Ayo buat satu:

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)

Tiga konser hilang dan empat salah, memberi kami presisi 67% dan perolehan 72%.

Menyatukan semuanya: dasbor

Kami memiliki semua bagan, tetapi tujuannya adalah untuk menempatkan semuanya dalam satu halaman. Untuk melakukan itu kita akan menggunakan Dash (by Plotly).

“Dash adalah kerangka kerja Python untuk membangun aplikasi web analitik. Tidak diperlukan JavaScript. Dash sangat ideal untuk membangun aplikasi visualisasi data dengan antarmuka pengguna yang sangat khusus dengan Python murni. Ini sangat cocok untuk siapa saja yang bekerja dengan data dengan Python. ” - Situs Plotly

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! ?