HOWTO · Plotly

Plotly 線形圖

本文教你在 Python 中使用 Plotly 的 line() 函式建立折線圖。

本頁內容

折線圖以連續的線條連接資料點,容易呈現某個值在時間這類有序軸上的變化。在 Python 中,建立折線圖最快的方法是 px.line,也就是 Plotly Express 的折線圖函式:傳入 x 軸與 y 軸資料,它會回傳一個 Figure 物件,再由 fig.show() 在瀏覽器或筆記本中渲染出來。

使用 Plotly Express 建立折線圖

Plotly Express 是 Plotly 的高階繪圖介面。px.line 會接收你的資料、建立 Figure,並為你提供的每個序列儲存一條 trace(一條線)。

執行這個範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import pandas as pd
import plotly.express as px

df = pd.DataFrame(
    {
        "day": ["Mon", "Tue", "Wed", "Thu"],
        "team_a": [3, 4, 3, 5],
        "team_b": [2, 3, 2, 4],
    }
)
fig = px.line(df, x="day", y=["team_a", "team_b"], width=500, height=400)
print(len(fig.data))
2

width 與 height 引數以像素為單位設定圖表大小;將包含兩個欄位的清單傳給 y 會畫出兩條線,因此印出的 trace 數量是 2。欄位名稱會成為圖例項目。

在最後一行加上 fig.show(),即可在瀏覽器中開啟渲染好的圖表(在 Jupyter 筆記本中,直接對 fig 求值就會自動顯示)。結果如下:

一張 Plotly 折線圖,包含兩個線條序列、四個 x 軸標籤與圖例

選擇 x 軸與 y 軸的資料

px.line 接受兩種形式的資料。你可以直接把一般的 Python 序列傳給 x 和 y,也可以把 dataframe 作為第一個引數傳入,再把要繪製的欄位名稱指定給 x 和 y。x 沿著水平軸定位資料點,y 沿著垂直軸定位,Plotly 會依照數值出現的順序連接各點。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import pandas as pd
import plotly.express as px

sequence_fig = px.line(x=[1, 2, 3, 4], y=[10, 15, 13, 18])

df = pd.DataFrame(
    {"month": ["Jan", "Feb", "Mar", "Apr"], "revenue": [10, 15, 13, 18]}
)
column_fig = px.line(df, x="month", y="revenue")

print(len(sequence_fig.data), len(column_fig.data))
1 1

兩種形式都會產生單線圖。若要繪製多個序列,可以像第一個範例那樣,對寬格式(wide-form)資料把欄位名稱清單傳給 y;或者把資料保持為長格式(long form)——每個觀測值一列,並用一個欄位標明所屬序列——再把該欄位傳給 color。當你想讓座標軸標題或圖例名稱與欄位名稱不同時,可以使用 labels 引數,它是一個把欄位名稱對應到顯示文字的字典。

自訂線條、顏色與標記

使用長格式資料時,color 會為每個群組各畫一條線並加上圖例,line_dash 會改變每條線的虛線樣式,symbol 則改變每個資料點的標記符號(設定 symbol 後標記會自動出現;否則可用 markers=True 強制顯示)。text 引數為每個資料點設定文字標籤,可用 fig.update_traces(mode="lines+markers+text") 顯示出來,而 title 會為圖表加上標題。

Plotly 會從預設序列中挑選顏色與虛線樣式。你可以用 color_discrete_sequence 覆寫它——可指定 px.colors.qualitative.Light24 或 Dark24 等具名色盤,或你自己的清單——以及 line_dash_sequence,它會在 solid、dot、dash、longdash、dashdot、longdashdot 等有效虛線樣式之間循環。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(
    df,
    x="year",
    y="lifeExp",
    color="country",
    line_dash="country",
    color_discrete_sequence=px.colors.qualitative.Light24,
    line_dash_sequence=["longdashdot", "dash"],
    width=600,
    height=400,
)
print(len(fig.data), fig.data[0].line.dash)
2 longdashdot

px.data.gapminder() 會載入 Plotly 內建的資料集,query 呼叫則保留大洋洲的兩個國家,使圖表有兩條線。第一個序列會採用 line_dash_sequence 的第一個項目。

一張 Plotly 折線圖,兩條線改用 Light24 色盤的顏色並以不同虛線樣式繪製

若要精確控制個別線條,可使用 color_discrete_map,它是一個把群組名稱對應到 CSS 顏色的字典。未列入對應表的群組會繼續使用目前作用中序列的顏色。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(
    df,
    x="year",
    y="lifeExp",
    color="country",
    color_discrete_map={"Australia": "black", "New Zealand": "yellow"},
    width=600,
    height=400,
)
print(fig.data[0].name, fig.data[0].line.color)
Australia black

一張 Plotly 折線圖,澳洲線條為黑色、紐西蘭線條為黃色

將圖表分割為 facet 並變更座標軸刻度

facet_col 與 facet_row 會把圖表分割成子圖網格,為所選欄位的每個值各產生一個子圖,讓各序列可以並排比較。facet_col_spacing 與 facet_row_spacing 接受 0 到 1 之間的浮點數,以繪圖區域的比例設定子圖之間的間距。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(
    df,
    x="year",
    y="lifeExp",
    color="country",
    line_dash="country",
    symbol="country",
    facet_col="country",
    title="Line Chart",
    width=600,
    height=400,
)
print(len(fig.data))
2

兩個並排的 Plotly 子圖,在共用標題下各自顯示一個國家帶標記的線條序列

當數值橫跨數個數量級時,可用 log_x=True 或 log_y=True 把座標軸切換為對數刻度;Plotly 會以十的冪次標示刻度。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", log_y=True)
print(fig.layout.yaxis.type)
log

更新 trace 並加入誤差線

若要繪製誤差線(error bar),請把存放每個資料點誤差大小的欄位或序列傳給 error_y(水平方向的不確定性則用 error_x):

本節中的程式碼以及顯示的標籤或輸出仍為英文。

import pandas as pd
import plotly.express as px

df = pd.DataFrame(
    {
        "month": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
        "revenue": [102, 118, 110, 131, 125, 140],
        "uncertainty": [6, 8, 5, 9, 7, 10],
    }
)
fig = px.line(df, x="month", y="revenue", error_y="uncertainty", markers=True)
print(len(fig.data[0].error_y.array))
6

圖表建立之後,fig.update_traces 會一次把 trace 屬性套用到所有線條。例如,showlegend=False 會把所有線條從圖例中移除,而 opacity 介於 0 到 1 之間可讓線條變成半透明——當多個序列重疊時特別有用。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", width=600, height=400)
fig.update_traces(showlegend=False, opacity=0.7)
print(fig.data[0].showlegend, fig.data[0].opacity)
False 0.7

一張 Plotly 折線圖,兩條半透明線條且無圖例

px.line 建立的是 Scatter trace,因此 Plotly scatter 參考文件中的每個選項也都能與 fig.update_traces 搭配使用。