
python具有強大的可視化功能,能夠繪制出許多效果酷炫的圖表,小編今天跟大家分享的是:如何用python繪制折線圖。
以下文章轉載于大數據DT微信公眾號。
作者:屈希峰,資深Python工程師,知乎多個專欄作者
來源:大數據DT(ID:hzdashuju)
內容摘編自《Python數據可視化:基于Bokeh的可視化繪圖》
導讀:數據分析時經常用到的折線圖,你真的懂了嗎?可以用來呈現哪些數據關系?在數據分析過程中可以解決哪些問題?怎樣用Python繪制折線圖?本文逐一為你解答。
01 概述
折線圖(Line)是將排列在工作表的列或行中的數據進行繪制后形成的線狀圖形。折線圖可以顯示隨時間(根據常用比例設置)而變化的連續數據,非常適用于顯示在相等時間間隔下數據的趨勢。
在折線圖中,數據是遞增還是遞減、增減的速率、增減的規律(周期性、螺旋性等)、峰值等特征都可以清晰地反映出來。所以,折線圖常用來分析數據隨時間的變化趨勢,也可用來分析多組數據隨時間變化的相互作用和相互影響。
例如,可用來分析某類商品或是某幾類相關的商品隨時間變化的銷售情況,從而進一步預測未來的銷售情況。在折線圖中,一般水平軸(x軸)用來表示時間的推移,并且間隔相同;而垂直軸(y軸)代表不同時刻的數據的大小。如圖0所示。
▲圖0 折線圖
02 實例
折線圖代碼示例如下所示。
代碼示例①
1# 數據
2x = [1. 2. 3. 4. 5. 6. 7]
3y = [6. 7. 2. 4. 5. 10. 4]
4# 畫布:坐標軸標簽,畫布大小
5p = figure(title="line example", x_axis_label='x', y_axis_label='y', width=400. height=400)
6# 繪圖:數據、圖例、線寬
7p.line(x, y, legend="Temp.", line_width=2) # 折線
8# 顯示
9show(p)
運行結果如圖1所示。
▲圖1 代碼示例①運行結果
代碼示例①仍以最簡單的方式繪制第一張折線圖。line()方法的參數說明如下。
p.line(x, y, **kwargs)參數說明
x (:class:`~bokeh.core.properties.NumberSpec` ) : x坐標。
y (:class:`~bokeh.core.properties.NumberSpec` ) : y坐標。
line_alpha (:class:`~bokeh.core.properties.NumberSpec` ) : (default: 1.0) 輪廓線透明度。
line_cap ( :class:`~bokeh.core.enums.LineCap` ) : (default: 'butt') 線端。
line_color (:class:`~bokeh.core.properties.ColorSpec` ) : (default: 'black') 輪廓線顏色,默認:黑色。
line_dash (:class:`~bokeh.core.properties.DashPattern` ) : (default: []) 虛線,類型可以是序列,也可以是字符串('solid', 'dashed', 'dotted', 'dotdash', 'dashdot')。
line_dash_offset (:class:`~bokeh.core.properties.Int` ) : (default: 0) 虛線偏移。
line_join(:class:`~bokeh.core.enums.LineJoin` ) : (default: 'bevel')。
line_width(:class:`~bokeh.core.properties.NumberSpec` ) : (default: 1) 線寬。
name (:class:`~bokeh.core.properties.String` ) : 圖元名稱。
tags (:class:`~bokeh.core.properties.Any` ) :圖元標簽。
alpha (float) : 一次性設置所有線條的透明度。
color (Color) : 一次性設置所有線條的顏色。
source (ColumnDataSource) : Bokeh特有數據格式(類似于Pandas Dataframe)。
legend (str) : 圖元的圖例。
x_range_name (str) : x軸范圍名稱。
y_range_name (str) : y軸范圍名稱。
level (Enum) : 圖元渲染級別。
代碼示例②
1p = figure(plot_width=400. plot_height=400)
2# 線段x、y位置點均為列表;兩段線的顏色、透明度、線寬
3p.multi_line([[1. 3. 2], [3. 4. 6. 6]], [[2. 1. 4], [4. 7. 8. 5]],
4color=["firebrick", "navy"], alpha=[0.8. 0.3], line_width=4) # 多條折(曲)線
5show(p)
運行結果如圖2所示。
▲圖2 代碼示例②運行結果
代碼示例②第3行使用multi_line()方法,實現一次性繪制兩條折線,同時,在參數中定義不同折線的顏色。如果使用Pandas Dataframe,則可以同時繪制不同列的數據。multi_line()方法的參數說明如下。
p.multi_line(xs, ys, **kwargs)參數說明
xs (:class:`~bokeh.core.properties.NumberSpec` ) :x坐標,列表。
ys (:class:`~bokeh.core.properties.NumberSpec` ) :y坐標,列表。
其他參數同line。
代碼示例③
1# 準備數據
2x = [0.1. 0.5. 1.0. 1.5. 2.0. 2.5. 3.0]
3y0 = [i**2 for i in x]
4y1 = [10**i for i in x]
5y2 = [10**(i**2) for i in x]
6# 創建畫布
7p = figure(
8 tools="pan,box_zoom,reset,save",
9 y_axis_type="log", title="log axis example",
10 x_axis_label='sections', y_axis_label='particles',
11 width=700. height=350)
12# 增加圖層,繪圖
13p.line(x, x, legend="y=x")
14p.circle(x, x, legend="y=x", fill_color="white", size=8)
15p.line(x, y0. legend="y=x^2", line_width=3)
16p.line(x, y1. legend="y=10^x", line_color="red")
17p.circle(x, y1. legend="y=10^x", fill_color="red", line_color="red", size=6)
18p.line(x, y2. legend="y=10^x^2", line_color="orange", line_dash="4 4")
19# 顯示
20show(p)
運行結果如圖3所示。
▲圖3 代碼示例③運行結果
代碼示例③第13、15、16行使用line()方法逐一繪制折線,該方法的優點是基本數據清晰,可在不同線條繪制過程中直接定義圖例。讀者也可以使用multi_line()方法一次性繪制三條折線,然后再繪制折線上的數據點。同樣,既可以在函數中預定義圖例,也可以用Lengend方法單獨進行定義,在后會對圖例進行詳細說明。
代碼示例④
1p.legend.location = "top_left" # 圖例位于左上
2p.legend.click_policy="hide" # 點擊圖例顯示、隱藏圖形
3show(p) # 自行測試效果
運行結果如圖4所示。
▲圖4 代碼示例④運行結果
代碼示例④在代碼示例③的基礎上增加了圖例的位置、顯示或隱藏圖形屬性;通過點擊圖例,可實現圖形的顯示或隱藏,當折線數目較多或者顏色干擾閱讀時,可以通過該方法實現對某一條折線數據的重點關注。這種通過圖例、工具條、控件實現數據人機交互的可視化方式,正是Bokeh得以在GitHub火熱的原因,建議在工作實踐中予以借鑒。
代碼示例⑤
1# 數據
2import numpy as np
3x = np.linspace(0. 4*np.pi, 200)
4y1 = np.sin(x)
5y2 = np.cos(x)
6# 將y1+—0.9范圍外的數據設置為無窮大
7y1[y1>+0.9] = +np.inf
8y1[y1<-0.9] = -np.inf
9# 將y2+—0.9范圍外的數據采用掩碼數組或NAN值替換
10y2 = np.ma.masked_array(y2. y2<-0.9)
11y2[y2>0.9] = np.nan
12# 圖層
13p = figure(title="lines with missing/inf values")
14# 繪圖x,y1
15p.line(x, y1. color="firebrick", line_width=2) # 磚紅色
16# 繪圖x,y2
17p.line(x, y2. color="blue", line_width=2) # 藍色
18show(p)
運行結果如圖5所示。
▲圖5 代碼示例⑤運行結果
代碼示例⑤第15、16行使用line()方法繪制兩組不同顏色的曲線。
代碼示例⑥
1import numpy as np
2from collections import defaultdict
3from scipy.stats import norm
4from bokeh.models import HoverTool, TapTool
5from bokeh.layouts import gridplot
6from bokeh.palettes import Viridis6
7# 數據
8mass_spec = defaultdict(list) #defaultdict類的初始化函數接受一個list類型作為參數,當所訪問的鍵不存在時,可以實例化一個值作為默認值
9RT_x = np.linspace(118. 123. num=50)
10norm_dist = norm(loc=120.4).pdf(RT_x) # loc均值;pdf輸入x,返回概率密度函數
11
12# 生成6組高斯分布的曲線
13for scale, mz in [(1.0. 83), (0.9. 55), (0.6. 98), (0.4. 43), (0.2. 39), (0.12. 29)]:
14 mass_spec["RT"].append(RT_x)
15 mass_spec["RT_intensity"].append(norm_dist * scale)
16 mass_spec["MZ"].append([mz, mz])
17 mass_spec["MZ_intensity"].append([0. scale])
18 mass_spec['MZ_tip'].append(mz)
19 mass_spec['Intensity_tip'].append(scale)
20# 線條顏色
21mass_spec['color'] = Viridis6
22# 畫布參數
23figure_opts = dict(plot_width=450. plot_height=300)
24hover_opts = dict(
25 tooltips=[('MZ', '@MZ_tip'), ('Rel Intensity', '@Intensity_tip')], # 鼠標懸停在曲線上動態顯示數據
26 show_arrow=False,
27 line_policy='next'
28)
29line_opts = dict(
30 line_width=5. line_color='color', line_alpha=0.6.
31 hover_line_color='color', hover_line_alpha=1.0.
32 source=mass_spec # 線條數據
33)
34# 畫布1
35rt_plot = figure(tools=[HoverTool(**hover_opts), TapTool()], **figure_opts)
36# 同時繪制多條折(曲)線
37rt_plot.multi_line(xs='RT', ys='RT_intensity', legend="Intensity_tip", **line_opts)
38# x,y軸標簽
39rt_plot.xaxis.axis_label = "Retention Time (sec)"
40rt_plot.yaxis.axis_label = "Intensity"
41# 畫布2
42mz_plot = figure(tools=[HoverTool(**hover_opts), TapTool()], **figure_opts)
43mz_plot.multi_line(xs='MZ', ys='MZ_intensity', legend="Intensity_tip", **line_opts)
44mz_plot.legend.location = "top_center"
45mz_plot.xaxis.axis_label = "MZ"
46mz_plot.yaxis.axis_label = "Intensity"
47# 顯示
48show(gridplot([[rt_plot, mz_plot]]))
運行結果如圖6所示。
▲圖6 代碼示例⑥運行結果
代碼示例⑥第19行中,生成繪圖數據時,同時生成圖例名稱列表;第37、43行使用multi_line()方法一次性繪制6條曲線,并預定義圖例。
代碼示例⑦
1import numpy as np
2# 數據
3x = np.linspace(0.1. 5. 80)
4# 畫布
5p = figure(title="log axis example", y_axis_type="log",
6 x_range=(0. 5), y_range=(0.001. 10**22),
7 background_fill_color="#fafafa")
8# 繪圖
9p.line(x, np.sqrt(x), legend="y=sqrt(x)",
10 line_color="tomato", line_dash="dashed")
11p.line(x, x, legend="y=x")
12p.circle(x, x, legend="y=x")
13p.line(x, x**2. legend="y=x**2")
14p.circle(x, x**2. legend="y=x**2",
15 fill_color=None, line_color="olivedrab")
16p.line(x, 10**x, legend="y=10^x",
17 line_color="gold", line_width=2)
18p.line(x, x**x, legend="y=x^x",
19 line_dash="dotted", line_color="indigo", line_width=2)
20p.line(x, 10**(x**2), legend="y=10^(x^2)",
21 line_color="coral", line_dash="dotdash", line_width=2)
22# 其他
23p.legend.location = "top_left"
24# 顯示
25show(p)
運行結果如圖7所示。
▲圖7 代碼示例⑦運行結果
代碼示例⑦與代碼示例③相似,第10、19、21行對曲線的屬性進行自定義,注意虛線的幾種形式('solid', 'dashed', 'dotted', 'dotdash', 'dashdot'),讀者可以自行替換測試。
代碼示例⑧
1from bokeh.models import ColumnDataSource, NumeralTickFormatter, SingleIntervalTicker
2from bokeh.sampledata.us_marriages_divorces import data
3# 數據
4data = data.interpolate(method='linear', axis=0).ffill().bfill()
5source = ColumnDataSource(data=dict(
6 year=data.Year.values,
7 marriages=data.Marriages_per_1000.values,
8 divorces=data.Divorces_per_1000.values,
9))
10# 工具條
11TOOLS = 'pan,wheel_zoom,box_zoom,reset,save'
12# 畫布
13p = figure(tools=TOOLS, plot_width=800. plot_height=500.
14 tooltips='@$name{0.0} $name per 1.000 people in @year')
15# 其他自定義屬性
16p.hover.mode = 'vline'
17p.xaxis.ticker = SingleIntervalTicker(interval=10. num_minor_ticks=0)
18p.yaxis.formatter = NumeralTickFormatter(format='0.0a')
19p.yaxis.axis_label = '# per 1.000 people'
20p.title.text = '144 years of marriage and divorce in the U.S.'
21# 繪圖
22p.line('year', 'marriages', color='#1f77b4', line_width=3. source=source, name="marriages")
23p.line('year', 'divorces', color='#ff7f0e', line_width=3. source=source, name="divorces")
24# 顯示
25show(p)
運行結果如圖8所示。
▲圖8 代碼示例⑧運行結果
代碼示例⑧第22、23行通過line()方法繪制兩條曲線,嚴格上講這兩條曲線并不是Bokeh時間序列的標準繪制方法。第17行定義了x軸刻度的間隔以及中間刻度數,讀者可以嘗試將num_minor_ticks=10的顯示效果與圖8進行對比;第18行定義了y軸的數據顯示格式。
代碼示例⑨
1import numpy as np
2from scipy.integrate import odeint
3# 數據
4sigma = 10
5rho = 28
6beta = 8.0/3
7theta = 3 * np.pi / 4
8# 洛倫茲空間向量點生成函數
9def lorenz(xyz, t):
10 x, y, z = xyz
11 x_dot = sigma * (y - x)
12 y_dot = x * rho - x * z - y
13 z_dot = x * y - beta* z
14 return [x_dot, y_dot, z_dot]
15initial = (-10. -7. 35)
16t = np.arange(0. 100. 0.006)
17solution = odeint(lorenz, initial, t)
18x = solution[:, 0]
19y = solution[:, 1]
20z = solution[:, 2]
21xprime = np.cos(theta) * x - np.sin(theta) * y
22# 調色
23colors = ["#C6DBEF", "#9ECAE1", "#6BAED6", "#4292C6", "#2171B5", "#08519C", "#08306B",]
24# 畫布
25p = figure(title="Lorenz attractor example", background_fill_color="#fafafa")
26# 繪圖 洛倫茲空間向量
27p.multi_line(np.array_split(xprime, 7), np.array_split(z, 7),
28 line_color=colors, line_alpha=0.8. line_width=1.5)
29# 顯示
30show(p)
運行結果如圖9所示。
▲圖9 代碼示例⑨運行結果
代碼示例⑨使用multi_line()方法在二維空間展示洛倫茲空間向量,示例中的數據生成稍微有點復雜,可以直觀感受可視化之下的數據之美,有興趣的讀者可以深入了解。
代碼示例⑩
1import numpy as np
2from bokeh.layouts import row
3from bokeh.palettes import Viridis3
4from bokeh.models import CheckboxGroup, CustomJS
5# 數據
6x = np.linspace(0. 4 * np.pi, 100)
7# 畫布
8p = figure()
9# 折線屬性
10props = dict(line_width=4. line_alpha=0.7)
11# 繪圖
12l0 = p.line(x, np.sin(x), color=Viridis3[0], legend="Line 0", **props)
13l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], legend="Line 1", **props)
14l2 = p.line(x, np.tan(x), color=Viridis3[2], legend="Line 2", **props)
15# 復選框激活顯示
16checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"],
17 active=[0. 1. 2], width=100)
18checkbox.callback = CustomJS(args=dict(l0=l0. l1=l1. l2=l2. checkbox=checkbox), code="""
19l0.visible = 0 in checkbox.active;
20l1.visible = 1 in checkbox.active;
21l2.visible = 2 in checkbox.active;
22""")
23# 添加圖層
24layout = row(checkbox, p)
25# 顯示
26show(layout)
運行結果如圖10所示。
▲圖10 代碼示例⑩運行結果
代碼示例⑩增加了Bokeh控件復選框,第12、13、14行使用line()方法繪制3條曲線;第16行定義復選框,并在18行定義回調函數,通過該回調函數控制3條曲線的可視狀態;第24行將復選框、繪圖并在一行進行顯示。
代碼示例?
1from bokeh.models import TapTool, CustomJS, ColumnDataSource
2# 數據
3t = np.linspace(0. 0.1. 100)
4# 回調函數
5code = """
6// cb_data = {geometries: ..., source: ...}
7const view = cb_data.source.selected.get_view();
8const data = source.data;
9if (view) {
10 const color = view.model.line_color;
11 data['text'] = ['Selected the ' + color + ' line'];
12 data['text_color'] = [color];
13 source.change.emit();
14}
15"""
16source = ColumnDataSource(data=dict(text=['No line selected'], text_color=['black']))
17# 畫布
18p = figure(width=600. height=500)
19# 繪圖
20l1 = p.line(t, 100*np.sin(t*50), color='goldenrod', line_width=30)
21l2 = p.line(t, 100*np.sin(t*50+1), color='lightcoral', line_width=20)
22l3 = p.line(t, 100*np.sin(t*50+2), color='royalblue', line_width=10)
23# 文本,注意選擇線條時候的文字變化
24p.text(0. -100. text_color='text_color', source=source)
25# 調用回調函數進行動態交互
26p.add_tools(TapTool(callback=CustomJS(code=code, args=dict(source=source))))
27# 顯示
28show(p)
運行結果如圖11所示。
▲圖11 代碼示例?運行結果
代碼示例?增加點擊曲線的交互效果,第20、21、22行使用line()方法繪制3條曲線;第26行定義曲線再次被點擊時的效果:圖11中左下方會動態顯示當前選中的是哪條顏色的曲線。
代碼示例?
1import numpy as np
2from bokeh.models import ColumnDataSource, Plot, LinearAxis, Grid
3from bokeh.models.glyphs import Line
4# 數據
5N = 30
6x = np.linspace(-2. 2. N)
7y = x**2
8source = ColumnDataSource(dict(x=x, y=y))
9# 畫布
10plot = Plot(
11 title=None, plot_width=300. plot_height=300.
12# min_border=0.
13# toolbar_location=None
14)
15# 繪圖
16glyph = Line(x="x", y="y", line_color="#f46d43", line_width=6. line_alpha=0.6)
17plot.add_glyph(source, glyph)
18# x軸單獨設置(默認)
19xaxis = LinearAxis()
20plot.add_layout(xaxis, 'below')
21# y軸單獨設置(默認)
22yaxis = LinearAxis()
23plot.add_layout(yaxis, 'left')
24# 坐標軸刻度
25plot.add_layout(Grid(dimension=0. ticker=xaxis.ticker))
26plot.add_layout(Grid(dimension=1. ticker=yaxis.ticker))
27# 顯示
28show(plot)
運行結果如圖12所示。
▲圖12 代碼示例?運行結果
代碼示例?使用models接口進行曲線繪制,注意第10、17、20行的繪制方法,這種繪圖方式在實踐中基本很少用到,僅作了解。
本文摘編自《Python數據可視化:基于Bokeh的可視化繪圖》,經出版方授權發布。
數據分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
CDA數據分析師證書考試體系(更新于2025年05月22日)
2025-05-26解碼數據基因:從數字敏感度到邏輯思維 每當看到超市貨架上商品的排列變化,你是否會聯想到背后的銷售數據波動?三年前在零售行 ...
2025-05-23在本文中,我們將探討 AI 為何能夠加速數據分析、如何在每個步驟中實現數據分析自動化以及使用哪些工具。 數據分析中的AI是什么 ...
2025-05-20當數據遇見人生:我的第一個分析項目 記得三年前接手第一個數據分析項目時,我面對Excel里密密麻麻的銷售數據手足無措。那些跳動 ...
2025-05-20在數字化運營的時代,企業每天都在產生海量數據:用戶點擊行為、商品銷售記錄、廣告投放反饋…… 這些數據就像散落的拼圖,而相 ...
2025-05-19在當今數字化營銷時代,小紅書作為國內領先的社交電商平臺,其銷售數據蘊含著巨大的商業價值。通過對小紅書銷售數據的深入分析, ...
2025-05-16Excel作為最常用的數據分析工具,有沒有什么工具可以幫助我們快速地使用excel表格,只要輕松幾步甚至輸入幾項指令就能搞定呢? ...
2025-05-15數據,如同無形的燃料,驅動著現代社會的運轉。從全球互聯網用戶每天產生的2.5億TB數據,到制造業的傳感器、金融交易 ...
2025-05-15大數據是什么_數據分析師培訓 其實,現在的大數據指的并不僅僅是海量數據,更準確而言是對大數據分析的方法。傳統的數 ...
2025-05-14CDA持證人簡介: 萬木,CDA L1持證人,某電商中廠BI工程師 ,5年數據經驗1年BI內訓師,高級數據分析師,擁有豐富的行業經驗。 ...
2025-05-13CDA持證人簡介: 王明月 ,CDA 數據分析師二級持證人,2年數據產品工作經驗,管理學博士在讀。 學習入口:https://edu.cda.cn/g ...
2025-05-12CDA持證人簡介: 楊貞璽 ,CDA一級持證人,鄭州大學情報學碩士研究生,某上市公司數據分析師。 學習入口:https://edu.cda.cn/g ...
2025-05-09CDA持證人簡介 程靖 CDA會員大咖,暢銷書《小白學產品》作者,13年頂級互聯網公司產品經理相關經驗,曾在百度、美團、阿里等 ...
2025-05-07相信很多做數據分析的小伙伴,都接到過一些高階的數據分析需求,實現的過程需要用到一些數據獲取,數據清洗轉換,建模方法等,這 ...
2025-05-06以下的文章內容來源于劉靜老師的專欄,如果您想閱讀專欄《10大業務分析模型突破業務瓶頸》,點擊下方鏈接 https://edu.cda.cn/g ...
2025-04-30CDA持證人簡介: 邱立峰 CDA 數據分析師二級持證人,數字化轉型專家,數據治理專家,高級數據分析師,擁有豐富的行業經驗。 ...
2025-04-29CDA持證人簡介: 程靖 CDA會員大咖,暢銷書《小白學產品》作者,13年頂級互聯網公司產品經理相關經驗,曾在百度,美團,阿里等 ...
2025-04-28CDA持證人簡介: 居瑜 ,CDA一級持證人國企財務經理,13年財務管理運營經驗,在數據分析就業和實踐經驗方面有著豐富的積累和經 ...
2025-04-27數據分析在當今信息時代發揮著重要作用。單因素方差分析(One-Way ANOVA)是一種關鍵的統計方法,用于比較三個或更多獨立樣本組 ...
2025-04-25CDA持證人簡介: 居瑜 ,CDA一級持證人國企財務經理,13年財務管理運營經驗,在數據分析就業和實踐經驗方面有著豐富的積累和經 ...
2025-04-25