Trong lĩnh vực data science thì công đoạn data visualization đóng một vai trò quan trọng, giúp hiển thị rõ ràng hơn mối quan hệ và ý nghĩa của data. Và với Python, ngôn ngữ phổ biến nhất hiện tại trong lĩnh vực data science thì hiện tại đã có rất nhiều lự chọn để thực hiện công việc data visualization này. Có thể kể đến các thư viện native cho Python như matplotlib, seaborn, bokeh hay các thư viện có support cho Python như Altair, Plotly... Bài viết này sẽ giới thiệu qua về Plotly, thư viện dựa trên d3.js do vậy có thể tạo biểu đồ có tính interactive cao nhất (theo đánh giá cá nhân người viết)

I. Giới thiệu về Plotly

Thật ra Plotly không đơn giản chỉ là một thư viện phục vụ cho data visualization mà là hẳn một platform phục vu cho công việc data analytics, và platform này tốn phí cũng kha khá (Bạn đọc có thể tham khảo ở trang chủ của công ty) . Tuy nhiên, Plotly là một công ty hướng mã nguồn mở nên các thư viện xây dựng lên nền tảng của họ cũng được open source như là Dash (thư viện để tạo Dashboard, sẽ giới thiệu ở phần dưới của bài viết) hay Plotly (thư viện cho Data Visualization, hiện tại đã support Javascript, Python và R.

Việc sử dụng các thư viện trên hoàn toàn miễn phí theo MIT license, tuy nhiên ở setting mặc định các biểu đồ tạo ra sẽ được upload lên trang web của Plotly và cần có tài khoản của Plotly, tuy nhiên ta có thể setting để sử dụng Plotly ở chế độ offline và không cần có tài khoản gì cả (sẽ nói chi tiết hơn ở phần dưới).

II. Sử dụng Plotly với Python

1. Cài đặt Plotly

Khá là đơn giản, chỉ cần dùng pip hoặc nếu bạn đang dùng Anaconda để sử dụng Python thì dùng conda

$ pip install plotly
# or
$ conda install -c plotly plotly

Để sử dụng Plotly với Jupyter Notebook thì ta phải cài thêm 1 số package nữa

$ pip install "notebook>=5.3" "ipywidgets>=7.2"
# or
$ conda install "notebook>=5.3" "ipywidgets>=7.2"

Và để sử dụng với Jupyter Lab (chỉ support phiên bản Python > 3.5) thì ngoài bước cài đặt còn cần phải cài thêm và setup các extension cho Jupyter Lab (bài viết này sẽ chủ yếu sử dụng Jupyter Lab)

$ pip install jupyterlab==0.35 "ipywidgets>=7.2"
# or 
$ conda install jupyterlab=0.35 "ipywidgets>=7.2"

Cài đặt thêm các extensions cho Jupyter Lab

# Option để tránh lỗi out of memory khi compile
# (OS X/Linux)
export NODE_OPTIONS=--max-old-space-size=4096
# (Windows)
set NODE_OPTIONS=--max-old-space-size=4096

# Jupyter widgets extension
jupyter labextension install @jupyter-widgets/jupyterlab-manager@0.38 --no-build

# FigureWidget support
jupyter labextension install plotlywidget@0.5.2 --no-build

# offline iplot support
jupyter labextension install @jupyterlab/plotly-extension@0.18.1 --no-build

# JupyterLab chart editor support (optional)
jupyter labextension install jupyterlab-chart-editor@1.0 --no-build

# Build extensions (must be done to activate extensions since --no-build is used above)
jupyter lab build

# Unset NODE_OPTIONS environment variable
# (OS X/Linux)
unset NODE_OPTIONS
# (Windows)
set NODE_OPTIONS=

2. Sử dụng Plotly với Jupyter Lab

Vậy là đã xong phần cài đặt, giờ ta chỉ cần khởi động Jupyter Lab và test thử Plotly

$ mkdir plotly_test && cd plotly_test
$ jupyter lab

Sau đó chọn khởi tạo một notebook mới trên giao diện Jupyter Lab

Jupyter Lab

Để sử dụng Plotly ở chế độ offline ta phải cần import Plotly như sau

from plotly.offline import init_notebook_mode, plot, iplot
import plotly.graph_objs as go

plotly.graph_objs là object chứa tất cả các hàm để tạo biểu đồ cho chúng ta. Sau đó để có thể sử dụng Plotly ở chế độ Notebook ta phải gọi hàm sau (thực ra là inject thư viện Plotly.JS vào file notebook).

init_notebook_mode(connected=True)

Sau đó ta có thể dùng hàm iplot để tạo biểu đồ ngay trực tiếp ở trên notebook hay plot để tạo biểu đồ ở một file HTML riêng biệt (bài viết này sẽ chủ yếu sử dụng iplot). Đã đến lúc ta test thử một biểu đồ đơn giản rồi

trace_test = go.Scatter(x=[1,2,3], y=[7,5,9], marker={'color': 'red', 'symbol': 104, 'size': 10}, 
                        mode="markers+lines",  text=["one","two","three"], name='1st Trace')
                                               
data = [trace_test]
layout = go.Layout(title="First Plot", xaxis={'title':'x1'}, yaxis={'title':'x2'})
figure = go.Figure(data=data,layout=layout)
iplot(figure, filename='pyguide_1')

Và Ta Da, ta đã có biểu đồ đơn giản đầu tiên với Plotly:

Ngoài ra ta, có thể nhận thấy figure object mà ta plot dùng hàm iplot thực ra là 1 Python dictionary object

>>> figure
Figure({
    'data': [{'marker': {'color': 'red', 'size': 10, 'symbol': 104},
              'mode': 'markers+lines',
              'name': '1st Trace',
              'text': [one, two, three],
              'type': 'scatter',
              'uid': 'bf4e4846-468a-4762-8080-b9314279c8a8',
              'x': [1, 2, 3],
              'y': [7, 5, 9]}],
    'layout': {'title': 'First Plot', 'xaxis': {'title': 'x1'}, 'yaxis': {'title': 'x2'}}
})

Ta có thể dễ dàng update object này và tạo 1 biểu đồ mới

figure.update({'layout' : {'title': 'Plot Update'}, 'data': [{'marker': {'color': 'green', 'symbol': 103}}]})
iplot(figure, filename='pyguide_2')
Plot Update

3. Plotly với Pandas

Chúng ta đã có thể vẽ biểu đồ đơn giản với Plotly tuy nhiên data mới chỉ là data tự tạo, không phải thực tế. Ta sẽ thử sử dụng Pandas để load data từ file CSV và dùng Plotly để vẽ biểu đồ cho data này. Data được sử dụng ở đây sẽ là data xếp hạng các trường đại học trên thế giới cùng với các thông tin về số lượng citations và nghiên cứu.

Trước tiên ta dùng Pandas để load data vào một Dataframe và xem thử data này nó có định dạng như thế nào.

import pandas as pd
df = pd.read_csv('world-university-rankings/timesData.csv')
time_df = df.iloc[:100,:]
time_df.head(10)

Và sau đó ta sẽ dùng Plotly để vẻ biểu đồ hiển thị số lượng citations và số lượng teaching cho các trường đại học này theo thứ tự từ trường top 1 xuống dần


trace1 = go.Scatter(
                    x = time_df.world_rank,
                    y = time_df.citations,
                    mode = "lines",
                    name = "citations",
                    marker = dict(color = 'rgba(16, 112, 2, 0.8)'),
                    text= time_df.university_name)
trace2 = go.Scatter(
                    x = time_df.world_rank,
                    y = time_df.teaching,
                    mode = "lines+markers",
                    name = "teaching",
                    marker = dict(color = 'rgba(80, 26, 80, 0.8)'),
                    text= time_df.university_name)
data = [trace1, trace2]
layout = dict(title = 'Citation and Teaching vs World Rank of Top 100 Universities',
              xaxis= dict(title= 'World Rank',ticklen= 5,zeroline= False)
             )
fig = dict(data = data, layout = layout)
iplot(fig)

Có thể thấy vì biểu đồ sẽ hiển thị 2 thông tin citations và teachings nên ta sẽ dùng plotly.graph_objs để tạo 2 object biểu đồ Scatter với các thông tin về màu sắc, hình dạng khác nhau. Và ta có thể trực tiếp sử dụng Pandas dataframe để áp data cho các trục xy của 2 biểu đồ này

Ta có thể dùng cách thủ công như trên để dùng Plotly kết hợp với Pandas. Tuy nhiên Plotly cung cấp một thư viện Python khác để có thể thực hiện công việc trên một cách hữu hiệu và ngắn gọn hơn, đó là Cufflinks.

Trước tiên là bước cài đặt:

$ pip install --upgrade cufflinks

Sau đó là config để cufflinks hoạt động ở chế độ offline

import cufflinks as cf
cf.go_offline()

Cufflinks sẽ inject trực tiếp các hàm vẽ đồ thị vào Pandas dataframe. Do đó, đoạn code để vẽ biểu đồ về citations và teaching ở trên có thể được viết lại như sau.

time_df.iplot(x='world_rank', y=['citations', 'teaching'], 
              kind='scatter', xTitle="World Rank", text='university_name',
              mode=['lines', 'lines+markers'],
              filename='cufflinks/cf-simple-line')

Ta sẽ có biểu đồ như sau (trông hơi khác một chút, vì chưa config lại màu sắc và hình dạng của marker):

III. Kết luận

Có thể thấy dù cài đặt hơi phức tạp hơn các thư viện data visualization khác, tuy nhiên Plotly là một công cụ rất mạnh và flexible cùng với một hệ sinh thái phong phú. Trong giới hạn format của blog khó có thể thể hiện được tính interactive của Plotly, mời bạn đọc tham khảo trên link notebook ở phần link tham khảo. Phần tới của bài viết (nếu có) sẽ giới thiệu về cách dùng Dash, một tool của Plotly để dựng Data Visualization Dashboard với Python.