当前位置: 首页 > news >正文

【python】计算偏度和峰度

本篇博文,首发在AIexplore微信公众号,内容总体相同,均为原创,特此申明。

0.教程代码环境

# 其他环境也可以,不一定非要一样
python 3.6
numpy 1.19.3
matplotlib 3.2.1
scipy 1.4.1

1.偏度

定义:偏度(skewness),是统计数据分布偏斜方向和程度的度量,或者说是统计数据分布非对称程度的数字特征。

说人话:偏度或偏态系数或偏度系数(Skewness)用来度量分布是否对称,一个分布如果不对称,则被称为偏度。

分布分为三种:对称分布(正态分布)、正偏分布(右偏分布)、负偏分布(左偏分布)
对称分布的特点:左右对称,均值 = 中位数 = 众数,偏度 = 0
正偏分布的特点:右侧长尾,均值 >中位数 >众数,偏度 > 0
负偏分布的特点:左侧长尾,均值 < 中位数 < 众数,偏度 < 0

1.1 绘制三种分布图

1.1.1 使用python代码绘制正态分布:

代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# python 3.6
# numpy 1.19.3
# matplotlib 3.2.1
# scipy 1.4.1
def plot():
    """
    绘制标准的正态分布
    draw standard deviation normal distribution
    """
    mu = 0.0    # mean 均值
    sd = 1.0    # std 标准差
    x = np.linspace(mu - 4 * sd, mu + 4 * sd, 100) # x range
    y = stats.norm.pdf(x)
    plt.plot(x, y, "g", linewidth = 2)
    plt.grid(True)  # 显示网格线
    plt.show()


if __name__ == '__main__':
    plot()

分布图:

在这里插入图片描述

1.1.2 使用python代码绘制右偏分布:

代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# python 3.6
# matplotlib 3.2.1
# scipy 1.4.1
def plot():
    """
    绘制标准的正偏分布
    """
    mu = 0.0    # mean 均值
    sd = 1.0    # std 标准差
    x = np.linspace(mu - 3 * sd, mu + 5 * sd, 100) # x range
    y = stats.norm.pdf(x)
    plt.plot(x, y, "g", linewidth = 2)
    plt.grid(True)  # 显示网格线
    plt.show()


if __name__ == '__main__':
    plot()

分布图:
在这里插入图片描述

1.1.3 使用python代码绘制左偏分布:

代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# python 3.6
# matplotlib 3.2.1
# scipy 1.4.1
def plot():
    """
    绘制标准的正偏分布
    """
    mu = 0.0    # mean 均值
    sd = 1.0    # std 标准差
    x = np.linspace(mu - 5 * sd, mu + 3 * sd, 100) # x range
    y = stats.norm.pdf(x)
    plt.plot(x, y, "g", linewidth = 2)
    plt.grid(True)  # 显示网格线
    plt.show()


if __name__ == '__main__':
    plot()        

分布图:

在这里插入图片描述

1.2 偏度计算

计算公式:

在这里插入图片描述

有的文章里面计算公式是这样的:

在这里插入图片描述

以上公式来自不同的出处,我不是学数学的,因此对这些内容没有太深入的研究(主要是我以前从来没遇到过,知识盲区;如果有学数学的朋友懂这方面知识,可以私聊我给我普及一下),我的理解是公式1和公式2应该没有对错之分,只是“选择”不同罢了(不知道对不对,如有大佬请在评论区修正),那我们计算偏度到底使用哪个公式呢?请继续阅读下文。

具体例子:
一组数据:arr = [1,4,6,8,10,20]

arr的均值和标准差我们使用numpy库直接进行计算 :

均值

import numpy as np

# arr = np.array([1,2,2,4,1])
# arr = np.array([3,6,3,9,10,12,36,3])
arr = np.array([1,4,6,8,10,20])

u = arr.mean()
print("均值:", u)

在这里插入图片描述

标准差
标准差分为总体标准差(分母位n)和样本标准差(分母n-1)【为什么分为总体标准差和样本标准差,感兴趣的可以自己找资料研究,在此不深入说明了】

import numpy as np

# arr = np.array([1,2,2,4,1])
# arr = np.array([3,6,3,9,10,12,36,3])
arr = np.array([1,4,6,8,10,20])

# a = np.std(arr, ddof=1) # 无偏 分母n-1, 有偏 分母n
a = arr.std(ddof=1)       # ddof=1无偏,ddof=0有偏
print("标准差:", a)   

这里我们使用无偏的标准差(不要问为什么,因为用无偏的比较“好”,大家都是用的无偏)。
在这里插入图片描述
知道了均值和标准差,就可以带入公式计算偏度了。
那么问题来了,我们应该带入到哪个公式呢?下面我们分别带入到2个公式中,查看一下结果。

使用公式1:

import numpy as np
import pandas as pd
from scipy import stats

# arr = np.array([1,2,2,4,1])
# arr = np.array([3,6,3,9,10,12,36,3])
arr = np.array([1,4,6,8,10,20])

n = len(arr)
u = arr.mean()
print("均值:", u)

# a = np.std(arr, ddof=1) # 无偏 分母n-1, 有偏 分母n
a = arr.std(ddof=1)       # ddof=1无偏,ddof=0有偏
print("标准差:", a)   


a1 = sum(((arr-u)/a)**3)
a2 = a1*n/((n-1)*(n-2))
print("偏度:", a2)

在这里插入图片描述
使用公式2:

import numpy as np
import pandas as pd
from scipy import stats

# arr = np.array([1,2,2,4,1])
# arr = np.array([3,6,3,9,10,12,36,3])
arr = np.array([1,4,6,8,10,20])

n = len(arr)
u = arr.mean()
print("均值:", u)

# a = np.std(arr, ddof=1) # 无偏 分母n-1, 有偏 分母n
a = arr.std(ddof=1)       # ddof=1无偏,ddof=0有偏
print("标准差:", a)   


a1 = sum(((arr-u)/a)**3)
a2 = a1/n
print("偏度:", a2)

在这里插入图片描述
可以看到使用不同公式计算得到的偏度不同:
公式1得到的偏度:1.2737636108819756
公式2得到的偏度:0.7076464504899865

不同公式得到的偏度肯定是不一样的,那我们到底应该采用哪一个偏度值呢?下面我们使用python科学计算包直接计算偏度:

使用pandas计算:

import numpy as np
import pandas as pd

# arr = np.array([1,2,2,4,1])
# arr = np.array([3,6,3,9,10,12,36,3])
arr = np.array([1,4,6,8,10,20])

print("--------使用pandas计算偏度和峰度--------")
# pandas计算标准差是无偏的
data = pd.DataFrame(arr)
print("标准差:", data[0].std())
print("偏度:", data[0].skew())

在这里插入图片描述
可以看到,标准差6.5853372477547923,使用的是无偏标准差;偏度1.2737636108819759,和公式1计算的结果相同。从侧面验证了pandas库使用的是无偏标准差+公式1来计算偏度。

使用scipy计算:

import numpy as np
from scipy import stats

# arr = np.array([1,2,2,4,1])
# arr = np.array([3,6,3,9,10,12,36,3])
arr = np.array([1,4,6,8,10,20])

print("--------使用scipy计算偏度和峰度--------")
# scipy计算标准差,通过ddof控制有偏和无偏,ddof=1无偏,ddof=0有偏
print("标准差:", stats.tstd(arr, ddof=1))
d = stats.skew(arr, bias=False)     # bias默认为True
print("偏度:", d)

在这里插入图片描述
可以看到,标准差6.585337247754792,使用的是无偏标准差;偏度1.2737636108819756,和公式1计算结果、pandas库计算结果相同。再次验证了应该使用公式1来计算偏度。

2.峰度

定义:峰度(peakedness;kurtosis)又称峰态系数。表征概率密度分布曲线在平均值处峰值高低的特征数。
说人话:峰度反映了峰部的尖度,用来度量数据在中心聚集程度,峰度越大分布图越尖,峰度越小分布图越矮胖。

2.1 绘制三种不同峰度的分布图

代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats


def plot():
    """
    draw standard deviation normal distribution
    """
    mu = 0.0    # mean
    sd1 = 1.0    # std
    sd2 = 2.0
    sd3 = 3.0

    # red line
    x = np.linspace(mu - 3 * sd1, mu + 3 * sd1, 50) # x range
    y = stats.norm.pdf(x)
    plt.plot(x, y, "r", linewidth = 2)

    # green line
    x2 = np.linspace(mu - 6 * sd1, mu + 6 * sd1, 50) # x range
    y2 = stats.norm.pdf(x2, mu, sd2)
    plt.plot(x2, y2, "g", linewidth = 2)

    # blue line
    x3 = np.linspace(mu - 10 * sd1, mu + 10 * sd1, 50) # x range
    y3 = stats.norm.pdf(x3, mu, sd3)
    plt.plot(x3, y3, "b", linewidth = 2)

    plt.grid(True)  # 显示网格线
    plt.show()

if __name__ == '__main__':
    plot()

分布图:
相同均值,不同标准差的正态分布曲线
相同均值、不同标准差的正态分布曲线

红色线条标准差是1,绿色线条标准差是2,蓝色线条标准差是3。
标准差越小,曲线越陡
标准差越大,曲线越平缓
红色线条:尖峰
绿色线条:中锋
蓝色线条:低峰

对于正态分布来说峰度=3,部分统计软件会给出超额峰度,超额峰度=峰度-3。
中锋分布的超额峰度=0, 尖峰分布的超额峰度>0,低峰分布的超额峰度<0。

2.2 峰度计算

峰度的计算公式,我也看到好几个版本,我想应该和偏度的计算类似,因此不再纠结它的计算公式,直接使用pandas或scipy进行计算。

代码:

import numpy as np
import pandas as pd
from scipy import stats

# arr = np.array([1,2,2,4,1])
# arr = np.array([3,6,3,9,10,12,36,3])
arr = np.array([1,4,6,8,10,20])

print("--------使用scipy计算偏度和峰度--------")
# scipy计算标准差,通过ddof控制有偏和无偏,ddof=1无偏,ddof=0有偏
print("标准差:", stats.tstd(arr, ddof=1))
d = stats.skew(arr, bias=False)     # bias默认为True
print("偏度:", d)
e = stats.kurtosis(arr, bias=False) # bias默认为True
print("峰度:", e)

print("--------使用pandas计算偏度和峰度--------")
# pandas计算标准差是无偏的
data = pd.DataFrame(arr)
print("标准差:", data[0].std())
print("偏度:", data[0].skew())
print("峰度:", data[0].kurt())

结果:
在这里插入图片描述

3.整体代码

import numpy as np
import pandas as pd
from scipy import stats

# arr = np.array([1,2,2,4,1])
# arr = np.array([3,6,3,9,10,12,36,3])
arr = np.array([1,4,6,8,10,20])

print("--------使用scipy计算偏度和峰度--------")
# scipy计算标准差,通过ddof控制有偏和无偏,ddof=1无偏,ddof=0有偏
print("标准差:", stats.tstd(arr, ddof=1))
d = stats.skew(arr, bias=False)     # bias默认为True
print("偏度:", d)
e = stats.kurtosis(arr, bias=False) # bias默认为True
print("峰度:", e)

print("--------使用pandas计算偏度和峰度--------")
# pandas计算标准差是无偏的
data = pd.DataFrame(arr)
print("标准差:", data[0].std())
print("偏度:", data[0].skew())
print("峰度:", data[0].kurt())

print("--------自己通过代码计算偏度和峰度,方式 1--------")
n = len(arr)
u = arr.mean()
print("均值", u)

# a = np.std(arr, ddof=1) # 无偏 分母n-1, 有偏 分母n
a = arr.std(ddof=1)       # ddof=1无偏,ddof=0有偏
print("标准差:", a)   

a1 = sum(((arr-u)/a)**3)
a2 = a1*n/((n-1)*(n-2))
print("偏度:", a2)

print("--------自己通过代码计算偏度和峰度,方式 2--------")
list_v = []
for v in arr:
    # print(v)
    q = (v-u)**3
    list_v.append(q)

b1 = sum(list_v)
b2 = b1/(a**3)
b3 = b2*n/((n-1)*(n-2))
print("偏度:", b3)

4.附录

我们也可以使用Excel直接计算一组数据的偏度和峰度。

Excel中的数据如下:

计算A1、A2、A3、A4、A5、A6数据的偏度和峰度。

偏度计算公式:=SKEW(A1:A6)
峰度计算公式:=KURT(A1:A6)

偏度1.2737,再一次验证了使用无偏标准差和公式1计算;峰度2.1546。

参考资料:

  1. https://blog.csdn.net/weixin_36236293/article/details/102632084
  2. https://zhidao.baidu.com/question/133028474.html
  3. https://blog.csdn.net/qq_36523839/article/details/88671873
  4. https://zhuanlan.zhihu.com/p/346810231
  5. https://zhuanlan.zhihu.com/p/84614017

相关文章:

  • 单片机原理指令系统习题超详细讲解
  • 使用Python,Keras和TensorFlow训练第一个CNN
  • Flutter: Dart 参数,以及 @required 与 required
  • 基于JAVA网上商城系统演示录像计算机毕业设计源码+数据库+lw文档+系统+部署
  • 【复杂网络】关于复杂网络中的动力学系统重构的文献资料整理
  • 应对数据安全典型薄弱点,这家医院“外防内控”筑牢屏障
  • 嵌入式开发:注释C代码的10个技巧
  • Qt5开发从入门到精通——第九篇一节( Qt5 文件及磁盘处理—— 读写文本文件)
  • ⌈Linux_ 感受系统美学⌋ 抛开图形化界面,深入探索命令行操作系统
  • 09-28 周三 使用朴素贝叶斯进行垃圾邮件处理
  • python+cuda编程(二)
  • 攻防世界-filemanager
  • 软件项目管理简答题
  • Spring源码分析(二):底层架构核心概念解析
  • vue3 watch的各种使用情景
  • JS 中的深拷贝与浅拷贝
  • 11111111
  • Android交互
  • js继承的实现方法
  • Linux快速复制或删除大量小文件
  • Quartz初级教程
  • VUE es6技巧写法(持续更新中~~~)
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 关于extract.autodesk.io的一些说明
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 实习面试笔记
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 提醒我喝水chrome插件开发指南
  • 微信公众号开发小记——5.python微信红包
  • 一些css基础学习笔记
  • 正则与JS中的正则
  • nb
  • ​ArcGIS Pro 如何批量删除字段
  • #QT(TCP网络编程-服务端)
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (javascript)再说document.body.scrollTop的使用问题
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (四) 虚拟摄像头vivi体验
  • (一)SpringBoot3---尚硅谷总结
  • (转)Sublime Text3配置Lua运行环境
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .NET Project Open Day(2011.11.13)
  • .Net 代码性能 - (1)
  • .Net6支持的操作系统版本(.net8已来,你还在用.netframework4.5吗)
  • .NET构架之我见
  • // an array of int
  • @hook扩展分析
  • [ IO.File ] FileSystemWatcher