赞
踩
本文将通过kaggle的一个实例来,来展示如何通过统计分析的方法来分析自己的数据集。当我们处理一个数据集,分析里面特征的时候。通常分成三个步骤:
这三个步骤也可以看成是从数据集中一层层提取出有用信息的方式。
下面将主要对统计分析这部分做详细展开。
探索分析的主要目的,是通过数据汇总,数据展示成图,数据透视等方式,来提取出一些有用的信息。这其中也包含前期,对数据的大致信息查看,和数据处理工作。
以kaggle的数据集为例下载地址https://www.kaggle.com/datasets/uciml/autompg-dataset
该数据记录了汽车的技术规格信息
实例数:398
特征数量:9个
各字段信息:
观察数据的一些大致信息,以及思考每列的数据类型,如果它是object类型,那么它是类别的,否则是数值的,对于是数值类型的数据,还要去重得唯一,看下数量(如果去唯一后数据量少),也可分成object类
import pandas as pd
df = pd.read_csv('mpg.csv')
# 1.查看数据信息
print(f'shape:{df.shape}')
print(f'columns:{list(df.columns)}')
print(f'info:{df.info}')
# 2.对数据类型,进行分类
categorical = list(df.select_dtypes(include=['object']).columns)
numerical = list(df.select_dtypes(exclude=['object']).columns)
print(f'categorical variables: {categorical}')
print(f'numerical variables: {numerical}')
categorical variables: ['origin', 'name']
numerical variables: ['mpg', 'cylinders', 'displacement', 'horsepower', 'weight', 'acceleration', 'model_year']
# 3.统计各特征下的唯一值的个数,对于唯一值个数少的且数据类型不为object的类型,转为object print(df.nunique(axis=0)) ''' out: mpg 129 cylinders 5 displacement 82 horsepower 93 weight 351 acceleration 95 model_year 13 origin 3 name 305 dtype: int64 ''' #从上面数量看,以及对应到之前的数据类型,发现cylinders和moderl year需要转化 categorical.extend(['cylinders', 'model_year']) numerical.remove('cylinders') numerical.remove('model_year')
缺失值
df.isna().sum() ''' mpg 0 cylinders 0 displacement 0 horsepower 6 weight 0 acceleration 0 model_year 0 origin 0 name 0 dtype: int64 ''' #查看缺失部分的数据,看下缺失数据的占比 df[df.isnull().any(axis=1)] print(f'null rate:{6 / len(df)}')
这里考虑到占比较少,因此对缺失的处理方式就删除(注意删除后,数据集的索引要重新排列),真实的缺失值要结合不同场景下去判断。
df = df[~df.isnull().any(axis=1)]
df.reset_index(inplace=True)
df.drop('index', inplace=True, axis=1)
重复值
# 查找全部重复条目并删除它们(如果有)
print(f'total duplicate rows: {df.duplicated().sum()}')
# drop duplicate rows if any
df = df[~df.duplicated()]
去除掉数值信息中的空格
for col in ['origin', 'name']:
df[col] = df[col].apply(lambda x: ' '.join(x.split()))
将英里数mpg划分成object
df['mpg_level'] = df['mpg'].apply(lambda x: 'low' if x<17 else 'high' if x>29 else 'medium')
categorical.append('mpg_level')
合并categorical和numerical
df = pd.concat((df[cats], df[nums]), axis=1)
到这里应该可以发现,我们初步数据探索,数据处理,其实是从数据宏观的角度开始逐渐往下处理(先看整体情况,然后把数据补齐,最后在做数据上值的信息处理),具体的数据如何处理
接下来最重要的部分就是统计分析,我们需要借助假设检验的知识,来判断各特征属性之间的关系,各特征下,不同因子之间的关系。通过假设检验可以做到分析中得出:
再开始分析之前介绍一下假设检验中各种检验的使用,是在怎么样的条件下选择的
假设检验分为:参数检验和非参数检验
参数检验的方法有,T检验、Z检验、F检验、二项分布总体的假设检验等,这些检验都是假设样本来自于正态分布的总体,将总体的数字特征看做未知的参数,通过样本的数据特征对其总体进行统计推断
常用的非参数检验的方法有,两个独立样本的K-S检验、W-W检验、U检验等,多个独立样本的H检验、中位数检验等,卡方检验,二项分布检验、拟合优度检验等
从解释上来看,都是基于样本去对总体参数做估计,那我们的数据不就是总体的吗,难道要抽样吗?。
我理解的,我们通常做这类型假设检验拿到的数据总体其实就是一个样本,用我们的数据去对总体提出假设检验,但是这个总体其实是不存在的,
常规的数据如果数据量越来越大的话,这个总体分布,一定是呈现正态分布(中心极限定理)。
中心极限定理,是指概率论中讨论随机变量序列部分和分布渐近于正态分布的一类定理
所以我们分析,对比数据的显著性差异,其实是构造了一个虚拟的总体,通过总体的参数来分析结论。
关于假设检验的原假设和备用假设,大致记住我们的原假设一定是等于什么什么:例如:
统计分析处理也是存在一个固定的流程的
根据之前我们划分的categorical和numerical,我们分别对categorical的特征做独立性测试,对numerical的特征做正态性测试和相关性测试
具体如何选择那种检验方法可以对应到下面这条思维导图
定量数据:numerical
分类数据:categorical
分类数据,其实就是对不同类别的数据,进行频数统计,类似于excel里数据透视图中求值的count。
接下来就按照假设检验的方法开始分析我们的数据了
categorical variables: ['origin', 'name', 'cylinders', 'model_year','mpg_level'']
numerical variables: ['mpg', 'displacement', 'horsepower', 'weight', 'acceleration']
先对origin、model_year做独立检验,从上图选择那种方法需要看样本数和频数pandas中pd.crosstab函数可以很好的应用到这里。
pd.crosstab(df.origin, df.model_year)
可以看到origin和model_year不能实用于这里,接下来对origin和mpg_level分析
observed_values = pd.crosstab(df.origin, df.mpg_level).value
'''
out:
array([[ 22, 2, 44],
[ 49, 0, 30],
[ 24, 90, 131]])
'''
符合配对卡方检验
chi2, p, dof, expected_values = stats.chi2_contingency(observed_values)
chi2, p, dof, expected_values
'''
(123.76491109767298,
8.381476294026467e-26,
4,
array([[ 16.47959184, 15.95918367, 35.56122449],
[ 19.14540816, 18.54081633, 41.31377551],
[ 59.375 , 57.5 , 128.125 ]]))
'''
pvalue值<0.05 拒绝原假设,所以origin和mpg_level没有相关性。
定量变量正态性检验分成二个部分:
有三种统计检验用于检查数据的正态性:
通常我们使用Shapiro Wilk检验足以。
通过对每一个numerical变量画出直方图观看是否为正态分布,
对数正态分布是对数呈正态分布的随机变量的分布。因此,如果随机变量X是对数正态分布,那么Y=ln(X)具有正态分布。
fig = pyplot.figure(1, (10, 4))
ax = pyplot.subplot(1,2,1)
sns.distplot(np.log2(df.mpg))
pyplot.tight_layout()
ax = pyplot.subplot(1,2,2)
sns.distplot(np.log2(df.weight))
pyplot.tight_layout()
pyplot.show()
由图发现weight不是对数正态分布,但mpg在视觉上看起来像对数正态。
感兴趣也可以增加一个QQplots来做检验
使用shapiro wilk检验对数值属性的正态性进行假设检验
原假设为等于,正态分布
def shapiro_wilk_test(df: pd.DataFrame, cols: list, alpha=0.05): for col in cols: _,p = stats.shapiro(df[col]) if p <= alpha: print(f'{col}拒绝原假设,无显著性,不是正态分布') else: print(f'{col}接受原假设,有显著性,是正态分布') shapiro_wilk_test(df, nums) ''' mpg 拒绝原假设,无显著性,不是正态分布 displacement 拒绝原假设,无显著性,不是正态分布 horsepower 拒绝原假设,无显著性,不是正态分布 weight 拒绝原假设,无显著性,不是正态分布 acceleration 拒绝原假设,无显著性,不是正态分布 '''
像现在这种情况,我们想让accleration为正态分布,但是检测出来不是,就需要对数据进行转换处理,让它转换为正态分布
from sklearn.preprocessing import PowerTransformer
df_tfnum = pd.DataFrame(PowerTransformer().fit_transform(df[numerical]), columns=numerical)
df_tfnum.head()
删除数据中nan的部分,再做一次正态检测(目测、在用shapiro_wilk_test检验一次),得到acceleration为正态分布。
当数据不为正态分布的时候,可以对数据做转换transform标准化
分析二个变量的相关性可以用皮尔逊相关系数
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。