安斯科姆四重奏(统计分析中可视化的重要性)

不论是做统计分析,还是做机器学习相关的项目时,常常在最后通过绘制一些图表来表达自己得出的结论。

然而,绘图的意义远不止此。

因为,即使不同的原始样本的分布情况差别很大,它们的基本统计特性也能几乎一致。

这时如果不把原始样本的分布绘制出来看看,仅仅依赖基本的统计量来描述数据,可能会数据情况造成误判。

安斯库姆四重奏就是这样的一种数据集,它们的分布情况差别很大,基本统计特性却几乎一致。

1. 安斯科姆四重奏数据集

安斯库姆四重奏 是统计学家弗朗西斯·安斯库姆(Francis Anscombe)于1973年构造的数据集。

它为我们揭示了数据分析中的一个重要问题:仅仅依赖基本的统计量(如均值、方差等)来描述数据集是不够的,还需要考虑数据的分布情况。

数据集内容如下:

python 复制代码
import numpy as np

anscombes = [
    {
        "x": np.array([10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]),
        "y": np.array([8.04, 6.95, 7.58, 8.81, 8.33, 9.96, 7.24, 4.26, 10.84, 4.82, 5.68]),
    },
    {
        "x": np.array([10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]),
        "y": np.array([9.14, 8.14, 8.74, 8.77, 9.26, 8.1, 6.13, 3.1, 9.13, 7.26, 4.74]),
    },
    {
        "x": np.array([10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]),
        "y": np.array([7.46, 6.77, 12.74, 7.11, 7.81, 8.84, 6.08, 5.39, 8.15, 6.42, 5.73]),
    },
    {
        "x": np.array([8, 8, 8, 8, 8, 8, 8, 19, 8, 8, 8]),
        "y": np.array([6.58, 5.76, 7.71, 8.84, 8.47, 7.04, 5.25, 12.5, 5.56, 7.91, 6.89]),
    },
]

它们的分布情况如下:

python 复制代码
import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 2, sharex="all", sharey="all")
fig.set_size_inches(8, 6)
axes[0][0].scatter(anscombes[0]["x"], anscombes[0]["y"])
axes[0][1].scatter(anscombes[1]["x"], anscombes[1]["y"])
axes[1][0].scatter(anscombes[2]["x"], anscombes[2]["y"])
axes[1][1].scatter(anscombes[3]["x"], anscombes[3]["y"])


plt.show()

2. 不同的数据,相同的指标

接下来,看看安斯库姆四重奏中4个数据集各自的统计特性。

2.1. 属性的平均值

统计各个数据集中属性xy的平均值。

python 复制代码
print(
    "x的平均值:{}, {}, {}, {}".format(
        np.mean(anscombes[0]["x"]),
        np.mean(anscombes[1]["x"]),
        np.mean(anscombes[2]["x"]),
        np.mean(anscombes[3]["x"]),
    )
)

print(
    "y的平均值:{:.2f}, {:.2f}, {:.2f}, {:.2f}".format(
        np.mean(anscombes[0]["y"]),
        np.mean(anscombes[1]["y"]),
        np.mean(anscombes[2]["y"]),
        np.mean(anscombes[3]["y"]),
    )
)

# 运行结果
x的平均值:9.0, 9.0, 9.0, 9.0
y的平均值:7.50, 7.50, 7.50, 7.50

每个数据集的属性xy的平均值都一样

2.2. 属性的样本方差

统计各个数据集中属性xy的样本方差。

python 复制代码
print(
    "x的样本方差:{}, {}, {}, {}".format(
        np.var(anscombes[0]["x"], ddof=1),
        np.var(anscombes[1]["x"], ddof=1),
        np.var(anscombes[2]["x"], ddof=1),
        np.var(anscombes[3]["x"], ddof=1),
    )
)

print(
    "y的样本方差:{:.2f}, {:.2f}, {:.2f}, {:.2f}".format(
        np.var(anscombes[0]["y"], ddof=1),
        np.var(anscombes[1]["y"], ddof=1),
        np.var(anscombes[2]["y"], ddof=1),
        np.var(anscombes[3]["y"], ddof=1),
    )
)

# 运行结果
x的样本方差:11.0, 11.0, 11.0, 11.0
y的样本方差:4.13, 4.13, 4.12, 4.12

各个数据集中属性xy的样本方差几乎一致,差别很小

2.3. 线性回归及R2分数

最后,分别对4个数据集进行线性回归,看看各自的回归的曲线和 R 2 R^2 R2分数。
R² 分数 (也叫决定系数),是用于衡量模型的拟合优度的一个指标。

python 复制代码
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score

fig, axes = plt.subplots(2, 2, sharex="all", sharey="all")
fig.set_size_inches(8, 6)
axes[0][0].scatter(anscombes[0]["x"], anscombes[0]["y"])
axes[0][1].scatter(anscombes[1]["x"], anscombes[1]["y"])
axes[1][0].scatter(anscombes[2]["x"], anscombes[2]["y"])
axes[1][1].scatter(anscombes[3]["x"], anscombes[3]["y"])

reg_x = np.array([0, 20])

reg = LinearRegression()
sample_x = [[x] for x in anscombes[0]["x"]]
reg.fit(sample_x, anscombes[0]["y"])
# print(reg.coef_, reg.intercept_)
reg_y = reg.coef_ * reg_x + reg.intercept_
axes[0][0].plot(reg_x, reg_y, color="r")
r2 = r2_score(anscombes[0]["y"], reg.predict(sample_x))
axes[0][0].set_title("R2系数: {:.2f}".format(r2))

sample_x = [[x] for x in anscombes[1]["x"]]
reg.fit(sample_x, anscombes[1]["y"])
# print(reg.coef_, reg.intercept_)
reg_y = reg.coef_ * reg_x + reg.intercept_
axes[0][1].plot(reg_x, reg_y, color="r")
r2 = r2_score(anscombes[1]["y"], reg.predict(sample_x))
axes[0][1].set_title("R2系数: {:.2f}".format(r2))

sample_x = [[x] for x in anscombes[2]["x"]]
reg.fit(sample_x, anscombes[2]["y"])
# print(reg.coef_, reg.intercept_)
reg_y = reg.coef_ * reg_x + reg.intercept_
axes[1][0].plot(reg_x, reg_y, color="r")
r2 = r2_score(anscombes[2]["y"], reg.predict(sample_x))
axes[1][0].set_title("R2系数: {:.2f}".format(r2))

sample_x = [[x] for x in anscombes[3]["x"]]
reg.fit(sample_x, anscombes[3]["y"])
# print(reg.coef_, reg.intercept_)
reg_y = reg.coef_ * reg_x + reg.intercept_
axes[1][1].plot(reg_x, reg_y, color="r")
r2 = r2_score(anscombes[3]["y"], reg.predict(sample_x))
axes[1][1].set_title("R2系数: {:.2f}".format(r2))

plt.show()

虽然数据分布差别很大,但是线性回归的曲线和 R 2 R^2 R2分数却出奇的一致。

3. 总结

安斯库姆四重奏 虽然是构造出的数据集,但是真实世界中难免不会有类似的情况。

它提醒我们要用更加严谨的态度对待数据分析的结果,不要仅仅依据基本的统计特性就得出结论,

还需要对数据进行可视化处理,以便更全面地了解数据的分布情况。

安斯库姆四重奏 数据传达给我们的核心信息是:在数据分析中,可视化是一个至关重要的步骤,它能帮助我们更好地理解和解释数据。

相关推荐
般若-波罗蜜6 分钟前
MinerU高级用法,避坑指南(持续更新)
人工智能·python·语言模型·自然语言处理
你是我的解忧王子25 分钟前
10进制和16进制 超声波 FFT 变换分析筛选系统误差-ADC采样筛选工具
数据分析·adc·fft·系统误差
用户83562907805132 分钟前
使用 Python 对 PDF 文档进行数字签名的方法
后端·python
李可以量化1 小时前
PTrade 量化入门必学:get\_trading\_day 交易日函数全解与实战(下)
python
柒和远方1 小时前
LeetCode 139. 单词拆分 —— 从暴力回溯到 DP 完全背包
javascript·python·算法
半兽先生2 小时前
大模型实现金融文本分类
人工智能·python·金融
汤姆小白2 小时前
06-LoRA参数高效微调
人工智能·python·机器学习·transformer
铅笔侠_小龙虾2 小时前
Rust 学习(6)-所有权规则、移动语义、Clone 与 Copy
python·学习·rust
码云骑士2 小时前
65-AI-Agent基础原理-AutoGPT-四大架构全景解读
人工智能·python·架构
Ulyanov3 小时前
刚体动力学方程——牛顿-欧拉与陀螺效应的奥秘
开发语言·python·目标跟踪·雷达电子对抗·导引头