数据可视化第二版-03部分-07章-局部与整体

2023-10-16 17:11:17 浏览数 (2)

数据可视化第二版-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)

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,则不绘制标签,而是存储在图例()中使用。

代码语言:javascript复制
# -*- 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/

0 人点赞