成功的秘诀在于:当机会来临时,你已准备妥当。 —— 23号老板
原创:a廉小宝
检验温差是否满足正态分布
代码语言:javascript复制import requests
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
第一步获取数据
代码语言:javascript复制re = requests.get("http://jse.amstat.org/datasets/normtemp.dat.txt")
re.encoding = "utf-8"
with open("normtemp.dat.txt","w") as f:
f.write(re.text)
# sep='s ' ,正则表达式,表示分隔符为一个或多个空;s表示匹配空白,即空格,tab键
df = pd.read_csv("normtemp.dat.txt", header=None, sep="s ")
df.columns = ['体温','性别','心率']
df.head()
体温 | 性别 | 心率 | |
---|---|---|---|
0 | 96.3 | 1 | 70 |
1 | 96.7 | 1 | 71 |
2 | 96.9 | 1 | 74 |
3 | 97.0 | 1 | 80 |
4 | 97.1 | 1 | 73 |
第二步 查看数据的基本情况
代码语言:javascript复制df.describe()
体温 | 性别 | 心率 | |
---|---|---|---|
count | 130.000000 | 130.000000 | 130.000000 |
mean | 98.249231 | 1.500000 | 73.761538 |
std | 0.733183 | 0.501934 | 7.062077 |
min | 96.300000 | 1.000000 | 57.000000 |
25% | 97.800000 | 1.000000 | 69.000000 |
50% | 98.300000 | 1.500000 | 74.000000 |
75% | 98.700000 | 2.000000 | 79.000000 |
max | 100.800000 | 2.000000 | 89.000000 |
散点图
代码语言:javascript复制plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
fig=plt.figure(figsize=(16,5))
plt.scatter(df['性别'],df['体温'],c='b',marker='o',alpha=0.7)
plt.title('Scatter')
plt.xlabel('sex')
plt.ylabel('temp')
plt.grid(True)
plt.show()
代码语言:javascript复制plt.scatter(df['心率'],df['体温'],c='b',marker='<',alpha=0.7)
plt.title('scatter')
plt.xlabel('heart')
plt.ylabel('temp')
plt.grid(True)
plt.show()
代码语言:javascript复制fig=plt.figure(figsize=(16,5))
plt.scatter(df['性别'],df['心率'],c='b',marker='o',alpha=0.7)
plt.title('Scatter')
plt.xlabel('sex')
plt.ylabel('heart')
plt.grid(True)
plt.show()
柱形图
代码语言:javascript复制# 函数说明:
# arange([start,] stop[, step,], dtype=None)根据start与stop指定的范围以及step设定的步长,生成一个 ndarray。
# >>> arange(0,1,0.1)
# array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
# range()
# >>> range(0,5) #生成一个range object,而不是[0,1,2,3,4]
# range(0, 5)
# >>> c = [i for i in range(0,5)] #从0 开始到4,不包括5,默认的间隔为1
# >>> c
# [0, 1, 2, 3, 4]
# >>> c = [i for i in range(0,5,2)] #间隔设为2
# >>> c
# [0, 2, 4]
x=np.arange(0,130,1)
y=df['体温'].values
plt.bar(x,y)
代码语言:javascript复制<BarContainer object of 130 artists>
代码语言:javascript复制x=np.arange(0,130,1)
y=df['心率'].values
plt.bar(x,y)
代码语言:javascript复制<BarContainer object of 130 artists>
直方图
代码语言:javascript复制df['体温'].hist(bins=20,alpha=0.5)
代码语言:javascript复制<matplotlib.axes._subplots.AxesSubplot at 0x1218097f0>
代码语言:javascript复制# 密度图也被称为KDF图,
# 调用plt时加上kind='kde'即可生成一张密度图
df['体温'].plot(kind='kde',secondary_y=True)
代码语言:javascript复制<matplotlib.axes._subplots.AxesSubplot at 0x1219a1198>
密度直方图
代码语言:javascript复制df['体温'].hist(bins=20,alpha=0.5)
df['体温'].plot(kind='kde',secondary_y=True)
代码语言:javascript复制<matplotlib.axes._subplots.AxesSubplot at 0x1a234f0940>
用python为直方图绘制拟合曲线,使用seaborn中的displot绘制
代码语言:javascript复制import seaborn as sns
sns.set_palette("hls") #设置所有图的颜色,使用hls色彩空间
sns.distplot(df['体温'],color="r",bins=30,kde=True)
plt.show()
代码语言:javascript复制/Users/lianxiaobao/anaconda/anaconda3/lib/python3.7/site-packages/scipy/stats/stats.py:1713: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
return np.add.reduce(sorted[indexer] * weights, axis=axis) / sumval
代码语言:javascript复制# 设置详细的参数,可采用kde_kws(拟合曲线的设置),hist_kws(直方图柱子的设置)
import seaborn as sns
import matplotlib as mpl
sns.set_palette("hls")
mpl.rc("figure", figsize=(6,4))
# lw为曲线的粗细程度
sns.distplot(df['体温'],bins=30,kde_kws={"color":"seagreen", "lw":3 }, hist_kws={ "color": "b" })
plt.show()
第三步 检验体温数据是否服从正态分布
前三个方法的p值均大于0.05,说明体温服从正态分布
方法一:scipy.stats.normaltest (a, axis=0)
代码语言:javascript复制# a - 待检验数据,
# axis - 可设置为整数或置空,如果设置为 none,则待检验数据被当作单独的数据集来进行检验。该值默认为 0,即从 0 轴开始逐行进行检验。
import scipy.stats
scipy.stats.normaltest(df['体温'])
代码语言:javascript复制NormaltestResult(statistic=2.703801433319236, pvalue=0.2587479863488212)
方法二:Shapiro-Wilk test, scipy.stats.shapiro(x)
参数:x - 待检验数据
返回:W - 统计数;p-value - p值
代码语言:javascript复制scipy.stats.shapiro(df['体温'].values)
代码语言:javascript复制(0.9865770936012268, 0.233174666762352)
方法三:scipy.stats.kstest; scipy.stats.kstest (rvs, cdf, args = ( ), N = 20, alternative =‘two-sided’, mode =‘approx’)
rvs - 待检验数据,可以是字符串、数组;
cdf - 需要设置的检验,这里设置为 norm,也就是正态性检验;
alternative - 设置单双尾检验,默认为 two-sided
返回:W - 统计数;p-value - p值
代码语言:javascript复制u = df['体温'].mean()
std = df['体温'].std()
scipy.stats.kstest(df['体温'].values,'norm',args=(u,std))
代码语言:javascript复制KstestResult(statistic=0.06472685044046644, pvalue=0.6450307317439967)
方法四:Anderson-Darling test; scipy.stats.anderson (x, dist =‘norm’ )
该方法是由 scipy.stats.kstest 改进而来的,可以做正态分布、指数分布、Logistic 分布、Gumbel 分布等多种分布检验。默认参数为 norm,即正态性检验。
参数:x - 待检验数据;dist - 设置需要检验的分布类型
返回:statistic - 统计数;critical_values - 评判值;significance_level - 显著性水平
代码语言:javascript复制scipy.stats.anderson(df['体温'].values,dist="norm")
代码语言:javascript复制AndersonResult(statistic=0.5201038826714353, critical_values=array([0.56 , 0.637, 0.765, 0.892, 1.061]), significance_level=array([15. , 10. , 5. , 2.5, 1. ]))