python 系列 05 -数据可视化

1 安装Plotly库

关于库的选择,这里不再对常用的可视化库作对比,直接用Plotly。首先安装:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple Plotly # 其中-i选项是清华源,可加快下载速度

2 常用图表绘制

示例尽量采用同一组数据源去生成不同的图表。以下是简单的数据示例,数据是虚拟的,模拟四个城市的降雨量:

在这里插入图片描述

2.1 折线图示例

# -*- coding: utf-8 -*-
import plotly.offline as py                    
import plotly.graph_objs as go
import plotly.express as px

# x轴显示月份
month = ['1月份', '2月份', '3月份', '4月份', '5月份', '6月份', '7月份', '8月份', '9月份', 
         '10月份', '11月份', '12月份']

# y轴显示降雨量
guangzhou = [20,18,17,19,16,22,27,15,16,19,21,18]
shanghai = [14,15,13,17,16,15,18,19,21,20,18,16]
chongqing = [17,16,18,20,17,23,21,20,23,14,17,20]
xian = [21,20,23,22,21,20,19,17,20,18,23,21]


#折线图,x,y指定x,y轴显示的数据集,name是图例,line指定线样式
line1 = go.Scatter(
    x = month,
    y = guangzhou,
    name = '广州2022降雨量',
    line = dict(color = ('rgb(245, 12, 20)'), width = 2)
)

line2 = go.Scatter(
    x = month,
    y = shanghai,
    name = '上海2022降雨量',
    line = dict(color = ('rgb(20, 213, 24)'), width = 2)
)

line3 = go.Scatter(
    x = month,
    y = chongqing,
    name = '重庆2022降雨量',
    line = dict(color = ('rgb(20, 14, 245)'), width = 2)
)

line4 = go.Scatter(
    x = month,
    y = xian,
    name = '西安2022降雨量',
    line = dict(color = ('rgb(245, 245, 20)'), width = 2)
)


lines = [line1,line2,line3,line4]

fig = go.Figure(lines) 
fig.show()



'''
#柱状图
#text为标注,textposition标注位置
bar1 = go.Bar(x = month, y = guangzhou,name = '广州2022降雨量',text=guangzhou,textposition='auto')
bar2 = go.Bar(x = month, y = shanghai,name = '上海2022降雨量')
bar3 = go.Bar(x = month, y = chongqing,name = '重庆2022降雨量')
bar4 = go.Bar(x = month, y = xian,name = '西安2022降雨量')

bars = [bar1,bar2,bar3,bar4]

fig = go.Figure(bars)
#旋转座标轴(x轴旋转45度)用于x轴字符串过长
fig.update_layout(xaxis_tickangle=-45)
fig.show()
'''

'''
#饼图
#pull参数是爆炸饼图效果,即将这两个月份的块拉出到圆形外边一部分
pie = go.Pie(values= guangzhou, labels=month, title='广州2022年降雨量',
pull=[0.2,0,0,0,0,0,0,0,0.1,0,0,0])
fig = go.Figure(pie)
fig.show()
'''

'''
#散点图
#散点图横纵均为数字
month_list = [1,2,3,4,5,6,7,8,9,10,11,12]
#markers为散点图
points_1 = go.Scatter(x=month_list,y=guangzhou,mode='markers',name='广州')
points_2 = go.Scatter(x=month_list,y=shanghai,mode='markers',name='上海')
points_3 = go.Scatter(x=month_list,y=chongqing,mode='markers',name='重庆')
points_4 = go.Scatter(x=month_list,y=xian,mode='markers',name='西安')
data = [points_1,points_2,points_3,points_4]
fig = go.Figure(data)
fig.show() 

'''

运行代码会生成一个包含js的html页面,并直接在默认浏览器打开,效果如下所示:

在这里插入图片描述

以下示例图表的代码均在第一个示例代码中给出,分别打开注释的部分即可。

2.2 柱状图

在这里插入图片描述

2.3 饼图

在这里插入图片描述

2.4 散点图

在这里插入图片描述

3 Plotly模块

Plotly库包含三个主要的模块:

  • plotly.plotly :包含需要Plotly服务器响应的函数。
  • plotly.graph_objs: 最主要的模块,主要包含以下对象:
    • Figure: 图
      • Data:数据
      • Layout:布局
    • 一些基本的图表绘制方法:散点,直方图等。
  • plotly.tools:工具模块,包含许多有用的功能。

Plotly 还包含许多子包,来自官网部分子包的截图:
在这里插入图片描述
可以 单击此处 进行了解。

4 导出静态图像

导出静态图像依赖kaleido库,使用pip install kaleido 安装。导出图像很简单:

import plotly.io as pio # 引入plotly的io库
pio.write_image(fig, '01.png') # 在代码结尾处,将fig导出为图像

导出图像示例:

在这里插入图片描述

5 定制

5.1 定制轴外观

示例代码中添加一个布局:

#布局
layout=go.Layout(
    #标题,x是位置,距离左边50%,大致居中。
    title=dict(text="2020年降雨量分布",x=0.5),
    
    #x轴定义
    xaxis=dict(
        title='月份', # 轴标题
        showgrid=True, # 显示网格线,默认True
        showline=True, #是否显示座标轴
        linecolor='#00ffff', #座标轴颜色
        linewidth=2, #座标轴宽度
        gridcolor='#bdbdbd', # 网格线颜色
        gridwidth=1 # 网格线宽度
        
    ),
    #y轴定义
    yaxis=dict(
        showgrid=True,#是否显示网格线
        zeroline=True,#是否绘制0刻度线
        showline=True,#是否显示座标轴
        gridcolor='#bdbdbd',
        gridwidth=1,
        zerolinecolor='#ff0000',#0刻度线颜色
        zerolinewidth=2,# 0刻度线宽度
        linecolor='#0000ff', #座标轴颜色
        linewidth=2, #座标轴宽度
        title='降雨量',
        titlefont=dict( #字体
            family='Arial, sans-serif',
            size=18,
            color='lightgrey'
        )
    )
)

#更多参数参见官方文档

生成图表时采用fig = go.Figure(lines,layout=layout) ,比原来的方法增加一个参数,传入上面定义的布局,生成的图表:

在这里插入图片描述

5.2 转换数据属性

通过修改layout.Updatemenu属性可修改同一个图表的展现样式,如:从柱状图切换到折线图。代码种增加修改updatemenu属性的代码如下,在调用fig.show()之前:

fig.layout.update(
    updatemenus=[
        go.layout.Updatemenu(
            type = "buttons",
            direction = "left",
            buttons=list([
                dict(
                    args=["type", "bar"], label="柱状图", method="restyle"
                ),
                dict(
                    args=["type", "scatter"], label="折线图", method="restyle"
                )
            ])
        )
    ]
)
# 其中method可设置为以下四种:
# restyle: 修改数据或数据属性
# relayout: 修改布局属性
# update: 修改数据和布局属性
# animate: 修改数据和布局属性

效果如下,默认显示为柱状图,当点击折线图按钮时,图表即可显示为折线图,点击柱状图又会显示为柱状图。
在这里插入图片描述
在这里插入图片描述
按钮同样可以修改为下拉列表:

fig.layout.update(
    updatemenus=[
        go.layout.Updatemenu(
        		#下拉列表
            type = "dropdown",
            #列表弹出方向
            direction = "down",
            buttons=list([
                dict(
                    args=["type", "bar"], label="柱状图", method="restyle"
                ),
                dict(
                    args=["type", "scatter"], label="折线图", method="restyle"
                )
            ])
        )
    ]
)

效果如下:

在这里插入图片描述

5.3 图例(legend)定制

fig.update_layout(
    legend=dict(
        #图例按照座标定位,表示位于左上角
        x=0,
        y=1,
        #图例名称
        title_text='降雨量',
        #字体
        font=dict(
            size=12,
            color="black"
        ),
        #背景色
        bgcolor="yellowgreen",
        #边框色
        bordercolor="Pink",
        #边框宽度
        borderwidth=2
    )
)

效果如下:
在这里插入图片描述

颜色的取值范围:

				aliceblue, antiquewhite, aqua, aquamarine, azure,
            beige, bisque, black, blanchedalmond, blue,
            blueviolet, brown, burlywood, cadetblue,
            chartreuse, chocolate, coral, cornflowerblue,
            cornsilk, crimson, cyan, darkblue, darkcyan,
            darkgoldenrod, darkgray, darkgrey, darkgreen,
            darkkhaki, darkmagenta, darkolivegreen, darkorange,
            darkorchid, darkred, darksalmon, darkseagreen,
            darkslateblue, darkslategray, darkslategrey,
            darkturquoise, darkviolet, deeppink, deepskyblue,
            dimgray, dimgrey, dodgerblue, firebrick,
            floralwhite, forestgreen, fuchsia, gainsboro,
            ghostwhite, gold, goldenrod, gray, grey, green,
            greenyellow, honeydew, hotpink, indianred, indigo,
            ivory, khaki, lavender, lavenderblush, lawngreen,
            lemonchiffon, lightblue, lightcoral, lightcyan,
            lightgoldenrodyellow, lightgray, lightgrey,
            lightgreen, lightpink, lightsalmon, lightseagreen,
            lightskyblue, lightslategray, lightslategrey,
            lightsteelblue, lightyellow, lime, limegreen,
            linen, magenta, maroon, mediumaquamarine,
            mediumblue, mediumorchid, mediumpurple,
            mediumseagreen, mediumslateblue, mediumspringgreen,
            mediumturquoise, mediumvioletred, midnightblue,
            mintcream, mistyrose, moccasin, navajowhite, navy,
            oldlace, olive, olivedrab, orange, orangered,
            orchid, palegoldenrod, palegreen, paleturquoise,
            palevioletred, papayawhip, peachpuff, peru, pink,
            plum, powderblue, purple, red, rosybrown,
            royalblue, rebeccapurple, saddlebrown, salmon,
            sandybrown, seagreen, seashell, sienna, silver,
            skyblue, slateblue, slategray, slategrey, snow,
            springgreen, steelblue, tan, teal, thistle, tomato,
            turquoise, violet, wheat, white, whitesmoke,
            yellow, yellowgreen

也可以直接使用16进制颜色值 如bgcolor:#ff0000.

6 同一个布局显示多图

import plotly.subplots as sp #首先在文件头部引入子图的包

#定义显示图的行列数和图表的类型,类型不指定默认是xy
#饼图的类型不是xy。所以此处定义了图形类型。
fig = sp.make_subplots(
    rows=2,
    cols=2,
    specs=[[{"type": "xy"}, {"type": "xy"}],
           [{"type": "xy"}, {"type": "domain"}]],
)
#然后添加数据集
fig.add_traces(lines,1,1) # lines在上面的示例代码中有定义,篇幅太长这里不再列出。
fig.add_traces(bars,1,2) # bars数据集也在上面示例代码里
fig.add_traces(data,2,1) # data也在示例代码有定义
fig.add_trace(pie,2,2)  # pie在上面的示例代码中

#更新视图高度,关闭图例,宽度是width
#这一步可省略,会有默认宽高,而且四个图的图例都都在右边。
fig.update_layout(height=700, showlegend=False)
fig.show()

生成的图表效果如下:

在这里插入图片描述

6.1 关于图形类型的说明

  • xy: 二维的散点scatter、柱状图bar等。
  • scene: 3维的scatter3d、球体cone.
  • polar: 极坐标图形如scatterpolar, barpolar等.
  • ternary: 三元图如scatterternary
  • mapbox: 地图如scattermapbox
  • domain: .针对有一定域的图形,如饼图pie, parcoords, parcats

7 其它图表示例

7.1 堆叠条状图,表格,直方图,箱图

# -*- coding: utf-8 -*-
import plotly.offline as py                    
import plotly.graph_objs as go
import plotly.express as px
import plotly.io as pio
import plotly.subplots as sp
import numpy as np

# x轴显示月份
month = ['1月份', '2月份', '3月份', '4月份', '5月份', '6月份', '7月份', '8月份', '9月份', 
         '10月份', '11月份', '12月份']

# y轴显示降雨量
guangzhou = [20,18,17,19,16,22,27,15,16,19,21,18]
shanghai = [14,15,13,17,16,15,18,19,21,20,18,16]
chongqing = [17,16,18,20,17,23,21,20,23,14,17,20]
xian = [16,20,23,22,21,20,19,17,20,18,23,21]


#布局
layout=go.Layout(
    title=dict(text="2020年降雨量分布",x=0.5),
    barmode='stack',#堆积柱状图
    showlegend=False
)

#堆叠柱状图
bar1 = go.Bar(x = month, y = guangzhou,name = '广州2022降雨量',)
bar2 = go.Bar(x = month, y = shanghai,name = '上海2022降雨量')
bar3 = go.Bar(x = month, y = chongqing,name = '重庆2022降雨量')
bar4 = go.Bar(x = month, y = xian,name = '西安2022降雨量')

bars = [bar1,bar2,bar3,bar4]


#表格
#准备表格数据
header_list = month.insert(0,'城市') #表头
city_column = ['广州','上海','重庆','西安'] #第1列
table_cells = []
table_cells.append(city_column) # piotly表格数据按列追加
for i in range(0,12):
    column = []
    column.append(guangzhou[i])
    column.append(shanghai[i])
    column.append(chongqing[i])
    column.append(xian[i])
    table_cells.append(column)

table = go.Table(
    #表头
    header=dict(
        values=month,
        line_color='gray',
        align='center'
    ),
    #单元格
    cells=dict(
        values=table_cells, 
        line_color='gray',#线颜色
        align='center'
    )
)

data = [table]


#直方图
his1 = go.Histogram(x=guangzhou,name='广州')
his2 = go.Histogram(x=shanghai,name='上海')
his3 = go.Histogram(x=chongqing,name='重庆')
his4 = go.Histogram(x=xian,name='西安')
his = [his1,his2,his3,his4]

#箱图
box1 = go.Box(y=guangzhou,name='广州')
box2 = go.Box(y=shanghai,name='上海')
box3 = go.Box(y=chongqing,name='重庆')
box4 = go.Box(y=xian,name='西安')
box = [box1,box2,box3,box4]




#定义显示图的行列数和图表的类型,类型不指定默认是xy
fig = sp.make_subplots(
    rows=2,
    cols=2,
    specs=[
        [
            {"type": "xy"},
            {"type": "domain"}
        ],
        [
            {"type": "xy"},
            {"type": "xy"},
        ]
    ],
)
fig.add_traces(bars,1,1)
fig.add_traces(table,1,2)
fig.add_traces(his,2,1)
fig.add_traces(box,2,2)

fig.update_layout(layout)

fig.show()

在这里插入图片描述

7.2 小提琴图,密度图,箭袋图,热力图

# -*- coding: utf-8 -*-
import plotly.offline as py                    
import plotly.graph_objs as go
import plotly.express as px
import plotly.io as pio
import plotly.subplots as sp
import numpy as np
import plotly.figure_factory as ff


month = ['1月份', '2月份', '3月份', '4月份', '5月份', '6月份', '7月份', '8月份', '9月份', 
         '10月份', '11月份', '12月份']


guangzhou = [12,14,16,19,21,23,21,19,17,15,13,11]
shanghai = [24,22,20,18,16,14,12,14,16,18,20,24]
chongqing = [17,16,18,20,17,23,21,20,23,14,17,20]
xian = [16,20,23,22,21,20,19,17,20,18,23,21]

#布局
layout=go.Layout(
    title=dict(text="2020年降雨量分布",x=0.5),
    showlegend=False,
)

#小提琴图
vi1 = go.Violin(y = guangzhou,name = '广州')
vi2 = go.Violin(y = shanghai,name = '上海')
vi3 = go.Violin(y = chongqing,name = '重庆')
vi4 = go.Violin(y = xian,name = '西安')

vi = [vi1,vi2,vi3,vi4]

#等高线图
#等高线图是对三维平面的二维描述,需要z轴。
data = [guangzhou,shanghai,chongqing,xian]
#showscale是显示颜色条,参见热力图的颜色条显示
con = go.Contour(x=month,y=['广州','上海','重庆','西安'],z=data,name='降雨量',showscale=False)


#箭袋图(速度图)
#降雨量的数据在这里不适用,这里用numpy模拟出数据
x,y = np.meshgrid(np.arange(-2, 2, .2), np.arange(-2, 2, .25))
z = x*np.exp(-x**2 - y**2)
v, u = np.gradient(z, .2, .2)

a,b = np.meshgrid(np.arange(-3, 3, .3), np.arange(-3, 3, .50))
c = a*np.exp(-a**2 - b**2)
n, m = np.gradient(c, .2, .2)
#x:箭头位置的x坐标,y:箭头位置的y坐标
#u: 箭头向量的 x 个分量,v:箭头向量的y分量
fig1 = ff.create_quiver(x, y, u, v,name='A数据集')
fig2 = ff.create_quiver(a, b, m, n,name='B数据集')
#箭袋图多数据集添加
fig1.add_traces(data=fig2.data)

#热力图
city=['广州','上海','重庆','西安']
h_data = [guangzhou,shanghai,chongqing,xian]
heat = go.Heatmap(x=month,y=city,z=h_data,type='heatmap',name='降雨量')
#定义显示图的行列数和图表的类型,类型不指定默认是xy
fig = sp.make_subplots(
    rows=2,
    cols=2,
    specs=[
        [
            {"type": "xy"},
            {"type": "xy"}
        ],
        [
            {"type": "xy"},
            {"type": "xy"},
        ]
    ],
)
fig.add_traces(vi,1,1)
fig.add_traces(con,1,2)
fig.add_traces(fig1.data,2,1)
fig.add_traces(heat,2,2)

fig.update(layout=layout)

fig.show()

在这里插入图片描述

7.3 极座标图,雷达图,OHLC图,瀑布图

# -*- coding: utf-8 -*-
import plotly.offline as py                    
import plotly.graph_objs as go
import plotly.express as px
import plotly.io as pio
import plotly.subplots as sp
import numpy as np
import plotly.figure_factory as ff


month = ['1月份', '2月份', '3月份', '4月份', '5月份', '6月份', '7月份', '8月份', '9月份', 
         '10月份', '11月份', '12月份']


guangzhou = [12,14,16,19,21,23,21,19,17,15,13,11]
shanghai = [24,22,20,18,16,14,12,14,16,18,20,24]
chongqing = [17,16,18,20,17,23,21,20,23,14,17,20]
xian = [16,20,23,22,21,20,19,17,20,18,23,21]


#布局
layout=go.Layout(
    title=dict(text="2020年降雨量分布",x=0.5),
)

#极座标图
polar1 = go.Scatterpolar( theta = guangzhou,name = '广州',mode='lines')
polar2 = go.Scatterpolar( theta = shanghai,name = '上海',mode='lines')
polar3 = go.Scatterpolar( theta = chongqing,name = '重庆',mode='lines')
polar4 = go.Scatterpolar( theta = xian,name = '西安',mode='lines')
polar = [polar1,polar2,polar3,polar4]

#雷达图
radar1 = go.Scatterpolar(r=guangzhou, theta = month,name = '广州',fill='toself')
radar2 = go.Scatterpolar(r=shanghai, theta = month,name = '上海',fill='toself')
radar3 = go.Scatterpolar(r=chongqing, theta = month,name = '重庆',fill='toself')
radar4 = go.Scatterpolar(r=xian, theta = month,name = '西安',fill='toself')
radar = [radar1,radar2,radar3,radar4]

#OHLC 图
#这里用四个城市的降雨量分别模拟 开,关,高,低数据
ohlc1 = go.Ohlc(x=month,open=guangzhou,high=shanghai,low=chongqing,close=xian,name='降雨量')
ohlc=[ohlc1]

#瀑布图
water1 = go.Waterfall(
    x=month,
    y=guangzhou,
    measure = [
        "relative", "relative", "total", "relative", "relative", "total",
        "relative", "relative", "total", "relative", "relative", "total"
    ],
    name='广州',
)
water2 = go.Waterfall(x=month,y=shanghai,base=5,name='上海')
water3 = go.Waterfall(x=month,y=chongqing,name='重庆')
water4 = go.Waterfall(x=month,y=xian,name='西安')
water = [water1,water2,water3,water4]




#定义显示图的行列数和图表的类型,类型不指定默认是xy
fig = sp.make_subplots(
    rows=2,
    cols=2,
    specs=[
        [
            {"type": "polar"},
            {"type": "polar"}
        ],
        [
            {"type": "xy"},
            {"type": "xy"},
        ]
    ],
)
fig.add_traces(polar,1,1)

fig.add_traces(radar,1,2)
fig.add_traces(ohlc,2,1)
fig.add_traces(water,2,2)

fig.update(layout=layout)

fig.show()

在这里插入图片描述

7.4 漏斗图,3D散点图

# -*- coding: utf-8 -*-
import plotly.offline as py                    
import plotly.graph_objs as go
import plotly.express as px
import plotly.io as pio
import plotly.subplots as sp
import numpy as np
import plotly.figure_factory as ff


month = ['1月份', '2月份', '3月份', '4月份', '5月份', '6月份', '7月份', '8月份', '9月份', 
         '10月份', '11月份', '12月份']


guangzhou = [12,14,16,19,21,23,21,19,17,15,13,11]
shanghai = [24,22,20,18,16,14,12,14,16,18,20,24]
chongqing = [17,16,18,20,17,23,21,20,23,14,17,20]
xian = [16,20,23,22,21,20,19,17,20,18,23,21]


#布局
layout=go.Layout(
    title=dict(text="2020年降雨量分布",x=0.5),
)

#漏斗图
funnel1 = go.Funnel(x=guangzhou,y = month,name = '广州')
funnel2 = go.Funnel(x=shanghai,y=month,name = '上海')
funnel3 = go.Funnel(x=chongqing,y=month,name = '重庆')
funnel4 = go.Funnel(x=xian,y=month,name = '西安')
funnel = [funnel1,funnel2,funnel3,funnel4]

#3D 散点图
z=[5,10,15,20,25,30,35,40,45]
d1 = go.Scatter3d(x=month,y=guangzhou,name = '广州',z=z,)
d2 = go.Scatter3d(x=month,y=shanghai,name = '上海',z=z)
d3 = go.Scatter3d(x=month,y=chongqing,name = '重庆',z=z)
d4 = go.Scatter3d(x=month,y=xian,name = '西安',z=z)
d = [d1,d2,d3,d4]


#定义显示图的行列数和图表的类型,类型不指定默认是xy
fig = sp.make_subplots(
    rows=1,
    cols=2,
    specs=[
        [
            {"type": "xy"},
            {"type": "scene"}
        ],
        
    ],
)
fig.add_traces(funnel,1,1)
fig.add_traces(d,1,2)

fig.update(layout=layout)

fig.show()

在这里插入图片描述

8 生成离线图表供html使用

8.1 第一种方式,生成离线html

生成图表时不要使用fig.show(),使用如下方式,生成一个离线的html文件。

#fig.show()

#import plotly.offline as py
#auto_open=False可以避免在批量生成html时在本地浏览器打开
py.plot(data, filename='file.html',auto_open=False)

之后可以在页面中使用iframe来包含这个html。如果这个html文件需要在外网环境上使用,则可以借助github pages 或者 giteepages。需要将这个页面上传到github,或者gitee。

8.2 第二种方式,直接生成div,以dom节点的方式放入html

演示方便,随便创建了一个html文件,项目中用什么模板技术可相对调整:

#生成div代码,这里先去除js,防止js插入到div中
div = py.plot(data, include_plotlyjs=False, output_type='div')

#创建演示html,并在头部引入plotly js
html = '''
<html>
    <head>
    <title>Test</title>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    </head>
<body>
    <h1 style="text-align:center;">降雨量div演示</h1>'''
html += div
html += '</body>'
html += '</html>'


f = open('test.html','w')
f.write(html)
f.close()

生成的html效果如下:
在这里插入图片描述

-- THE END --
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值