《python编程从入门到实践》15 生成数据

image


📘 第15章 教程:生成数据

数据可视化是指通过可视化表示来探索数据。Python提供了多个强大的可视化库,本章将使用MatplotlibPlotly来实现不同形式的图表。

常用参数及讲解

一、 Matplotlib 常用方法与参数

1. 折线图 plot()

  • x, y:必要参数,分别代表横纵坐标的数据序列。
  • linewidth (或 lw):线条粗细。例如 linewidth=2 使线条更醒目(对应15.2.1)。
  • color线条颜色。支持颜色名称(如 'red')、缩写(如 'r')或十六进制码。
  • label图例标签。配合 ax.legend() 使用,用于区分多条线。
  • marker数据点标记样式。如 marker='o'(圆圈)、marker='s'(方块)。
  • markersize (或 ms):数据点标记的大小。

2. 散点图 scatter()

  • x, y:横纵坐标数据。
  • s数据点的尺寸(size)。可传入单个数值统一设置,也可传入列表逐点设置大小。
  • c数据点的颜色。可传入单一颜色名;若要实现颜色渐变,可传入一个数值列表,此时需配合 cmap 使用(对应15.2.9)。
  • cmap颜色映射。仅当 c 为数值序列时生效,将数值映射到色谱。常用值如 'Reds', 'Blues', 'viridis', 'plasma' 等。
  • edgecolors:数据点边缘的颜色,常设为 'none' 以消除边缘让散点更柔和。
  • alpha透明度。取值 0.0(全透明)到 1.0(不透明),在密集散点图中非常有用,可凸显数据聚集区域。

3. 样式与刻度定制方法

  • plt.style.use('stylename')全局样式设置。常用内置样式如 'seaborn', 'ggplot', 'bmh' 等,可直接改变图表整体美感(对应15.2.3)。
  • ax.set_title("Title", fontsize=14):设置图表标题及字体大小。
  • ax.set_xlabel("X_Label", fontsize=14) / ax.set_ylabel(...):设置坐标轴标签及字体大小。
  • ax.tick_params(axis='both', labelsize=12)定制刻度标记axis 指定作用于哪个轴('x', 'y''both'),labelsize 设置刻度字号。
  • ax.set_xticks([list]):设置 x 轴刻度的位置(传入数值列表)。
  • ax.set_xticklabels([list], rotation=45):设置 x 轴刻度的文本标签rotation 用于旋转角度防重叠(对应15.2.7 及日期图)。
  • ax.axis([xmin, xmax, ymin, ymax])校正绘图。直接设定坐标轴的起止范围;若传入 False'off' 则隐藏坐标轴(对应15.2.2)。

4. 其他方法

  • plt.savefig('filename.png', bbox_inches='tight')自动保存绘图bbox_inches='tight' 是极常用的参数,用于裁剪图表周围多余的空白区域(对应15.2.10)。

二、 Plotly Express 常用方法与参数

(第3版全面采用 Plotly Express 模块,导入方式通常为 import plotly.express as px

1. 直方图 px.histogram()

用于掷骰子项目的结果分布可视化:

  • data_frame:传入的数据源,通常为 Pandas DataFrame 或字典。
  • x:指定作为 x 轴的数据列名或数据列表(如掷骰子的结果)。
  • y:指定 y 轴数据。若省略,默认统计 x 轴各值出现的频次。
  • nbins直方图的柱子数量。调整此参数可控制分布的精细度。
  • histnorm:归一化模式。如设为 'percent' 可显示百分比而非绝对频数。
  • barmode:多组数据时的排列模式。如 'group'(并排显示)或 'overlay'(重叠显示,需配合透明度 opacity)。

2. 柱状图/条形图 px.bar()

  • x, y:横纵坐标数据。
  • color分组/颜色区分参数。传入分类字段名,自动按类别着色并生成图例。
  • barmode:同上,'group' 并排,'relative' 堆叠。

3. 图表更新与定制方法

Plotly Express 生成的 fig 对象可通过 .update_ 系列方法深度定制:

  • fig.update_layout(title_text="My Title", xaxis_title="X", yaxis_title="Y")
    • title_text:图表主标题。
    • xaxis_title / yaxis_title:坐标轴标题(PX 默认可能不显轴标题,需手动开启)。
  • fig.update_traces(opacity=0.75, marker_line_width=1, marker_line_color='white')
    • opacity透明度,0-1之间,在重叠柱状图(如同时掷两个骰子)中极为关键。
    • marker_line_width / marker_line_color:柱子边框的宽度和颜色,增加边框能让各柱体区分更明显。

4. 保存方法

  • fig.write_html("filename.html")保存图形。Plotly 保留交互特性的标准保存方式,可在浏览器中打开查看悬停、缩放等交互效果(对应15.4.10)。

15.1 安装 Matplotlib

Matplotlib 是一个数学绘图库,可制作简单的图表(如折线图、散点图)。使用 pip 安装它:

python -m pip install --user matplotlib

[notice] A new release of pip is available: 26.0.1 -> 26.1
[notice] To update, run: python.exe -m pip install --upgrade pip
E:\C sharp电子书\电子书\python\python学习>python -m pip install --user matplotlib
Requirement already satisfied: matplotlib in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (3.10.7)
Requirement already satisfied: contourpy>=1.0.1 in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (from matplotlib) (1.3.3)
Requirement already satisfied: cycler>=0.10 in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (from matplotlib) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (from matplotlib) (4.61.0)
Requirement already satisfied: kiwisolver>=1.3.1 in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (from matplotlib) (1.4.9)
Requirement already satisfied: numpy>=1.23 in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (from matplotlib) (2.3.5)
Requirement already satisfied: packaging>=20.0 in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (from matplotlib) (25.0)
Collecting pillow>=8 (from matplotlib)
  Downloading pillow-12.2.0-cp312-cp312-win_amd64.whl.metadata (9.0 kB)
Requirement already satisfied: pyparsing>=3 in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (from matplotlib) (3.2.5)
Requirement already satisfied: python-dateutil>=2.7 in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (from matplotlib) (2.9.0.post0)
Requirement already satisfied: six>=1.5 in C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages (from python-dateutil>=2.7->matplotlib) (1.17.0)
Downloading pillow-12.2.0-cp312-cp312-win_amd64.whl (7.1 MB)
   ━━╸━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.5/7.1 MB 36.6 kB/s eta 0:03:00

15.2 绘制简单的折线图

15.2.1 使用 Matplotlib 绘制折线图

def plot(
    *args: ArrayLike | float,           # 位置参数:数据
    scalex: bool = True,                # 自动缩放X轴
    scaley: bool = True,                # 自动缩放Y轴
    data: Any | None = None,            # 数据源
    **kwargs: Any                       # 关键字参数:样式属性
) -> list[Line2D]                       # 返回 Line2D 对象列表

# 示例
plt.plot([1, 2, 3, 4, 5])           # Y值,X自动为 0-4
plt.plot([1, 2, 3], [1, 4, 9])      # X和Y
plt.plot([1, 2, 3], [1, 4, 9], 'b--')  # 蓝色虚线

下面绘制一个简单的折线图,其中包含几个平方数:

import matplotlib.pyplot as plt

squares = [1, 4, 9, 16, 25]
plt.plot(squares)
plt.show()

这个程序将 squares 列表传递给 plot() 函数,再调用 show() 打开Matplotlib查看器并显示图表。

15.2.2 修改标签文字和线型

你可以为图表添加标题、标签,并自定义线条样式:

squares = [1, 4, 9, 16, 25]  # 定义数据列表:1-5的平方数
fig, ax = plt.subplots()  # 创建图形画布(fig)和坐标轴(ax)对象
ax.plot(squares, linewidth=3)  # 在坐标轴上绘制折线图,设置线宽为3

# 设置图题并给坐标轴加上标签
ax.set_title("Square Numbers", fontsize=24)  # 设置图表标题,字体大小为24
ax.set_xlabel("Value", fontsize=14)  # 设置X轴标签为"Value",字体大小为14
ax.set_ylabel("Square of Value", fontsize=14)  # 设置Y轴标签为"Square of Value",字体大小为14
# 设置刻度标记的样式
ax.tick_params(axis='both', labelsize=14)  # 设置X轴和Y轴的刻度标签字体大小为14

plt.show()  # 显示绘制的图表

注意:要纠正之前图表的形状错误(曲线起点不对),需要给plot()同时提供输入值和输出值。


15.2.3 内置样式

Matplotlib 提供了很多已定义好的样式,这些样式包含默认的背景色、网格线、线条粗细、字体、字号等设置,让你无须做太多定制就能生成引人瞩目的可视化效果。要看到能在你的系统中使用的所有样式,可在终端会话中执行如下命令:

>>> import matplotlib.pyplot as plt
>>> plt.style.available
['Solarize_Light2', '_classic_test_patch', '_mpl-gallery', '_mpl-gallery-nogrid', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'petroff10', 'seaborn-v0_8', 'seaborn-v0_8-bright', 'seaborn-v0_8-colorblind', 'seaborn-v0_8-dark', 'seaborn-v0_8-dark-palette', 'seaborn-v0_8-darkgrid', 'seaborn-v0_8-deep', 'seaborn-v0_8-muted', 'seaborn-v0_8-notebook', 'seaborn-v0_8-paper', 'seaborn-v0_8-pastel', 'seaborn-v0_8-poster', 'seaborn-v0_8-talk', 'seaborn-v0_8-ticks', 'seaborn-v0_8-white', 'seaborn-v0_8-whitegrid', 'tableau-colorblind10']  

15.3 绘制散点图

def scatter(
    self, 
    x, y,                    # 必需:X和Y坐标数据
    s=None,                  # 点的大小(size)
    c=None,                  # 点的颜色(color)
    marker=None,             # 标记形状
    cmap=None,               # 颜色映射(colormap)
    norm=None,               # 颜色归一化
    vmin=None, vmax=None,    # 颜色范围的最小/最大值
    alpha=None,              # 透明度
    linewidths=None,         # 标记边框线宽
    *,                       # 关键字参数分隔符(之后必须用关键字传参)
    edgecolors=None,         # 标记边框颜色
    colorizer=None,          # 颜色处理器(新功能)
    plotnonfinite=False,     # 是否绘制非有限值(NaN/Inf)
    **kwargs                 # 其他关键字参数
):

15.3.1 使用 scatter() 绘制单个点

使用 scatter() 函数绘制单个点并设置其样式:

import matplotlib.pyplot as plt

plt.scatter(2, 4, s=200)

# 设置图表标题并给坐标轴加上标签
plt.title("Square Numbers", fontsize=24)
plt.xlabel("Value", fontsize=14)
plt.ylabel("Square of Value", fontsize=14)

# 设置刻度标记的大小
plt.tick_params(axis='both', which='major', labelsize=14)

plt.show()

15.3.2 使用 scatter() 绘制一系列点

要绘制一系列点,可将x值和y值分别放在列表中传递给scatter()

import matplotlib.pyplot as plt

x_values = [1, 2, 3, 4, 5]
y_values = [1, 4, 9, 16, 25]

plt.scatter(x_values, y_values, s=100)
plt.show()

15.3.3 自动计算数据

使用循环自动生成数据,例如计算前1000个整数的平方:

import matplotlib.pyplot as plt

x_values = range(1, 1001)
y_values = [x**2 for x in x_values]

plt.scatter(x_values, y_values, s=40)

# 设置图表标题并给坐标轴加上标签
plt.title("Square Numbers", fontsize=24)
plt.xlabel("Value", fontsize=14)
plt.ylabel("Square of Value", fontsize=14)

# 设置每个坐标轴的取值范围
plt.axis([0, 1100, 0, 1100000])

plt.show()

image

1e6 ↑
1.0 ┤
0.8 ┤
0.6 ┤
0.4 ┤
0.2 ┤
0.0 ┤

1e6 = 1 × 10⁶ = 1,000,000
2e6 = 2 × 10⁶ = 2,000,000
1.5e6 = 1.5 × 10⁶ = 1,500,000

15.3.4 删除数据点的轮廓

scatter() 默认绘制蓝色点和黑色轮廓。可以修改参数 edgecolor='none' 来删除轮廓:

plt.scatter(x_values, y_values, edgecolor='none', s=40)

image

15.3.5 自定义颜色

scatter() 传递参数 c,可设置颜色名称(如 'red')或RGB元组(取值在0~1之间):

plt.scatter(x_values, y_values, c='red', edgecolor='none', s=40)
# 或使用RGB颜色
plt.scatter(x_values, y_values, c=(0, 0.8, 0), edgecolor='none', s=40)

15.3.6 使用颜色映射

颜色映射(colormap)是一系列渐变颜色,可根据数据点的值来设置颜色。参数 c 传入y值列表,参数 cmap 指定映射名称:

plt.scatter(x_values, y_values, c=y_values, cmap=plt.cm.Blues, edgecolor='none', s=40)

15.3.7 自动保存图表

如果要让程序自动将图表保存到文件中,而非在查看器中显示,可调用 savefig() 替换 show()

plt.savefig('squares_plot.png', bbox_inches='tight')
# 第一个参数是文件名(可指定路径),第二个参数`bbox_inches='tight'`可裁剪图表多余的空白区域

15.4 随机漫步

随机漫步是从原点开始、每一步方向完全随机的一种路径。使用Python和Matplotlib可轻松模拟。

15.4.1 创建 RandomWalk 类

from random import choice

class RandomWalk:
    """一个生成随机漫步数据的类"""
    
    def __init__(self, num_points=5000):
        """初始化随机漫步的属性"""
        self.num_points = num_points
        
        # 所有随机漫步都始于(0, 0)
        self.x_values = 
        self.y_values = 
    
    def fill_walk(self):
        """计算随机漫步包含的所有点"""
        
        # 不断漫步,直到列表达到指定的长度
        while len(self.x_values) < self.num_points:
            
            # 决定前进方向以及沿这个方向前进的距离
            x_direction = choice([1, -1])
            x_distance = choice([0, 1, 2, 3, 4])
            x_step = x_direction * x_distance
            
            y_direction = choice([1, -1])
            y_distance = choice([0, 1, 2, 3, 4])
            y_step = y_direction * y_distance
            
            # 拒绝原地踏步
            if x_step == 0 and y_step == 0:
                continue
            
            # 计算下一个点的x和y值
            x = self.x_values[-1] + x_step
            y = self.y_values[-1] + y_step
            
            self.x_values.append(x)
            self.y_values.append(y)

15.4.2 绘制随机漫步图

import matplotlib.pyplot as plt

# 创建一个RandomWalk实例,并调用fill_walk()
rw = RandomWalk()
rw.fill_walk()

# 将所有的点都绘制出来
plt.style.use('classic')
fig, ax = plt.subplots()
ax.scatter(rw.x_values, rw.y_values, s=15)

plt.show()

15.4.3 模拟多次随机漫步

每次运行都会生成不同的随机漫步,因为随机性的存在。如果你想继续漫步,程序会循环运行直到你选择退出,只需将上述代码放入一个 while 循环即可。

15.4.4 给点着色

使用颜色映射来显示漫步中点的先后顺序。将点的顺序列表传递给参数 c,并指定 cmap

point_numbers = range(rw.num_points)
ax.scatter(rw.x_values, rw.y_values, c=point_numbers, cmap=plt.cm.Blues, edgecolor='none', s=15)

15.4.5 重新绘制起点和终点

将起点和终点突出显示,能更清楚地看出漫步的轨迹:

ax.scatter(0, 0, c='green', edgecolors='none', s=100)  # 起点
ax.scatter(rw.x_values[-1], rw.y_values[-1], c='red', edgecolors='none', s=100)  # 终点

c - point_numbers 颜色值数组 (点的序号 0, 1, 2, 3...)
cmap - plt.cm.Blues 颜色映射 :蓝色渐变
轨迹可视化 - 能看出随机游走的先后顺序

15.4.6 起点和终点

ax.scatter(0, 0, c='green', edgecolors='none', s=100)
ax.scatter(rw.x_values[-1], rw.y_values[-1], c='red', edgecolors='none', s=100)

image

15.4.7 隐藏坐标轴

隐藏坐标轴让随机漫步图看起来更整洁:

ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)

15.4.8 调整图表尺寸以适应屏幕

figure() 函数可指定图表的宽度、高度、分辨率和背景色。在创建图表前设置:

fig, ax = plt.subplots(figsize=(10, 6), dpi=128)

15.5 使用 Plotly 绘制掷骰子模拟

Plotly 可以创建交互式图表,特别适合在浏览器中展示。使用 Plotly 模拟掷骰子的结果。

15.5.1 安装 Plotly

python -m pip install --user plotly 
python -m pip install --user pandas

注意:本教程中的示例使用 Plotly 4.0,安装后请导入 plotly.graph_objs

15.5.2 创建 Die 类

from random import randint

class Die:
    """表示一个骰子的类"""
    
    def __init__(self, num_sides=6):
        """骰子默认为6面"""
        self.num_sides = num_sides
    
    def roll(self):
        """返回一个介于1和骰子面数之间的随机值"""
        return randint(1, self.num_sides)

15.5.3 掷骰子并对结果进行分析

创建一个6面骰子和一个10面骰子,同时掷它们50000次,计算点数之和:

# 从 DieClass 模块导入 Die 类(骰子类)
from DieClass import Die

# 创建两个骰子实例
die_1 = Die()      # 创建默认 6 面骰子
die_2 = Die(10)    # 创建 10 面骰子

# 创建空列表,用于存储每次投掷的结果
results = []

# 模拟投掷骰子 49,999 次(5_0000 是 Python 的数字分隔写法,等于 50000)
for roll_num in range(1, 5_0000):
    # 投掷两个骰子,将结果相加
    result = die_1.roll() + die_2.roll()
    # 将结果添加到列表中
    results.append(result)

# print(results)  # 调试用,查看所有结果(数据量太大,已注释) [11, ...(50000个)..., 5, 12]

# ========== 分析结果 ==========

# 创建空列表,用于存储每个结果出现的频率
frequencies = []

# 计算最大可能的结果值(6 + 10 = 16)
max_result = die_1.num_sides + die_2.num_sides

# 遍历所有可能的结果(从 2 到 16)
for value in range(2, max_result + 1):
    # 统计该结果在 results 列表中出现的次数
    frequency = results.count(value)
    # 将频率添加到 frequencies 列表中
    frequencies.append(frequency)
    
print(frequencies)
# 分析频率 2到16出现频率 
# [781, 1682, 2516, 3262, 4050, 4940, 5159, 5059, 4936, 5053, 4228, 3315, 2526, 1628, 864]
# [823, 1770, 2432, 3350, 4216, 4986, 4865, 4971, 4876, 5140, 4134, 3418, 2494, 1695, 829]

15.5.4 绘制直方图

简单版 Plotly Express (高级 API)

from DieClass import Die
import plotly.express as px

# 前面的代码
...

# 对结果进行可视化

fig = px.bar(x=range(2, max_result + 1), y=frequencies)
fig.show()

image

可自定义 Plotly Graph Objects (底层 API)

使用 Plotly 的 bar 方法绘制直方图,并显示交互式图表:

from plotly.graph_objs import Bar, Layout
from plotly import offline

# 可视化结果
x_values = list(range(2, max_result + 1))
data = [Bar(x=x_values, y=frequencies)]

x_axis_config = {'title': 'Result', 'dtick': 1}
y_axis_config = {'title': 'Frequency of Result'}
my_layout = Layout(title='Results of rolling a D6 and a D10 50000 times',
                   xaxis=x_axis_config, yaxis=y_axis_config)

offline.plot({'data': data, 'layout': my_layout}, filename='d6_d10.html')

注意dtick: 1 告诉Plotly显示每个坐标轴刻度标签;offline.plot() 生成一个HTML文件并在浏览器中自动打开。

15.5.5 同时掷两个骰子

上述示例已演示了同时掷两个骰子的场景。你可以创建任意数量、任意面数的骰子组合,只需修改 Die 的实例化参数(例如 Die(8) 表示8面骰子)。


✍️ 动手试一试(课后练习)

根据教程内容,尝试完成以下练习来巩固数据可视化的知识:

  1. 练习 15.1 立方:数字的立方指其三次方。请绘制一个图表,显示前5个整数的立方值,再绘制一个图表显示前5000个整数的立方值。
  2. 练习 15.2 彩色立方:在前一个练习绘制的立方图上应用颜色映射。
  3. 练习 15.3 分子运动:修改随机漫步程序,让分子每次移动的步长是随机选择的1到100之间的整数,并让方向也是随机的。绘制这种分子运动轨迹图。
  4. 练习 15.6 同时掷两个骰子:创建一个同时掷两个6面骰子100000次的程序,使用Plotly绘制结果直方图,并统计每种点数之和出现的频率。
posted @ 2026-05-04 21:27  【唐】三三  阅读(27)  评论(0)    收藏  举报