数据可视化第二版-03部分-07章-局部与整体
光荣的三八节到了,来个充满理想年代的图片。
总结
本系列博客为基于《数据可视化第二版》一书的教学资源博客。本文主要是第07章-局部与整体可视化的案例相关。
可视化视角-局部与整体
代码实现
韦恩图
可参考:https://www.jb51.net/article/238729.htm https://pypi.org/project/matplotlib-venn/ python中Matplotlib并没有现成的函数可直接绘制venn图, 不过已经有前辈基于matplotlib.patches及matplotlib.path开发了两个轮子。 安装matplotlib_venn:
代码语言:javascript复制pip install matplotlib_venn -i https://pypi.tuna.tsinghua.edu.cn/simple
该包提供了四个主要函数:venn2、venn2_circles、venn3和venn3_circles。
venn3
韦恩图1
代码语言:javascript复制from matplotlib import pyplot as plt
from matplotlib_venn import venn3
# 1
plt.figure(figsize=(4, 4)) # 设置画布大小
plt.title("韦恩图示例")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# (Abc, aBc, ABc, abC, AbC, aBC, ABC)
v = venn3(subsets=(20, 10, 5, 15, 5, 10, 5),
set_labels=('逻辑学', '艺术修养', '大学语文'),
set_colors=('magenta', 'cyan', 'b'))
plt.show()
输出为:
代码语言:javascript复制from matplotlib import pyplot as plt
from matplotlib_venn import venn3
# 2
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.figure(figsize=(4, 4)) # 设置画布大小
v = venn3(subsets=(20, 10, 5, 15, 5, 10, 5), set_labels=('逻辑学', '艺术修养', '大学语文'), set_colors=('magenta', 'cyan', 'b'))
plt.show()
venn2
代码语言:javascript复制#导入依赖packages
import matplotlib.pyplot as plt
from matplotlib_venn import venn2,venn2_circles
# subsets参数
#绘图数据的格式,以下5种方式均可以,注意异同
# (Ab, aB, AB)
subset = [[{1,2,3},{1,2,4}],#列表list(集合1,集合2)
({1,2,3},{1,2,4}),#元组tuple(集合1,集合2)
{'10': 1, '01': 1, '11': 2},#字典dict(A独有,B独有,AB共有)
(3, 3, 2),####元组tuple(A有,B有,AB共有),注意和其它几种方式的异同点
[3,3,2]#列表list(A有,B有,AB共有)
]
for i in subset:
my_dpi=100
plt.figure(figsize=(500/my_dpi, 500/my_dpi), dpi=my_dpi) # #控制图尺寸的同时,使图高分辨率(高清)显示
g=venn2(subsets=i, #默认数据绘制venn图,只需传入绘图数据
set_colors=("#098154","#c72e29"),#设置圈的颜色,中间颜色不能修改
alpha=0.6,#透明度
normalize_to=1.0,#venn图占据figure的比例,1.0为占满
)
g=venn2_circles(subsets = i,
linestyle='--', linewidth=0.8, color="black"#外框线型、线宽、颜色
)
plt.title('subsets=%s'%str(i))
plt.show()
饼图
代码语言:javascript复制plt.pie(x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1,
startangle=0, radius=1, counterclock=True, wedgeprops=None, textprops=None, center=0, 0, frame=False,
rotatelabels=False, *, normalize=None, data=None)
代码语言:javascript复制x即每个扇形的占比的序列或数组 explode如果不是None,则是一个len(x)长度的数组,指定每一块的突出程度;突出显示,设置每一块分割出来的间隙大小 labels为每个扇形提供标签的字符串序列 colors为每个扇形提供颜色的字符串序列 autopct如果它是一个格式字符串,标签将是fmt % pct。如果它是一个函数,它将被调用。 shadow阴影 startangle从x轴逆时针旋转,饼的旋转角度 pctdistance, default: 0.6每个饼片的中心与由autopct生成的文本的开头之间距离与半径的比率,大于1的话会显示在圆外 labeldistance, default: 1.1饼状图标签绘制时的径向距离(我认为这个也与8类似是个比率)。如果设置为None,则不绘制标签,而是存储在图例()中使用。
# -*- coding:UTF-8 -*-
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
# 1
labels = '法语', '意大利语', '德语' # 建立不同类别
sizes = [60, 40, 30] # 不同类别对应的数量
fig = plt.figure(figsize=(4, 4))
ax1 = fig.add_subplot(111)
color = ['tomato', 'Gold', 'DeepSkyBlue']
ax1.pie(sizes,
labels=labels,
labeldistance=0.5,
colors=color,
textprops=dict(color='black'), # 字体颜色
autopct='%1.1f%%', # 显示数值标签
pctdistance=0.7) # 数值标签到中心点的距离
ax1.axis('equal')
plt.title('小语种学习人数饼图')
plt.show()
代码语言:javascript复制from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
# 2
labels = 'Python组', 'Java组', 'C组', 'Go组'
sizes = [25, 45, 30, 10]
fig = plt.figure(figsize=(4, 4))
explode = (0.1, 0, 0, 0) # 分割扇形
ax2 = fig.add_subplot(111)
ax2.pie(sizes, explode=explode, # 分隔扇形
labels=labels, autopct='%1.1f%%')
plt.title('不同种类程序语言使用分割饼图')
plt.show()
代码语言:javascript复制from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
# 3
labels = '男性', '女性' # 建立不同类别
sizes = [30, 70] # 不同类别对应的数量
fig = plt.figure(figsize=(4, 4))
ax1 = fig.add_subplot(111)
color = ['RoyalBlue', 'DeepPink']
ax1.pie(sizes,
labels=labels,
labeldistance=0.5,
colors=color,
textprops=dict(color='white'), # 字体颜色
autopct='%1.1f%%', # 显示数值标签
pctdistance=0.7) # 数值标签到中心点的距离
ax1.axis('equal')
plt.title('某款应用程序使用者性别饼图')
plt.show()
环形图
参考: [python] 基于matplotlib实现圆环图的绘制 可以重点看下这个链接。
wedgeprops中通过width参数设定内部圆的半径,edgecolor设置内部圆的颜色。
代码语言:javascript复制import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
# 1
labels = ['四川', '河北', '北京', '重庆', '天津'] # 设定类别
A1 = [36980.22, 35964.00, 28000.40, 19500.00, 18595.38]
color = ['yellow', 'cyan', 'lightblue', 'lightgreen', 'pink']
wedges1, texts1, autotexts1 = plt.pie(A1, autopct='%3.1f%%', radius=1, pctdistance=0.8,
colors=color, startangle=180, textprops=dict(color='black'),
wedgeprops=dict(width=0.4, edgecolor='w'))
plt.legend(wedges1, labels, fontsize=12, title='地区', loc='center right',
bbox_to_anchor=(1, 0, 0.3, 1))
plt.title('2017年四个地区生产总值')
plt.show()
代码语言:javascript复制import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
# 2
labels = ['日用品', '餐饮', '交通', '储蓄', '其他'] # 设定类别
A1 = [1000, 1500, 500, 2000, 1000]
color = ['lightpink', 'hotpink', 'MediumPurple', 'Lavender', 'seashell']
wedges1, texts1, autotexts1 = plt.pie(A1, autopct='%3.1f%%', radius=1, pctdistance=0.8,
colors=color, startangle=180, textprops=dict(color='black'),
wedgeprops=dict(width=0.4, edgecolor='w'))
plt.legend(wedges1, labels, fontsize=12, title='消费种类', loc='center right',
bbox_to_anchor=(1.1, 0, 0.3, 1))
plt.title('个人消费环形图')
plt.show()
旭日图
参考: https://pyecharts.org/#/zh-cn/intro https://pyecharts.org/#/zh-cn/basic_charts?id=sunburst:旭日图
代码语言:javascript复制from pyecharts.charts import Sunburst
from pyecharts import options as opts
data = [
opts.SunburstItem(
name="A公司",
children=[
opts.SunburstItem(
name="男装",
value=15,
children=[
opts.SunburstItem(name="上装", value=8),
opts.SunburstItem(name="下装", value=7)]
),
opts.SunburstItem(
name="女装",
value=10,
children=[
opts.SunburstItem(name="衬衫", value=5),
opts.SunburstItem(name="裙子", value=1),
opts.SunburstItem(name="裤子", value=4),
],
),
],
),
opts.SunburstItem(
name="B公司",
children=[
opts.SunburstItem(name="鞋子",
children=[
opts.SunburstItem(name="凉鞋", value=1),
opts.SunburstItem(name="运动鞋", value=2),
],
)
],
),
]
sunburst = (
Sunburst(init_opts=opts.InitOpts(width="600px", height="600px"))
.add(series_name="", data_pair=data, radius=[0, "90%"])
.set_global_opts(title_opts=opts.TitleOpts(title="旭日图示例"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}"))
.render("旭日图.html")
)
import os
os.system("旭日图.html")
园堆积图
参考:https://blog.csdn.net/LuohenYJ/article/details/119006870
代码语言:javascript复制
pip install circlify==0.15.0
代码:
代码语言:javascript复制# 圆堆积图
import circlify
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
data = [{'id': '中国', 'datum': 1015986, 'children': [
{'id': "广东", 'datum': 110760.94,
'children': [
{'id': "深圳", 'datum': 27670.24},
{'id': "广州", 'datum': 25019.11}
]},
{'id': "上海", 'datum': 38700.58},
{'id': "北京", 'datum': 36102.6},
{'id': "重庆", 'datum': 25002.79},
{'id': "浙江", 'datum': 64613,
'children': [
{'id': "杭州", 'datum': 16106},
{'id': "宁波", 'datum': 12408.7},
{'id': "温州", 'datum': 6870.9}
]}
]}]
# 计算圆圈位置
circles = circlify.circlify(
data,
show_enclosure=False,
target_enclosure=circlify.Circle(x=0, y=0, r=1)
)
# 设置画布
fig, ax = plt.subplots(figsize=(4, 4))
# 设置标题
ax.set_title('2020年中国部分地市GDP')
ax.axis('off')
lim = max(
max(
abs(circle.x) circle.r,
abs(circle.y) circle.r,
)
for circle in circles
)
plt.xlim(-lim, lim)
plt.ylim(-lim, lim)
# 画最高级的圆圈:
for circle in circles:
if circle.level != 1:
continue
x, y, r = circle
ax.add_patch(plt.Circle((x, y), r, alpha=0.5, linewidth=2, color="yellow"))
# 画第二级的圆圈:
for circle in circles:
if circle.level != 2:
continue
x, y, r = circle
ax.add_patch(plt.Circle((x, y), r, alpha=0.5, linewidth=2, color="lightblue"))
# 画第三级的圆圈:
for circle in circles:
if circle.level != 3:
continue
x, y, r = circle
label = circle.ex["id"]
ax.add_patch(plt.Circle((x, y), r, alpha=0.5, linewidth=2, color="green"))
plt.annotate(label, (x, y), ha='center', color="black")
# 设置标签
for circle in circles:
if circle.level != 2:
continue
x, y, r = circle
label = circle.ex["id"]
plt.annotate(label, (x, y), va='top', ha='center', bbox=dict(edgecolor='blue', pad=.5),
fontsize=8)
plt.show()
输出为:
voronoi一般指泰森多边形。 泰森多边形又叫冯洛诺伊图(Voronoi diagram),得名于Georgy Voronoi,是一组由连接两邻点线段的垂直平分线组成的连续多边形。
矩形树图
squarify一种坐标系,包括原点(x和y)和宽度/高度(dx和dy)的值。 从最大值到最小值排序并规范化为总面积(即dx*dy)的正值列表。 将数据生成基于matplotlib的树状图可视化
代码语言:javascript复制pip install squarify
代码语言:javascript复制# 导入第三方包
import matplotlib.pyplot as plt
import squarify
# 中文及负号处理办法
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
# 创建数据
name = ['俄罗斯', '加拿大', '中国', '美国', '巴西', '澳大利亚',
'印度', '阿根廷', '哈萨克斯坦', '苏丹', '阿尔及利亚']
income = [1707.50, 997.1, 960.1, 936.4, 854.7, 774.1, 328.8, 278, 271.1, 250.6, 238.2]
# 绘图
colors = ['steelblue', '#9999ff', 'red', 'indianred',
'green', 'yellow', 'orange', 'lightblue', 'gold', 'lightgreen', 'pink']
plot = squarify.plot(sizes=income, # 指定绘图数据
label=name, # 指定标签
color=colors, # 指定自定义颜色
alpha=0.6, # 指定透明度
value=income, # 添加数值标签
edgecolor='white', # 设置边界框为白色
linewidth=3 # 设置边框宽度为3
)
# 设置标签大小
plt.rc('font', size=9)
# 设置标题大小
plot.set_title('世界国土面积情况(单位:万平方公里)', fontdict={'fontsize': 16})
# 去除坐标轴
plt.axis('off')
# 去除上边框和右边框刻度
plt.tick_params(top='off', right='off')
# 显示图形
plt.show()
代码语言:javascript复制# 导入第三方包
import matplotlib.pyplot as plt
import squarify
# 中文及负号处理办法
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
# 2
# # 创建数据
name = ['美国', '加拿大', '中国', '德国', '意大利', '英国', '土耳其', '西班牙']
income = [529951, 23318, 83482, 126266, 152271, 79885, 52167, 163027]
# 绘图
colors = ['royalblue', 'cyan', 'red', 'violet', 'green', 'yellow', 'orange', 'lightblue']
plot = squarify.plot(sizes=income, # 指定绘图数据
label=name, # 指定标签
color=colors, # 指定自定义颜色
alpha=0.5, # 指定透明度
value=income, # 添加数值标签
linewidth=3 # 设置边框宽度为3
)
# 设置标签大小
plt.rc('font', size=9)
# 设置标题大小
plot.set_title('截止2020年4月12日的新冠肺炎感染人数', fontdict={'fontsize': 16})
# 去除坐标轴
plt.axis('off')
# 去除上边框和右边框刻度
plt.tick_params(top='off', right='off')
# 显示图形
plt.show()
漏斗图
基于matplot’lib的漏斗图
代码语言:javascript复制# 漏斗图1
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
# Polygon()可以用来传入按顺序组织的多边形顶点,从而生成出多边形
from matplotlib.collections import PatchCollection
plt.style.use('seaborn-dark') # 设置主题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams["axes.unicode_minus"] = False # 用来正常显示负号
data = [135043, 113413, 74909, 10366, 9018, 4151]
phase = ['总访客数量 ', '活跃访客数量', '注册用户数量', '预定用户数量', '支付用户数量', '复购用户数量']
visitor_num = 135043
data1 = [visitor_num / 2 - i / 2 for i in data]
data2 = [i j for i, j in zip(data, data1)]
color_list = ['#5c1d1d', '#892c2c', '#994a4a', '#c56161', '#d48989', '#e2b0b0'] # 柱子颜色
fig, ax = plt.subplots(figsize=(16, 9), facecolor='#f4f4f4')
ax.barh(phase[::-1], data2[::-1], color=color_list, height=0.7) # 柱宽设置为0.7
ax.barh(phase[::-1], data1[::-1], color='#f4f4f4', height=0.7) # 设置成背景同色
ax.axis('off')
polygons = []
for i in range(len(data)):
# 阶段
ax.text(
0, # 坐标
i, # 高度
phase[::-1][i], # 文本
color='black', alpha=0.8, size=16, ha="right")
# 数量
ax.text(
data2[0] / 2,
i,
str(data[::-1][i]) '(' str(round(data[::-1][i] / data[0] * 100, 1)) '%)',
color='black', alpha=0.8, size=18, ha="center")
if i < 5:
# 比例
ax.text(
data2[0] / 2,
4.4 - i,
str(round(data[i 1] / data[i], 3) * 100) '%',
color='black', alpha=0.8, size=16, ha="center")
# 绘制多边形
polygons.append(Polygon(xy=np.array([(data1[i 1], 4 0.35 - i),
# 因为柱状图的宽度设置成了0.7,所以一半便是0.35
(data2[i 1], 4 0.35 - i),
(data2[i], 5 - 0.35 - i),
(data1[i], 5 - 0.35 - i)])))
# 使用add_collection与PatchCollection来向Axes上添加多边形
ax.add_collection(PatchCollection(polygons,
facecolor='#e2b0b0',
alpha=0.8));
plt.title("商品购买情况分析", fontsize=18)
plt.show()
基于pyecharts的漏斗图
代码语言:javascript复制pip install openpyxl
代码语言:javascript复制# 漏斗图2
import pandas as pd
import os
os.chdir(os.path.dirname(os.path.realpath(__file__)))
data = pd.read_excel('漏斗图.xlsx', 'Sheet1')
attrs = data['环节'].tolist()
attr_value = data['人数'].tolist()
from pyecharts import options as opts
from pyecharts.charts import Funnel
c = (
Funnel()
.add("商品", [list(z) for z in zip(attrs, attr_value)],
label_opts=opts.LabelOpts(position="inside"),
)
.set_global_opts(title_opts=opts.TitleOpts(title="漏斗图示例"))
.render("漏斗图.html")
)
import os
os.system("漏斗图.html")
输出为:
基于pyecharts的治愈率漏斗图
代码语言:javascript复制from pyecharts import options as opts
from pyecharts.charts import Funnel
data = [13500, 10000, 9000, 7000]
phase = ['检查', '阳性', '手术治疗', '治愈']
c = (
Funnel()
.add("阶段", [list(z) for z in zip(phase, data)])
.set_global_opts(title_opts=opts.TitleOpts(title="漏斗图"))
.render("治愈率漏斗图.html")
)
import os
os.system("治愈率漏斗图.html")
虚拟环境相关命令汇集
激活conda
代码语言:javascript复制d:ProgramDataAnaconda3Scriptsactivate
创建python版本的命令
代码语言:javascript复制conda create -n py10 python=3.10
查看当前的python版本
代码语言:javascript复制conda env list
切换到指定的python版本
代码语言:javascript复制conda activate py10
激活虚拟环境后,安装python虚拟环境
代码语言:javascript复制python -m venv venv202302
切换路径到文件当前路径
代码语言:javascript复制import os
print(os.getcwd(),"-----------------")
# os.chdir("./")
os.chdir(os.path.dirname(os.path.realpath(__file__)))
print(os.getcwd(),"-----------------")
临时使用阿里镜像安装python包
代码语言:javascript复制pip install 包名 -i https://mirrors.aliyun.com/pypi/simple/
持久使用阿里镜像安装python包
代码语言:javascript复制pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/