编辑
2026-04-01
undefined
00

目录

方法论
数理统计
描述性统计分析
频数与频率
集中趋势
离散程度
分布形状
推断统计分析
参数估计
点估计
区间估计
假设检验
Z检验
右边假设检验
左边假设检验
假设检验的两类错误
t检验
单样本t检验
两独立样本t检验
两配对样本t检验
卡方检验
单个变量
两个变量

方法论

OSEMN(Obtain, Scrub, Explore, Model, iNterpret)是一种常用的数据分析方法论,包括数据获取、数据清洗、数据探索、建模和解释等步骤。OSEMN方法论强调了数据分析过程中数据质量和数据探索的重要性。

数理统计

数理统计分为如下两类:

  • 描述统计
  • 推断统计

描述性统计分析

描述性统计所提取统计的信息,称为统计量,主要包括以下几个方面:

  • 频数与频率

集中趋势分析

  • 均值

  • 中位数

  • 众数

  • 分位数

离散程度分析

  • 极差

  • 方差

  • 标准差

分布形状

  • 偏度
  • 峰度

频数与频率

import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import load_iris import warnings 设置seaborn绘图样式与字体规模 sns.set(style="darkgrid", font_scale=1.2) plt.rcParams["font.family"] = "SimHei" # 设置中文字体 plt.rcParams["axes.unicode_minus"] = False # 是否使用Unicode字符集中的负号 warnings.filterwarnings("ignore") # 忽略警告信息 iris = load_iris() # 加载鸢尾花数据集 print(iris.data.shape) # NumPy 数组 (150, 4) print(iris.target.shape) # NumPy 数组 (150, ) 每朵鸢尾花对应的类别,取值为0,1,2 print(iris.feature_names) # 特征列的名称 print(iris.target_names) # 鸢尾花类别的名称,即数值0,1,2分别对应的类别 合并数据 data = np.concatenate([iris.data, iris.target.reshape(-1, 1)], axis=1) # 横向拼接,-1的作用是自动计算行 data = pd.DataFrame(data, columns=["sepal_length", "sepal_width", "petal_length", "petal_width", "type"]) data.sample(10) # 随机抽样 frequency = data["type"].value_counts() # 计算类别出现的频数 print(frequency) percentage = frequency * 100 / len(data) # 计算类别出现的频率 print(percentage) sns.countplot(x="type", data=data) # 绘制type列不同取值出现的次数 plt.show()

集中趋势

mean = data["sepal_length"].mean() # 花萼长度的均值 median = data["sepal_length"].median() # 中位数 s = data["sepal_length"].mode() # mode方法返回Series类型 mode = s.iloc[0] # 众数 print(mean, median, mode) sns.distplot(data["sepal_length"]) # 绘制数据的发布,直方图 + 密度图 绘制垂直线 plt.axvline(mean, ls="-", color="r", label="均值") plt.axvline(median, ls="-", color="g", label="中值") plt.axvline(mode, ls="-", color="indigo", label="众数") plt.legend() x = [1, 3, 10, 15, 18, 20, 23, 40] print(np.quantile(x, q=[0.25, 0.5, 0.75])) # 计算分位数 print(np.percentile(x, q=[25, 50, 75])) s = pd.Series(x) print(s.describe()) # pandas中计算分位数 print(s.describe(percentiles=[0.25, 0.9]))

离散程度

sub = np.ptp(data["sepal_length"]) # 极差 var = data["sepal_length"].var() # 方差 std = data["sepal_length"].std() # 标准差 print(sub, var, std) plt.figure(figsize=(15, 4)) # 设置图形大小,宽*高,单位为英寸 plt.ylim(-0.5, 1.5) plt.plot(data["petal_length"], np.zeros(len(data)), linestyle="", marker="o", markersize=10, color="g", label="花瓣长度") plt.plot(data["petal_width"], np.ones(len(data)), ls="", marker="o", ms=10, color="r", label="花瓣宽度") plt.axvline(data["petal_length"].mean(), ls="--", color="g", label="花瓣长度均值") plt.axvline(data["petal_width"].mean(), ls="--", color="r", label="花瓣宽度均值") plt.legend()

分布形状

## 构造左偏分布数据 t1 = np.random.randint(1, 11, size=100) t2 = np.random.randint(11, 21, size=500) t3 = np.concatenate([t1, t2]) left_skew = pd.Series(t3) 构造右偏分布数据 t1 = np.random.randint(1, 11, size=500) t2 = np.random.randint(11, 21, size=100) t3 = np.concatenate([t1, t2]) right_skew = pd.Series(t3) print(left_skew.skew(), right_skew.skew()) 绘制核密度图 sns.kdeplot(left_skew, shade=True, label="左偏") sns.kdeplot(right_skew, shade=True, label="右偏") plt.legend() 标准正态分布 standard_normal = pd.Series(np.random.normal(0, 1, size=10000)) print("标准正态分布峰度:", standard_normal.kurt(), "标准差:", standard_normal.std()) sns.kdeplot(standard_normal, label="标准正态分布") sns.kdeplot(data["sepal_width"], label="花萼宽度") sns.kdeplot(data["petal_length"], label="花瓣长度") plt.legend()

推断统计分析

总体的参数往往是未知的,为了获取总体的参数,就需要通过样本统计量来估计总体参数。

参数估计

点估计

import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import load_iris import warnings sns.set(style="darkgrid", font_scale=1.2) plt.rcParams["font.family"] = "SimHei" plt.rcParams["axes.unicode_minus"] = False warnings.filterwarnings("ignore") iris = load_iris() data = np.concatenate([iris.data, iris.target.reshape(-1, 1)], axis=1) data = pd.DataFrame(data, columns=["sepal_length", "sepal_width", "petal_length", "petal_width", "type"]) print(data["petal_length"].mean())

点估计容易受到随机抽样的影响,可能无法保证结论的准确性。但是,样本来自于总体,样本还是能够体现出总体的一些特征的。

区间估计

区间估计使用一个置信区间与置信度,表示总体参数有多少可能(置信度)会在该范围(置信区间)内。

样本均值分布的标准差,称为标准误差,简称标准误。

根据中心极限定理,如果多次抽样(总体的均值为μ,方差为σ*σ*),则样本均值构成的正态分布,满足样本均值~N(μ, σσ/n),如果只对总体进行一次抽样,则该样本的均值有95%的概率会在(μ-2σ, μ+2σ)范围内,仅有5%的概率会在(μ-2σ, μ+2σ)范围外。根据小概率事件(很小的概率在一次抽样中基本不会发生),如果抽样的样本均值在(μ-2σ, μ+2σ)之外,就可以认为,本次抽样来自的总体,该总体的均值并非是我们所期望的均值。

通常,以2倍标准差作为判依据,即以样本均值为中心,正负2倍标准差构成的区间,就是置信区间。而2倍标准差包含了95%的数据,因此,此时的置信度为95%。换言之,有95%的信心认为总体的均值会在置信区间之内。

a = np.array([0.497, 0.506, 0.518, 0.524, 0.498, 0.511, 0.520, 0.515, 0.512]) mean, std = 0.5, 0.015 # 总体均值与标准差 sample_mean = a.mean() # 样本均值 se = std / np.sqrt(len(a)) # 标准误 left, right = sample_mean - 1.96 * se, sample_mean + 1.96 * se print(f"置信区间:({left:.3f}, {right:.3f})") plt.plot(mean, 0, marker="*", color="orange", ms=15, label="总体均值") plt.plot(sample_mean, 0, marker="o", color="r", label="样本均值") plt.hlines(0, xmin=left, xmax=right, color="b", label="置信区间") plt.axvline(left, 0.4, 0.6, color="r", ls="--", label="左边界") plt.axvline(right, 0.4, 0.6, color="g", ls="--", label="右边界") plt.legend()

假设检验

设置原假设与备择假设

  • 原假设:μ=μ0=0.5kg(机器运作正常)
  • 备择假设:μ≠μ0≠0.5kg(机器运作不正常)
  1. 设置显著性水平,设置α=0.05
  2. 根据问题选择假设检验的方式。袋装糖的净重呈正态分布,总体标准差已知,选择Z检验
  3. 计算统计量,并通过统计量获取P值。根据选择的假设检验,进行计算

Z检验

Z检验用于正态总体均值的检验,即用来检验总体的均值(末知)是否与假设的均值相同。

from scipy import stats a = np.array([0.497, 0.506, 0.518, 0.524, 0.498, 0.511, 0.520, 0.515, 0.512]) mean, std = 0.5, 0.015 # 总体均值与标准差 sample_mean = a.mean() # 样本均值 se = std / np.sqrt(len(a)) # 标准误 Z = (sample_mean - mean) / se # Z统计量 print("统计量Z:", Z) 计算P值 sf函数,根据参数指定的统计量,返回该统计量与右侧图像围成的面积值 实际上,P值就是通过概率密度函数计算出来的面积,即概率值 P = 2 * stats.norm.sf(abs(Z)) print("P-Value值:", P)

由结果可知,Z值偏离超过了2倍的标准差,P值也就小于0.05。因此,在显著性水平α=0.05下,P<α,故拒绝原假设,接受备择假设,即认为机器运作是不正常的。

右边假设检验

右边假设检验的拒绝域在正态分布的右侧区域。

  • 原假设:μ≤μ0=0.5kg(机器运作正常)

  • 备择假设:μ>μ0≠0.5kg(机器运作不正常)

    Z统计量与之前计算的方式相同

    P = stats.norm.sf(Z) print("P-Value值:", P)

P<α,拒绝原假设,认为机器运作是不正常的。

左边假设检验

左边假设检验的拒绝域在正态分布的左侧区域。

  • 原假设:μ≥μ0=0.5kg(机器运作正常)

  • 备择假设:μ<μ0≠0.5kg(机器运作不正常)

    cdf函数,返回该统计量与左侧图像围成的面积值

    P = stats.norm.cdf(Z) print("P-Value值:", P)

P>α,维持原假设,认为机器运作是正常的。

假设检验的两类错误

接受H0拒绝H0H0为真正确I类错误(α错误,去真错误)H0为假II类错误(β错误,取伪错误)正确

t检验

与Z检验的应用场景类似,t检验也用于正态总体均值的检验。只不过,t检验的正态总体,标准差是未知的。

t检验分为三种类型:

  1. 单样本t检验
  2. 两独立样本t检验
  3. 两配对样本t检验
  • t检验原假设为等值假设,备择假设为不等值假设(双边检验)
  • t检验通过构造t统计量来实现
  • t统计量服从t分布
  • 随着样本容量的增大,t分布逐渐接近于标准正态分布

单样本t检验

单样本t检验前提条件为:

  1. 总体服从正态分布

总体方差(标准差)末知

mean = data["petal_length"].mean() std = data["petal_length"].std() t = (mean - 3.5) / (std / np.sqrt(len(data))) # t统计量 print("t统计量:", t) P = 2 * stats.t.sf(abs(t), df=len(data["petal_length"]) - 1) print("P-Value值:", P) 此外,也可通过scipy提供的相关方法来进行t检验的计算,无需自行计算 stats.ttest_1samp(data["petal_length"], 3.5)

两独立样本t检验

两独立样本t检验用于检验两个正态总体的均值是否相同,其前提条件为:

  • 1.两个样本是独立的
  • 2.两个样本所在的总体服从正态分布
  • 3.总体方差未知

由于方差是否齐性(相同),会影响t统计量的计算。因此,在进行两独立样本t检验时,首先需要进行方差齐性检验。可以通过Levene检验来判断两个正态总体的方差是否相同。

## A,B两个学校的学生数据 school_A = np.array([169.7, 163.1, 179.0, 163.4, 180.2, 160.9, 177.3, 160.7, 169.9, 163.4]) school_B = np.array([163.6, 180.0, 171.8, 174.7, 164.3, 173.9, 167.0, 162.9, 164.2, 171.6]) print(school_A.mean(), school_B.mean()) 使用levene检验判断两个样本背后的总体,其方差是否一致 stats.levene(school_A, school_B)

P>0.05,因此可以认为两个总体的方差是相同的。然后,就可以使用两独立样本t检验,来验证两个正态总体的均值是否相同。

stats.ttest_ind(school_A, school_B, equal_var=False)

P>0.05,因此维持原假设,认为两个正态总体的均值是相同的,即A与B两个学校的平均身高相同。

两配对样本t检验

两配对样本t检验,是同一组受试者产生两组数据,然后,验证两组数据是否存在显著性差异的方式。两组数据可以是:

  1. 受试者在接受处理前与处理后的数据
  2. 受试者在接受两种不同的处理方式,分别产生的数据

两配对样本t检验的前提条件为 :

  1. 配对样本差值独立

  2. 配对样本差值服从正态分布

  3. 总体标准差末知

    培训前体重数据

    train_before = np.array([98.8, 92.0, 94.9, 101.2, 99.3, 85.1, 94.8, 89.2, 89.5, 92.1]) 培训后体重数据 train_after = np.array([88.4, 92.4, 90.3, 88.4, 89.3, 89.0, 92.5, 87.4, 88.9, 85.4]) 两配对样本t检验(双边检验) stats.ttest_rel(train_before, train_after)

P<0.05,拒绝原假设,认为体重在培训前跟培训后是不同的。

如果没有充足的证据证明减肥有效,则应该按照减肥无效处理。则:

  • 原假设:D≤0(减肥无效)

  • 备择假设:D>0(减肥有效)

    sta = stats.ttest_rel(train_before, train_after).statistic # 获取统计量 P = stats.t.sf(sta, df=len(train_before) - 1) print(P)

P<0.05,拒绝原假设,认为减肥有效。

卡方检验

卡方检验用于检测变量的理论频数与实际频数是否一致。

卡方检验可以分为两个类别 :

  1. 单个变量
  2. 两个变量

关于卡方检验,说明如下 :

  1. 卡方检验原假设为理论频数与实际频数一致,备择假设为理论频数与实际频数不一致(双边假设)
  2. 卡方检验为非参数检验,不对总体进行任何假设,因此也不涉及关于总体分布的参数
  3. 卡方检验通过卡方统计量来实现
  4. 卡方统计量服从卡方分布

单个变量

卡方检验(单个变量)的前提条件为 :

  1. 观测值之间相互独立
  2. 变量每个取值的理论频数与实际频数≥5

举例:某手机在一段时间内,销量为200,各种颜色销量如下表所示: 红色绿色黄色紫色白色4350243152 请问该款手机的颜色对销售是否会造成影响?

o = [43, 50, 24, 31, 52] e = [40, 40, 40, 40, 40] stats.chisquare(f_obs=o, f_exp=e)

P<0.05,拒绝原假设,认为理论频数与实际频数不一致,得出结论:手机颜色对销售确实造成了影响。

两个变量

举例:某手机在一段时间内,每种颜色与性别的销量如下表所示: 红色绿色黄色紫色白色男4350243152女3842302945 请问该款手机的购买用户中,性别与手机颜色是否具有关联?

根据随机变量独立性的定义,如果两个随机变量A与B是独立的,则有:

P(AB) = P(A)*P(B)

因此,可以根据该定义来计算在性别与颜色两个变量独立的情况下,每个变量取值的期望概率(理论概率。例如,计算性别为男,颜色为红色为例。

P(A=男, B=红色) = P(A=男) * P(B=红色) =(43 + 50 + 24 + 31 + 52) / 384 * (43 + 38) / 384 =0.52083 * 0.2109 =0.10986328125

有了期望概率,就可以很容易计算每个取值的期望频数: Expected(A=男, B=红色) = count * P(A=男, B=红色) =384 *0.10986328125 =42.1875

observed = [[43, 50, 24, 31, 52], [38, 42, 30, 29, 45]] stats.chi2_contingency(observed)

P>0.05,维持原假设,认为理论频数与实际频数一致(意味着两个变量是独立的),得出结论:性别对手机颜色没有影响,他们之间没有关系。

本文作者:a

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!