【Python】【數據分析】葡萄酒質量評價


摘要

本例為演示數據分析的流程和對概率論和數理統計基礎知識的應用,使用Python的pandas和statmodels生成標准的描述性統計量和模型,對數據集進行探索和摘要分析,並利用多元線性回歸進行回歸分析。

本例以葡萄酒類型為標簽,分為白葡萄酒和紅葡萄酒。比較這兩種葡萄酒的差別並選取葡萄酒的化學成分:固定酸度、揮發性酸度、檸檬酸、氯化物、游離二氧化硫、總硫度、密度、PH值、硫酸鹽、酒精度數共11個,針對酒的各類化學成分建立線性回歸模型,從而預測該葡萄酒的質量評分。

數據收集

數據集來源:UCI Machine Learning Repository

winequality-red.csv

winequality-white.csv

本實驗應用UCI機器學習數據庫中的紅葡萄酒和白葡萄酒數據文件,將其合成一個數據集。

winequality-both.csv

數據預處理

首先進行數據預處理和數據描述性統計,其中描述性統計量包括總數、均值、標准差、最小值、第25個百分位數、中位數、第75個百分位數和最大值。

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.formula.api import ols,glm
#將數據集讀入到pandas數據框中
wine=pd.read_csv('winequality-both.csv',sep=',',header=0)
#列名重命名,用下划線替換空格,使之符合python命名規范
wine.columns=wine.columns.str.replace(' ','_')
print(wine.head())
#顯示所有變量的描述性統計量
#這些統計量包括總數、均值、標准差、最小值、第25個百分位數、中位數、第75個百分位數和最大值
print(wine.describe())
#找出唯一值
print(sorted(wine.quality.unique()))
#計算值的頻率
print(wine.quality.value_counts())


通過觀察知,沒有缺失值和異常值,不需進行補充和處理。

數據分析

分組、直方圖與t檢驗

繪制直方圖

在數據預處理步驟中,計算出的描述性統計量是針對紅葡萄酒和白葡萄酒兩個數據集。接下來我們針對兩個數據集分別分析,查看二者的質量分布。

#按照葡萄酒類型顯示質量的描述性統計量
print(wine.groupby('type')[['quality']].describe().unstack('type'))
#按照葡萄酒類型顯示質量的特定分位數值
print(wine.groupby('type')[['quality']].quantile([0.25,0.75]).unstack('type'))
#按葡萄酒類型查看質量分布
red_wine=wine.loc[wine['type']=='red','quality']
white_wine=wine.loc[wine['type']=='white','quality']
#使用seaborn和matplotlib繪圖
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.xlabel("Quality Score")
plt.ylabel("Density")
plt.title("Distribution of Quality by Wine Type")
plt.legend()
plt.show()

從統計圖中可以看出,兩種葡萄酒的評分都近似正態分布。

t檢驗

為檢驗紅葡萄酒和白葡萄酒質量是否不同,此處用到數理統計中的假設檢驗方法,此處使用t檢驗判斷紅葡萄酒和白葡萄酒的平均評分是否有區別。由於我們想知道紅葡萄酒和白葡萄酒評分的標准差是否相同,所以在t檢驗中可使用合並方差。

原假設:紅白兩種葡萄酒質量的均值相同。

#檢驗紅葡萄酒和白葡萄酒質量是否有所不同
print(wine.groupby(['type'])[['quality']].agg(['std']))
#按葡萄酒類型分組,計算質量的標准差和均值
tstat,pvalue,df=sm.stats.ttest_ind(red_wine,white_wine)
#分別返回t值和p值
print('tstat: %.3f pvalue: %.4f' % (tstat,pvalue))

從檢驗的結果來看,p值<0.0005。根據實際推斷原理,拒絕原假設,即認為紅白兩種葡萄酒質量有顯著性差異,並且從均值上來看白葡萄酒的平均質量等級在統計意義上大於紅葡萄酒的平均質量等級。

成對變量之間的關系和相關性

接下來我們研究一下變量之間的相關性,並創建部分變量之間帶有回歸直線的散點圖。

數據集中有6000多個點,如果將它們都畫在統計圖中,就很難分辨出清楚的點。因此我們使用take_sample函數進行抽樣。

#計算所有變量的相關矩陣
print(wine.corr())
#從紅葡萄酒和白葡萄酒的數據中取出一個“小”樣本進行繪圖
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,horizontalaligment='center',verticalaligment='top',\
            x=0.5,y=0.999)
plt.show()

從各變量的相關系數來看酒精含量、硫酸酯、pH 值、游離二氧化硫和檸檬酸這些指標與質量呈現正相關,即當這些指標的含量增加時,葡萄酒的質量會提高;非揮發性酸、揮發性酸、殘余糖分、氯化物、總二氧化硫和密度這些指標與質量呈負相關即當這些指標的含量增加時,葡萄酒的質量會降低。從相關系數可以看出,對葡萄酒質量影響最大的是葡萄酒是酒精含量,其相關系數為0.444,其次是酒的密度,但酒的密度對酒的質量是負影響的。

使用最小二乘估計進行線性回歸

系數解釋

相關系數和兩兩變量之間的統計圖有助於對兩個變量之間的關系進行量化和可視化。但它們不能測量出每個自變量在其他自變量不變時與因變量之間的關系,線性回歸可以解決這個問題。

線性回歸模型如下:

對i=1,2,…,n個觀測和p個自變量。

這個模型表示觀測yi服從均值為μi方差為σ2的正態分布,其中μi依賴於自變量,σ2為一個常數。也就是說,給定了自變量的值以后,我們就可以得到一個具體的質量評分,但在另一天,給定同樣的自變量值,我們可能會得到一個與前面不同的質量評分。但經過一個較長的周期,質量評分會落在μ±σ這個范圍內。

下面我們使用statmodel包進行線性回歸。

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()
print(lm.summary())
print("\nQuantities you can extract from the result:\n%s"%dir(lm))
print("\nCoefficients:\n%s"%lm.params)
print("\nCoefficient Std Errors:\n%s"%lm.bse)
print("\nAdj.R-squared\n%.2f"%lm.rsquared_adj)
print("\nF-statistic:%.1f Pvalue:%.2f"%(lm.fvalue,lm.f_pvalue))
print("\nNumber of obs:%d Number of fitted values:%d"%(lm.nobs,\
                                                      len(lm.fittedvalues)))

在這個模型中,某個自變量系數的意義是:在其他自變量保持不變的情況下,這個自變量發生一個單位的變化時,導致葡萄酒質量評分發生的平均變化。

自變量標准化

關於這個模型,還需要注意的一點是,普通最小二乘回歸是通過使殘差平方和最小化來估計未知的β參數值。由於殘差大小依賴於自變量的測量單位。所以當自變量測量單位不同,我們需要將自變量標准化。

由上一步的觀測數據知,各變量間最大值和最小值之間差別很大,因此應進行標准化。

pandas在數據框中對變量進行標准化非常容易。你可以對一個觀測寫一個變換公式,pandas將其擴展到行和列中,來標准化所有變量。

#創建一個名為dependent_variable的序列來保存質量數據
dependent_variable=wine['quality']
#創建一個名為independent_variables的數據框
independent_variables=wine[wine.columns.difference(['quality','type',\
                                                   'in_sample'])]
#對自變量進行標准化,減去均值、除以標准差
independent_variables_standardized=(independent_variables -\
                                   independent_variables.mean())/independent_variables.std()
#將因變量quality作為一列添加到自變量數據框
#創建一個帶有標准化自變量的新數據集
wine_standardized=pd.concat([dependent_variable,independent_variables_standardized],axis=1)
#重新進行線性回歸
lm_standardized=ols(my_formula,data=wine_standardized).fit()
print(lm_standardized.summary())

圖片

觀測數據知,線性回歸模型為:quality= 0.0877fixed acidity -0.2186volatile acidity -0.0159citric_acid+ 0.2072residual_sugar-0.0169chlorides+ 0.1060free_sulfur_dioxide -0.1648density-0.1402total_sulfur_dioxide+0.0706pH+0.1143sulphates+ 0.3185*alcohol+5.8184

在我們的模型摘要中,截距系數的意義就是當一種葡萄酒的所有成分都取均值時,它的質量評分均值應該是5.8,標准差為0.009。

預測

有了線性回歸模型,當給出了葡萄酒的化學成分的數據就可以預測該葡萄酒的質量評分。

在某些情況下,我們需要使用沒有用來擬合模型的新數據進行預測。例如,你會收到關於葡萄酒成分的一個新的觀測,並需要根據這些成分預測這種葡萄酒的質量評分。讓我們通過選擇現有數據集的前10個觀測,根據它們的成分進行評分。

#使用葡萄酒數據集中的前10個觀測創建10個“新”觀測
#新觀測只包含模型中是用的自變量
new_observations=wine.ix[wine.index.isin(range(10)),\
                        independent_variables.columns]
#基於新觀測中的葡萄酒特性預測質量評分
y_predicted=lm.predict(new_observations)
#將預測值保留2位小數
y_predicted_rounded=[round(score,2) for score in y_predicted]
print(y_predicted_rounded)

result:

[5.0, 4.92, 5.03, 5.68, 5.0, 5.04, 5.02, 5.3, 5.24, 5.69]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM