天天看點

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

雲栖号: https://yqh.aliyun.com 第一手的上雲資訊,不同行業精選的上雲企業案例庫,基于衆多成功案例萃取而成的最佳實踐,助力您上雲決策!

導讀:資料分析時經常用到的折線圖,你真的懂了嗎?可以用來呈現哪些資料關系?在資料分析過程中可以解決哪些問題?怎樣用Python繪制折線圖?本文逐一為你解答。

作者:屈希峰,資深Python工程師,知乎多個專欄作者

來源:大資料DT(ID:hzdashuju)

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

01 概述

折線圖(Line)是将排列在工作表的列或行中的資料進行繪制後形成的線狀圖形。折線圖可以顯示随時間(根據常用比例設定)而變化的連續資料,非常适用于顯示在相等時間間隔下資料的趨勢。

在折線圖中,資料是遞增還是遞減、增減的速率、增減的規律(周期性、螺旋性等)、峰值等特征都可以清晰地反映出來。是以,折線圖常用來分析資料随時間的變化趨勢,也可用來分析多組資料随時間變化的互相作用和互相影響。

例如,可用來分析某類商品或是某幾類相關的商品随時間變化的銷售情況,進而進一步預測未來的銷售情況。在折線圖中,一般水準軸(x軸)用來表示時間的推移,并且間隔相同;而垂直軸(y軸)代表不同時刻的資料的大小。如圖0所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖0 折線圖

02 執行個體

折線圖代碼示例如下所示。

  • 代碼示例1
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖1 代碼示例1運作結果

代碼示例1仍以最簡單的方式繪制第一張折線圖。line()方法的參數說明如下。

  • p.line(x, y, **kwargs)參數說明

1.x (:class:

~bokeh.core.properties.NumberSpec

) : x坐标。

2.y (:class:

~bokeh.core.properties.NumberSpec

) : y坐标。

3.line_alpha (:class:

~bokeh.core.properties.NumberSpec

) : (default: 1.0) 輪廓線透明度。

4.line_cap ( :class:

~bokeh.core.enums.LineCap

) : (default: 'butt') 線端。

5.line_color (:class:

~bokeh.core.properties.ColorSpec

) : (default: 'black') 輪廓線顔色,預設:黑色。

6.line_dash (:class:

~bokeh.core.properties.DashPattern

) : (default: []) 虛線,類型可以是序列,也可以是字元串('solid', 'dashed', 'dotted', 'dotdash', 'dashdot')。

7.line_dash_offset (:class:

~bokeh.core.properties.Int

) : (default: 0) 虛線偏移。

8.line_join (:class:

~bokeh.core.enums.LineJoin

) : (default: 'bevel')。

9.line_width (:class:

~bokeh.core.properties.NumberSpec

) : (default: 1) 線寬。

10.name (:class:

~bokeh.core.properties.String

) : 圖元名稱。

11.tags (:class:

~bokeh.core.properties.Any

) :圖元标簽。

12.alpha (float) : 一次性設定所有線條的透明度。

13.color (Color) : 一次性設定所有線條的顔色。

14.source (ColumnDataSource) : Bokeh特有資料格式(類似于Pandas Dataframe)。

15.legend (str) : 圖元的圖例。

16.x_range_name (str) : x軸範圍名稱。

17.y_range_name (str) : y軸範圍名稱。

18.level (Enum) : 圖元渲染級别。

  • 代碼示例2
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖2 代碼示例2運作結果

代碼示例2第3行使用multi_line()方法,實作一次性繪制兩條折線,同時,在參數中定義不同折線的顔色。如果使用Pandas Dataframe,則可以同時繪制不同列的資料。multi_line()方法的參數說明如下。

  • p.multi_line(xs, ys, **kwargs)參數說明

1.xs (:class:

~bokeh.core.properties.NumberSpec

) :x坐标,清單。

2.ys (:class:

~bokeh.core.properties.NumberSpec

) :y坐标,清單。

其他參數同line。

  • 代碼示例3
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖3 代碼示例3運作結果

代碼示例3第13、15、16行使用line()方法逐一繪制折線,該方法的優點是基本資料清晰,可在不同線條繪制過程中直接定義圖例。讀者也可以使用multi_line()方法一次性繪制三條折線,然後再繪制折線上的資料點。同樣,既可以在函數中預定義圖例,也可以用Lengend方法單獨進行定義,在後會對圖例進行詳細說明。

  • 代碼示例4
1p.legend.location = "top_left"  # 圖例位于左上  
2p.legend.click_policy="hide" # 點選圖例顯示、隐藏圖形  
3show(p)  # 自行測試效果           

運作結果如圖4所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖4 代碼示例4運作結果

代碼示例4在代碼示例3的基礎上增加了圖例的位置、顯示或隐藏圖形屬性;通過點選圖例,可實作圖形的顯示或隐藏,當折線數目較多或者顔色幹擾閱讀時,可以通過該方法實作對某一條折線資料的重點關注。這種通過圖例、工具條、控件實作資料人機互動的可視化方式,正是Bokeh得以在GitHub火熱的原因,建議在工作實踐中予以借鑒。

  • 代碼示例5
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖5 代碼示例5運作結果

代碼示例5第15、16行使用line()方法繪制兩組不同顔色的曲線。

  • 代碼示例6
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖6 代碼示例6運作結果

代碼示例6第19行中,生成繪圖資料時,同時生成圖例名稱清單;第37、43行使用multi_line()方法一次性繪制6條曲線,并預定義圖例。

  • 代碼示例7
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖7 代碼示例7運作結果

代碼示例7與代碼示例3相似,第10、19、21行對曲線的屬性進行自定義,注意虛線的幾種形式('solid', 'dashed', 'dotted', 'dotdash', 'dashdot'),讀者可以自行替換測試。

  • 代碼示例8
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='<font face="Arial" size="3">@$name{0.0} $name per 1,000 people in @year</font>')  
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖8 代碼示例8運作結果

代碼示例8第22、23行通過line()方法繪制兩條曲線,嚴格上講這兩條曲線并不是Bokeh時間序列的标準繪制方法。第17行定義了x軸刻度的間隔以及中間刻度數,讀者可以嘗試将num_minor_ticks=10的顯示效果與圖8進行對比;第18行定義了y軸的資料顯示格式。

  • 代碼示例9
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖9 代碼示例9運作結果

代碼示例9使用multi_line()方法在二維空間展示洛倫茲空間向量,示例中的資料生成稍微有點複雜,可以直覺感受可視化之下的資料之美,有興趣的讀者可以深入了解。

  • 代碼示10
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖10 代碼示10運作結果

代碼示例10增加了Bokeh控件複選框,第12、13、14行使用line()方法繪制3條曲線;第16行定義複選框,并在18行定義回調函數,通過該回調函數控制3條曲線的可視狀态;第24行将複選框、繪圖并在一行進行顯示。

  • 代碼示例11
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖11 代碼示例11運作結果

代碼示例11增加點選曲線的互動效果,第20、21、22行使用line()方法繪制3條曲線;第26行定義曲線再次被點選時的效果:圖11中左下方會動态顯示目前選中的是哪條顔色的曲線。

  • 代碼示例12
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所示。

什麼是折線圖?怎樣用Python繪制?怎麼用?終于有人講明白了

圖12 代碼示例12運作結果

代碼示例12使用models接口進行曲線繪制,注意第10、17、20行的繪制方法,這種繪圖方式在實踐中基本很少用到,僅作了解。

原文釋出時間:2020-01-06

本文作者:屈希峰

本文來自阿裡雲雲栖号合作夥伴“

大資料DT

”,了解相關資訊可以關注“