LyndonPyProjPython学习日志

Python数据分析基础ReadingDay10_描述性统计与建

2018-03-22  本文已影响38人  放翁lcf

reading Foundations for Analysis with Python Day 10

《Python数据分析基础》封面

学习完可视化之后,我们进入描述性统计的部分,得到一个数据集后,一般我们会通过简单的描述性统计和可视化进行探索性分析,再用一些经典算法进一步分析,或者在经典算法的基础上建模分析。书中通过两个例子来介绍这一过程,这篇笔记跟着课本的做法训练描述性统计与建模能力。

目录

葡萄酒数据探索与建模

葡萄酒质量数据集

葡萄酒质量数据集包括两个文件,一个是红葡萄酒数据文件,另一个是白葡萄酒数据文件,白葡萄酒是著名的葡萄牙“Vinho Verde”葡萄酒的一个变种。红葡萄酒文件中包含1599 条记录,白葡萄酒文件中包含 4898 条记录。两个文件中都有 1 个输出变量和 11 个输入变量。输出变量是酒的质量,是一个从 0(低质量)到 10(高质量)的评分。输入变量是葡萄酒的物理化学成分和特性,包括非挥发性酸、挥发性酸、柠檬酸、残余糖分、氯化物、游离二氧化硫、总二氧化硫、密度、pH 值、硫酸盐和酒精含量。原始数据可从UCI.EDU获取,我们不对这两个数据集分别进行分析,而是将它们合成了一个数据集。当你将红葡萄酒数据和白葡萄酒数据合成一个文件后,结果数据集中应该包括一个标题行和 6497 条记录。另外,还应该再添加一列,用来区分这行数据是红葡萄酒还是白葡萄酒的数据。这个文件可以从原书作者GitHub获取。将文件命名为winequality.csv 。
下面进行这个数据的描述性统计。

描述性统计

计算和显示基本统计量

import numpy as np
import pandas as pd

#引入需要的库,除了statsmodels外都是我们学过的库。

# 读入数据集
wineDF = pd.read_csv('./readingForDS/winequality.csv', sep=',', header=0)
wineDF.columns = wineDF.columns.str.replace(' ', '_')

print(wineDF.describe())  #describe()是很实用的函数,输出基本统计量。
#包括总数、均值、标准差、最小值、中位数、最大值等

print(wineDF.quality.value_counts()) # 计算值的频率 

输出(有所精简):

       fixed_acidity  volatile_acidity  citric_acid  residual_sugar  \
count    6497.000000       6497.000000  6497.000000     6497.000000   
mean        7.215307          0.339666     0.318633        5.443235   
std         1.296434          0.164636     0.145318        4.757804   
min         3.800000          0.080000     0.000000        0.600000   
50%         7.000000          0.290000     0.310000        3.000000   
75%         7.700000          0.400000     0.390000        8.100000   
max        15.900000          1.580000     1.660000       65.800000   

         chlorides  free_sulfur_dioxide  total_sulfur_dioxide      density  \
count  6497.000000          6497.000000           6497.000000  6497.000000   
mean      0.056034            30.525319            115.744574     0.994697   
std       0.035034            17.749400             56.521855     0.002999   
min       0.009000             1.000000              6.000000     0.987110   
50%       0.047000            29.000000            118.000000     0.994890   
75%       0.065000            41.000000            156.000000     0.996990   
max       0.611000           289.000000            440.000000     1.038980   

                pH    sulphates      alcohol      quality  
count  6497.000000  6497.000000  6497.000000  6497.000000  
mean      3.218501     0.531268    10.491801     5.818378  
std       0.160787     0.148806     1.192712     0.873255  
min       2.720000     0.220000     8.000000     3.000000  
50%       3.210000     0.510000    10.300000     6.000000  
75%       3.320000     0.600000    11.300000     6.000000  
max       4.010000     2.000000    14.900000     9.000000  
6    2836
5    2138
7    1079
4     216
8     193
3      30
9       5
Name: quality, dtype: int64

前面计算出的统计量是针对整个数据集的,既包括红葡萄酒数据也包括白葡萄酒数据。下面我们分别分析红葡萄酒数据和白葡萄酒数据,看看统计量是否会保持不变:

用 seaborn 创建一幅统计图,其中有两个直方图,一个表示红葡萄酒,另一个
表示白葡萄酒


import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm

%matplotlib inline  
plt.style.use('ggplot')

# 按照葡萄酒类型显示质量的描述性统计量 
print(wineDF.groupby('type')[['quality']].describe().unstack('type')) 
# 按照葡萄酒类型显示质量的特定分位数值 
print(wineDF.groupby('type')[['quality']].quantile([0.25, 0.75]).unstack('type')) 
# 按照葡萄酒类型查看质量分布 
red_wine = wineDF.loc[wineDF['type']=='red', 'quality'] 
white_wine = wineDF.loc[wineDF['type']=='white', 'quality'] 
sns.set_style("dark") 
print(sns.distplot(red_wine, norm_hist=True, kde=False, color="red", label="Red wine")) 
print(sns.distplot(white_wine,norm_hist=True, kde=False, color="white", label="White wine")) 

plt.title("Distribution of Quality by Wine Type") 
plt.legend() 
# 检验红葡萄酒和白葡萄酒的平均质量是否有所不同 
print(wineDF.groupby(['type'])[['quality']].agg(['std'])) 
tstat, pvalue, df = sm.stats.ttest_ind(red_wine, white_wine) 
print('tstat:',tstat,';pvalue: ' ,pvalue)

输出:

     quality      
type     red white
0.25     5.0   5.0
0.75     6.0   6.0
Axes(0.125,0.125;0.775x0.755)
Axes(0.125,0.125;0.775x0.755)
        quality
            std
type           
red    0.807569
white  0.885639
tstat: -9.68564955419 ;pvalue:  4.8880690442e-22
红/白葡萄酒质量分布

上面的直方图中,红条表示红葡萄酒,白条表示白葡萄酒。因为白葡萄酒数据比红葡萄酒多,所以图中显示密度分布,不显示频率分布。从这个统计图可以看出,两种葡萄酒的评分都近似正态分布。与原始数据的摘要统计量相比,直方图更容易看出两种葡萄酒的质量评分的分布。

前面已经检查了输出变量,下面简单研究一下输入变量。让我们计算一下输入变量两两之间的相关性,并为一些输入变量创建带有回归直线的散点图:

import statsmodels.formula.api as smf
from statsmodels.formula.api import ols, glm

print(wineDF.corr())  #corr 函数可以计算出数据集中所有变量两两之间的线性相关性
wine=wineDF
# 从红葡萄酒和白葡萄酒的数据中取出一个 “小” 样本来进行绘图 
def take_sample(data_frame, replace=False, n=200): 
    return data_frame.loc[np.random.choice(data_frame.index,replace=replace, size=n)] 
reds_sample = take_sample(wine.loc[wine['type']=='red', :]) 
whites_sample = take_sample(wine.loc[wine['type']=='white', :]) 
wine_sample = pd.concat([reds_sample, whites_sample]) 
wine['in_sample'] = np.where(wine.index.isin(wine_sample.index), 1.,0.) 
print(pd.crosstab(wine.in_sample, wine.type, margins=True)) 
# 查看成对变量之间的关系 
sns.set_style("dark") 
g = sns.pairplot(wine_sample, kind='reg', plot_kws={"ci": False,"x_jitter": 0.25, "y_jitter": 0.25}, hue='type', diag_kind='hist', 
diag_kws={"bins": 10, "alpha": 1.0}, palette=dict(red="red", white="white"),markers=["o", "s"], vars=['quality', 'alcohol', 'residual_sugar']) 
print(g) 
plt.suptitle('Histograms and Scatter Plots of Quality, Alcohol, and Residual Sugar', fontsize=14, horizontalalignment='center', verticalalignment='top',x=0.5, y=0.999)
plt.show()
红/白葡萄酒分布

seaborn库的pairplot 函数可以创建一个统计图矩阵。主对角线上的图以直方图或密度图的形式显示了每个变量的单变量分布,对角线之外的图以散点图的形式显示了每两个变量之间的双变量分布,散点图中可以有回归直线,也可以没有。
上面画出的统计图显示了葡萄酒质量、酒精含量和残余糖分之间的关系。红条和红点表示红葡萄酒,白条和白点表示白葡萄酒。因为质量评分都是整数,所以我加上了一点振动,这样更容易看出数据在何处集中。

葡萄酒质量预测

当我们有一个新的葡萄酒成分的记录时,通过预测算法可以根据这些成分预测这种葡萄酒的质量评分。

# 使用葡萄酒数据集中的前10个观测创建10个 “新” 观测 
# 新观测中只包含模型中使用的自变量 
independent_variables = wine[wine.columns.difference(['quality', 'type','in_sample'])]

new_observations = wine.loc[wine.index.isin(range(10)),independent_variables.columns] 
# 基于新观测中的葡萄酒特性预测质量评分 
my_formula = 'quality ~ alcohol + chlorides + citric_acid + density + fixed_acidity + free_sulfur_dioxide + pH + residual_sugar + sulphates + total_sulfur_dioxide + volatile_acidity' 
 
lm = ols(my_formula, data=wine).fit() 
y_predicted = lm.predict(new_observations) 
# 将预测值保留两位小数输出
y_predicted_rounded = [round(score, 2) for score in y_predicted] 
print(y_predicted_rounded)

# out: 
#[5.0, 4.9199999999999999, 5.0300000000000002, 5.6799999999999997, 5.0, 5.04, 5.0199999999999996, 5.2999999999999998, 5.2400000000000002, 5.6900000000000004]

客户流失数据统计

客户流失数据集

客户流失数据集是一个包含 3333 条记录的文件,其中的观测是电信公司现有的和曾经的客户。这个文件有 1 个输出变量和 20 个输入变量。输出变量 Churn是一个布尔型变量,表示在数据收集的时候,客户是否已经流失(是否还是电信公司的客户) 。输入变量是客户的电话计划和通话行为的特征,包括状态、账户时间、区号、电话号码、是否有国际通话计划、是否有语音信箱、语音信箱消息数量、白天通话时长、白天通话次数、白天通话费用、傍晚通话时长、傍晚通话次数、傍晚通话费用、夜间通话时长、夜间通话次数、夜间通话费用、国际通话时长、国际通话次数、国际通话费用和客户服务通话次数。
这个数据集可以从Churn下载。

简单的描述性统计:

import numpy as np 
import pandas as pd 

churn = pd.read_csv('./readingForDS/churn.csv', sep=',', header=0) 
churn.columns = [heading.lower() for heading in churn.columns.str.replace(' ', '_').str.replace("\'", "").str.strip('?')] 
churn['churn01'] = np.where(churn['churn'] == 'True.', 1., 0.) 
print(churn.describe())

逻辑斯蒂回归

逻辑斯蒂回归的语法与线性回归有一点区别。对于逻辑斯蒂回归,需要分别设置因变量和自变量.

import seaborn as sns 
import matplotlib.pyplot as plt 
import statsmodels.api as sm 
import statsmodels.formula.api as smf 

churn['total_charges'] = churn['day_charge'] +churn['eve_charge'] +churn['night_charge'] + churn['intl_charge'] 
factor_cut = pd.cut(churn.total_charges, 5, precision=2) 

grouped = churn.custserv_calls.groupby(factor_cut) 
dependent_variable = churn['churn01'] 
independent_variables = churn[['account_length', 'custserv_calls','total_charges']] 
independent_variables_with_constant = sm.add_constant(independent_variables,prepend=True) 
 
logit_model = sm.Logit(dependent_variable, independent_variables_with_constant).fit() 
 
print(logit_model.summary()) 
print("\nQuantities you can extract from the result:\n%s" % dir(logit_model)) 
print("\nCoefficients:\n%s" % logit_model.params) 
print("\nCoefficient Std Errors:\n%s" % logit_model.bse)

输出:

Optimization terminated successfully.
         Current function value: 0.363480
         Iterations 7
                           Logit Regression Results                           
==============================================================================
Dep. Variable:                churn01   No. Observations:                 3333
Model:                          Logit   Df Residuals:                     3329
Method:                           MLE   Df Model:                            3
Date:                Thu, 22 Mar 2018   Pseudo R-squ.:                  0.1216
Time:                        21:39:06   Log-Likelihood:                -1211.5
converged:                       True   LL-Null:                       -1379.1
                                        LLR p-value:                 2.234e-72
==================================================================================
                     coef    std err          z      P>|z|      [0.025      0.975]
----------------------------------------------------------------------------------
const             -7.2205      0.394    -18.309      0.000      -7.993      -6.448
account_length     0.0012      0.001      0.927      0.354      -0.001       0.004
custserv_calls     0.4443      0.037     12.129      0.000       0.373       0.516
total_charges      0.0729      0.005     13.448      0.000       0.062       0.084
==================================================================================

Coefficients:
const            -7.220520
account_length    0.001222
custserv_calls    0.444323
total_charges     0.072914
dtype: float64

Coefficient Std Errors:
const             0.394363
account_length    0.001317
custserv_calls    0.036633
total_charges     0.005422
dtype: float64

客户流失情况预测

与前面的葡萄酒质量预测一样,我们也可以使用拟合模型来对“新”输入的数据进行预测。

# 在churn数据集中 
# 使用前10个观测创建10个 “新” 观测 
new_observations = churn.loc[churn.index.isin(range(10)),independent_variables.columns] 
new_observations_with_constant = sm.add_constant(new_observations, prepend=True) 
 
# 基于新观测的账户特性 
# 预测客户流失可能性 
y_predicted = logit_model.predict(new_observations_with_constant) 
 
# 将预测结果保留两位小数并打印到屏幕上 
y_predicted_rounded = [round(score, 2) for score in y_predicted] 
print(y_predicted_rounded)

输出:

[0.25, 0.089999999999999997, 0.080000000000000002, 0.20000000000000001, 0.12, 0.10000000000000001, 0.48999999999999999, 0.029999999999999999, 0.22, 0.23999999999999999]

《Python数据分析基础》在第7章用了两个例子演示了描述性统计和建模的知识,有些代码还是有些难以理解的,可以通过其他资料进行深入理解。下一篇笔记是关于按计划自动运行脚本的,可以在电脑里设置代码每天自动运行,下一章可以使用之前写的代码,基本不需要再写代码了。

本篇笔记的GitHub同步项目于readingForDS。关于本系列笔记有任何建议欢迎留言讨论。

上一篇下一篇

猜你喜欢

热点阅读