前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >怎么样描述你的数据——用python做描述性分析

怎么样描述你的数据——用python做描述性分析

作者头像
刘早起
发布2020-04-22 16:05:23
2K0
发布2020-04-22 16:05:23
举报
文章被收录于专栏:早起Python早起Python

描述性分析介绍

描述性统计分析是关于数据的描述和汇总。它使用两种主要方法:

  1. 定量方法以数值方式描述和汇总数据。
  2. 可视化方法通过图表,曲线图,直方图和其他图形来说明数据。

一般在数据分析的过程中,拿到数据不会去直接去建模,而是先做描述性分析来对数据有一个大致的把握,很多后续的建模方向也是通过描述性分析来进一步决定的。那么除了在Excel/R中可以去做描述性分析。

本文将细致讲解如何使用python进行描述性分析的定量分析部分:

  • 均值
  • 中位数
  • 方差
  • 标准差
  • 偏度
  • 百分位数
  • 相关性

至于可视化的部分可以参考我之前讲解pyecharts的文章,当然后面还会介绍echarts以及ggplot2的方法。

涉及到的python库

  • Python statistics是用于描述性统计信息的内置Python库。如果您的数据集不是太大,或者您不能依赖于导入其他库,则可以使用它。
  • NumPy是用于数字计算的第三方库,已针对使用一维和多维数组进行了优化。它的主要类型是称为的数组类型ndarray。该库包含许多用于统计分析的方法。
  • SciPy是基于NumPy的用于科学计算的第三方库。与NumPy相比,它提供了其他功能,包括scipy.stats统计分析。Getting started - SciPy.org
  • Pandas是基于NumPy的用于数值计算的第三方库。它擅长处理带有Series对象的带标签的一维(1D)数据和带有对象的二维(2D)数据DataFrame
  • Matplotlib是用于数据可视化的第三方库。通常会与NumPy,SciPy和Pandas结合使用

开始

首先导入所有的包

代码语言:javascript
复制
import math
import statistics
import numpy as np
import scipy.stats
import pandas as pd

创建数据

xx_with_nan都是list。不同之处在于x_with_nan包含一个nan值。也就是空值(缺失值),这样的数据在分析中十分常见。那么在python里,创建一个nan值可以有以下方法

代码语言:javascript
复制
float('nan')
math.nan
np.nan

当然这三种方法创建的空值都是等价的

但是真的相等吗,两个nan是不相等的,换句话说,是不可以进行比较的,这后面的故事以后再说。

接着,我们使用numpy和pandas来创建两个一维numpy arrays和pandas series

均值

均值的定义啥的,就不说了,R里面直接mean()就可以,而在python,不导入包,怎么计算:

当然也可以用python的内置统计功能

但是如果数据中包含nan,那么将返回nan

代码语言:javascript
复制
>>> mean_ = statistics.mean(x_with_nan)
>>> mean_
nan

如果使用numpy

代码语言:javascript
复制
>>> mean_ = np.mean(y)
>>> mean_
8.7

在上面的示例中,mean()是一个函数,但是您也可以使用相应的方法

代码语言:javascript
复制
>>> mean_ = y.mean()
>>> mean_
8.7

如果包含nan,numpy也会返回nan,那么要是想忽略nan,可以使用np.nanmean()

代码语言:javascript
复制
>>> np.mean(y_with_nan)
nan
>>> np.nanmean(y_with_nan)
8.7

pandas也有对应方法,但是,默认情况下,.mean()在Pandas中忽略nan值:

代码语言:javascript
复制
mean_ = z.mean()
mean_
>>> z_with_nan.mean()
8.7

中位数

比较平均值和中位数,这是检测数据中异常值和不对称性的一种方法。平均值还是中位数对您更有用,取决于特定问题的背景。而不使用包的计算方法:

代码语言:javascript
复制
>>> n = len(x)
>>> if n % 2:
...     median_ = sorted(x)[round(0.5*(n-1))]
... else:
...     x_ord, index = sorted(x), round(0.5 * n)
...     median_ = 0.5 * (x_ord[index-1] + x_ord[index])
...
>>> median_
4

其他方法

代码语言:javascript
复制
>>> median_ = np.median(y)
>>> median_
4.0
>>> np.nanmedian(y_with_nan)
4.0

方差

方差的意义也不过多说明,在Excel中直接用stdev函数,但是怎么在python中计算?记得当初研究生复试就被问到用python不导入包怎么计算方差?

代码语言:javascript
复制
>>> n = len(x)
>>> mean_ = sum(x) / n
>>> var_ = sum((item - mean_)**2 for item in x) / (n - 1)
>>> var_
123.19999999999999

当然更简单的方法是直接使用函数,不过有nan还是会返回nan

代码语言:javascript
复制
>>> var_ = statistics.variance(x)
>>> var_
123.2
>>> statistics.variance(x_with_nan)
nan

放在numpy里面就更简单了,可以使用np.var()或者.var()

代码语言:javascript
复制
>>> var_ = np.var(y, ddof=1)
>>> var_
123.19999999999999
>>> var_ = y.var(ddof=1)
>>> var_
123.19999999999999

这里ddof就是自由度要设置为1才是无偏的。也就是分母用n-1替换n。如果有nan怎么办?返回nan,但是可以用np.nanvar()跳过nan,不过ddof依旧要设置为1

代码语言:javascript
复制
>>> np.var(y_with_nan, ddof=1)
nan
>>> y_with_nan.var(ddof=1)
nan
>>> np.nanvar(y_with_nan, ddof=1)
123.19999999999999

标准差

有了方差,标准差就很好计算了

代码语言:javascript
复制
#直接计算
>>> std_ = var_ ** 0.5
>>> std_
11.099549540409285
#使用内置包
>>> std_ = statistics.stdev(x)
>>> std_
11.099549540409287

numpy中也很好计算

代码语言:javascript
复制
>>> np.std(y, ddof=1)
11.099549540409285
>>> y.std(ddof=1)
11.099549540409285
>>> np.std(y_with_nan, ddof=1)
nan
>>> y_with_nan.std(ddof=1)
nan
>>> np.nanstd(y_with_nan, ddof=1) #跳过nan,ddof还是要是1哦
11.099549540409285

偏度(skew)

偏度(skewness)也称为偏态、偏态系数,是统计数据分布偏斜方向和程度的度量,是统计数据分布非对称程度的数字特征。偏度是利用3阶矩定义的,偏度的计算公式为:

我们之前研究的数据都是比较对称的数据,但是上图就给出了不对称的数据集,第一组用绿点表示,第二组用白点表示。通常,负偏度值表示左侧有一个占主导地位的尾巴,可以在第一个集合中看到。正偏度值对应于右侧较长或的尾巴,可以在第二组中看到。如果偏度接近0(例如,介于-0.5和0.5之间),则该数据集被认为是非常对称的。

那么不依赖第三包,怎么计算偏度。可以先计算完数据集的大小n,样本均值mean和标准差std后用公式计算

代码语言:javascript
复制
>>> x = [8.0, 1, 2.5, 4, 28.0]
>>> n = len(x)
>>> mean_ = sum(x) / n
>>> var_ = sum((item - mean_)**2 for item in x) / (n - 1)
>>> std_ = var_ ** 0.5
>>> skew_ = (sum((item - mean_)**3 for item in x)
...          * n / ((n - 1) * (n - 2) * std_**3))
>>> skew_
1.9470432273905929

可以看出偏度为正,因此x尾巴在右侧。

也可以用第三方包计算

代码语言:javascript
复制
>>> y, y_with_nan = np.array(x), np.array(x_with_nan)
>>> scipy.stats.skew(y, bias=False)
1.9470432273905927
>>> scipy.stats.skew(y_with_nan, bias=False)
nan
>>> z, z_with_nan = pd.Series(x), pd.Series(x_with_nan)
>>> z.skew()
1.9470432273905924
>>> z_with_nan.skew()
1.9470432273905924

百分位数(Percentiles)

如果将一组数据从小到大排序,并计算相应的累计百分位,则某一百分位所对应数据的值就称为这一百分位的百分位数。可表示为:一组n个观测值按数值大小排列。如,处于p%位置的值称第p百分位数。每个数据集都有三个四分位数,这是将数据集分为四个部分的百分位数:

  • 第一四分位数 (Q1),又称“较小四分位数”,等于该样本中所有数值由小到大排列后第25%的数字。
  • 第二四分位数 (Q2),又称“中位数”,等于该样本中所有数值由小到大排列后第50%的数字。
  • 第三四分位数 (Q3),又称“较大四分位数”,等于该样本中所有数值由小到大排列后第75%的数字。

第三四分位数与第一四分位数的差距又称四分位距(InterQuartile Range,IQR)。

那么在python里面怎么计算分位数呢。可以使用statistics.quantiles()

代码语言:javascript
复制
>>> x = [-5.0, -1.1, 0.1, 2.0, 8.0, 12.8, 21.0, 25.8, 41.0]
>>> statistics.quantiles(x, n=2)
[8.0]
>>> statistics.quantiles(x, n=4, method='inclusive')
[0.1, 8.0, 21.0]

可以看到第一行中,8就是x的中位数,而第二个例子中,0.1和21是样本的25%和75%分位数。也可以使用第三方包numpy计算

代码语言:javascript
复制
>>> np.percentile(y, [25, 50, 75])
array([ 0.1,  8. , 21. ])
>>> np.median(y)
8.0
#跳过nan
>>> y_with_nan = np.insert(y, 2, np.nan)
>>> y_with_nan
array([-5. , -1.1,  nan,  0.1,  2. ,  8. , 12.8, 21. , 25.8, 41. ])
>>> np.nanpercentile(y_with_nan, [25, 50, 75])
array([ 0.1,  8. , 21. ])

pandas也可以使用.quantile()计算,需要提供分位数值作为参数。该值可以是0到1之间的数字或数字序列。

代码语言:javascript
复制
>>> z, z_with_nan = pd.Series(y), pd.Series(y_with_nan)
>>> z.quantile(0.05)
-3.44
>>> z.quantile(0.95)
34.919999999999995
>>> z.quantile([0.25, 0.5, 0.75])
0.25     0.1
0.50     8.0
0.75    21.0
dtype: float64
>>> z_with_nan.quantile([0.25, 0.5, 0.75])
0.25     0.1
0.50     8.0
0.75    21.0
dtype: float64

范围(Ranges)

数据的范围是数据集中最大和最小元素之间的差。可以通过函数np.ptp()获得:

代码语言:javascript
复制
>>> np.ptp(y)
27.0
>>> np.ptp(z)
27.0
>>> np.ptp(y_with_nan)
nan
>>> np.ptp(z_with_nan)
27.0

描述性统计摘要

在SciPy和Pandas提供过单个函数或方法调用快速获取描述性统计信息。

代码语言:javascript
复制
>>> result = scipy.stats.describe(y, ddof=1, bias=False)
>>> result
DescribeResult(nobs=9, minmax=(-5.0, 41.0), mean=11.622222222222222, variance=228.75194444444446, skewness=0.9249043136685094, kurtosis=0.14770623629658886)

describe() 返回包含以下信息:

  • nobs:数据集中的观测值或元素数
  • minmax:数据的最大和最小值
  • mean:数据集的平均值
  • variance:数据集的方差
  • skewness:数据集的偏度
  • kurtosis:数据集的峰度
代码语言:javascript
复制
>>> result.nobs
9
>>> result.minmax[0]  # Min
-5.0
>>> result.minmax[1]  # Max
41.0
>>> result.mean
11.622222222222222
>>> result.variance
228.75194444444446
>>> result.skewness
0.9249043136685094
>>> result.kurtosis
0.14770623629658886

pandas也有类似的函数.describe():

代码语言:javascript
复制
>>> result = z.describe()
>>> result
count     9.000000 #数据集中的元素数
mean     11.622222 #数据集的平均值
std      15.124548 #数据集的标准差
min      -5.000000
25%       0.100000 #数据集的四分位数
50%       8.000000
75%      21.000000
max      41.000000
dtype: float64

相关性

相关行的统计学意义也不在过多说明,但是要注意,相关性只是能从数据上判断是否有关系,不能够说明因果关系!!!

度量相关性主要使用协方差和相关性系数:

那么我们先重新创建数据

代码语言:javascript
复制
>>> x = list(range(-10, 11))
>>> y = [0, 2, 2, 2, 2, 3, 3, 6, 7, 4, 7, 6, 6, 9, 4, 5, 5, 10, 11, 12, 14]
>>> x_, y_ = np.array(x), np.array(y)
>>> x__, y__ = pd.Series(x_), pd.Series(y_)

计算协方差

代码语言:javascript
复制
>>> n = len(x)
>>> mean_x, mean_y = sum(x) / n, sum(y) / n
>>> cov_xy = (sum((x[k] - mean_x) * (y[k] - mean_y) for k in range(n))
...           / (n - 1))
>>> cov_xy
19.95

numpyh和pandas都有可以返回协方差矩阵函数cov()

代码语言:javascript
复制
# numpy
>>> cov_matrix = np.cov(x_, y_)
>>> cov_matrix
array([[38.5       , 19.95      ],
       [19.95      , 13.91428571]])
# pandas
>>> cov_xy = x__.cov(y__)
>>> cov_xy
19.95
>>> cov_xy = y__.cov(x__)
>>> cov_xy
19.95

计算相关系数

我们这里说的均是pearson相关系数。Pearson相关系数(Pearson CorrelationCoefficient)是用来衡量两个数据集合是否在一条线上面,它用来衡量定距变量间的线性关系。计算公式为?=?ˣʸ/(?ˣ?ʸ)在python里面直接计算需要先计算均值和标准差。

代码语言:javascript
复制
>>> var_x = sum((item - mean_x)**2 for item in x) / (n - 1)
>>> var_y = sum((item - mean_y)**2 for item in y) / (n - 1)
>>> std_x, std_y = var_x ** 0.5, var_y ** 0.5
>>> r = cov_xy / (std_x * std_y)
>>> r
0.861950005631606

也可以用scipy.stats计算:

代码语言:javascript
复制
>>> r, p = scipy.stats.pearsonr(x_, y_)
>>> r
0.861950005631606
>>> p
5.122760847201171e-07

其中p代表p值,p值的意思我们以后再说。类似协方差,我们也能计算相关系数矩阵

代码语言:javascript
复制
>>> corr_matrix = np.corrcoef(x_, y_)
>>> corr_matrix
array([[1.        , 0.86195001],
       [0.86195001, 1.        ]])
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 早起Python 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 涉及到的python库
  • 开始
    • 方差
      • 范围(Ranges)
        • 描述性统计摘要
          • 相关性
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档