探索變量之間的關係(python3)

在做數據分析的過程中。我們往往是–理解需求–獲取數據–清洗數據–簡單描述統計–統計型分析報告;
其實到這裏還沒完。如果我們還需要深入探索數據的價值,那麼,單變量的分佈檢驗–探索變量間的關係–建立關係模型–評估–總結等。
接下來就來看看數據分析的其中重要的一環–探索變量間的關係。

探索變量之間的關係

探索數據變量之間是否存在某種關係/關聯。大致步驟有:

  • 變量的類型:類別型/數值型
  • 可視化給出可能的方向:散點圖、箱型圖、直方圖、…
  • 需建立更嚴格的分析方式:假設檢驗。假設變量間存在某種函數/邏輯等關聯關係,進行檢驗。

一、準備工具和數據

1.1、工具:我們用python3

通常我們把用於做數據分析的幾個庫直接先導入,基本是固定導入使用。

import numpy as np               #科學計算基礎庫,多維數組對象ndarray
import pandas as pd              #數據處理庫,DataFrame(二維數組)
import matplotlib as mpl         #畫圖基礎庫
import matplotlib.pyplot as plt  #最常用的繪圖庫
from scipy import stats          #scipy庫的stats模塊

mpl.rcParams["font.family"]="SimHei"  #使用支持的黑體中文字體
mpl.rcParams["axes.unicode_minus"]=False # 用來正常顯示負號  "-"
plt.rcParams['font.sans-serif']=['SimHei'] # 用來正常顯示中文標籤
# % matplotlib inline  #jupyter中用於直接嵌入圖表,不用plt.show()
import warnings
warnings.filterwarnings("ignore") #用於排除警告
 
#用於顯示使用庫的版本
print("numpy_" + np.__version__)
print("pandas_" + pd.__version__)
print("matplotlib_"+ mpl.__version__)
numpy_1.17.4
pandas_0.23.4
matplotlib_2.2.3

1.2、案例數據

某餐廳顧客消費記錄數據作爲主要的案例數據。

數據源:https://download.csdn.net/download/weixin_41685388/12144418

'''
某餐廳顧客消費記錄.
解釋數據結構:
total_bill:消費,tip:小費,sex:服務員性別,
smoker:是否抽菸,day:星期幾,time:午餐/晚餐,size:本桌人數
'''
tips = pd.read_csv(r"E:\tips.txt",sep='\t',encoding='utf-8') #導入txt格式數據
display(tips.shape)  #樣本量
display(tips.sample(5))  #隨機抽樣5行
(244, 7)
total_bill tip sex smoker day time size
96 27.28 4.00 Male Yes Fri Dinner 2
230 24.01 2.00 Male Yes Sat Dinner 4
17 16.29 3.71 Male No Sun Dinner 3
110 14.00 3.00 Male No Sat Dinner 2
235 10.07 1.25 Male No Sat Dinner 2

二、數據變量與變量間的關係

2.1、類別型數據 ~ 類別型數據間的獨立性檢驗

在這裏插入圖片描述
在這裏插入圖片描述
通用:用卡方檢驗

小樣本:用費舍爾檢驗(劣勢:只能檢驗2*2)

  • 問題1:探索案例數據中服務員性別與星期幾的關係?

卡方檢驗

'''①看變量的類型:類別型/數值型'''
display(tips.sample(3))  #隨機抽樣3行

statistics = tips[["sex","day"]].describe() #統計
display(statistics)

#兩個變量均是類別型數據,統計往往是進行分類彙總,即需要生成交叉表,用pd.crosstab()
count=pd.crosstab(tips.sex, tips.day)  
display(count)
total_bill tip sex smoker day time size
116 29.93 5.07 Male No Sun Dinner 4
146 18.64 1.36 Female No Thur Lunch 3
169 10.63 2.00 Female Yes Sat Dinner 2
sex day
count 244 244
unique 2 4
top Male Sat
freq 157 87
day Fri Sat Sun Thur
sex
Female 9 28 18 32
Male 10 59 58 30
'''②可視化給出可能的方向'''
count.T.plot(kind='bar')
plt.show()

在這裏插入圖片描述

count=pd.crosstab(tips.sex, tips.day)  #構造交叉表
print(stats.chi2_contingency(count,correction=False))
#chi2 卡方檢驗   contingency列聯表  列聯表中每個格子數量至少爲5
#對性別和星期幾進行卡方檢驗
chi2, p, dof, ex = stats.chi2_contingency(count, correction=False)  #卡方檢驗,p值很小,AB有關
print(p)
#P值很小,拒絕原假設,說明性別與星期幾有關係
#獨立性檢驗中,H0:AB無關,H1:AB有關係
(13.22200137240661, 0.004180302092822257, 3, array([[ 6.77459016, 31.0204918 , 27.09836066, 22.10655738],
       [12.22540984, 55.9795082 , 48.90163934, 39.89344262]]))
0.004180302092822257
  • 問題2:探索服務員性別與顧客是否吸菸是否有關?

費舍爾精確檢驗(小樣本)

count=pd.crosstab(tips.sex,tips.smoker)  
print(count)

oddsratio,pvalue=stats.fisher_exact(count)  #費舍爾精確檢驗
print(oddsratio,pvalue)
#P值很大,不能拒絕H0,是否吸菸和男女沒有關係
smoker  No  Yes
sex            
Female  54   33
Male    97   60
1.0121836925960637 1.0
#如果修改一下列聯表中數據
count.iat[0,0]=2  #手動將交叉表中的[0,0]位置的元素修改爲2
print(count)
oddsratio,pvalue=stats.fisher_exact(count)  ##費舍爾精確檢驗
print(oddsratio,pvalue)
#0.03748828491096532 3.9900059898475383e-10
#P值很小,拒絕H0,吸菸和男女有關係
#fisher精確檢驗的優勢:每個表格中數據不一定大於五
#  費舍爾精確檢驗劣勢:只能檢驗2*2

chi2, p, dof, ex = stats.chi2_contingency(count, correction=False)  #卡方檢驗
print(p)
#卡方檢驗結果:P值很小,拒絕H0,吸菸和男女有關係
smoker  No  Yes
sex            
Female   2   33
Male    97   60
0.03748828491096532 3.9900059898475383e-10
1.9484526423911992e-09

2.數值型~數值型間獨立性檢驗

  • pearson:積差相關係數,反應兩個變量之間的線性相關性
    在這裏插入圖片描述
    在這裏插入圖片描述

  • spearman:等級相關係數(Ranked data)—常用
    在這裏插入圖片描述
    spearman相關係數:先對所有變量進行排序,在做線性相關。與pearson不同,不假設變量爲正態分佈

  • Kendall’s Tau:非參數等級相關係數

    tau=(P-Q)/sqrt((P+Q+T)*(P+Q+U))

    P:同步數據對數,Q:異步,T:tie in x,U:tie in y

區別及選用

  • pearson和spearman區別:

    如果有線性模式,也有一些離散點,spearman線性相關係數要大一些,因爲離散點破壞了線性相關性,但是對rank排序影響不太大

    pearson只能處理兩組數據,spearman可以處理多組序列

  • 如何選擇:

    Kendall’s tau-b(肯德爾)等級相關係數:用於反映分類變量相關性的指標,適用於兩個分類變量均爲有序分類的情況。對相關的有序變量進行非參數相關檢驗;取值範圍在-1-1之間,此檢驗適合於正方形表格;

    計算積距pearson相關係數,連續性變量纔可採用;計算Spearman秩相關係數,適合於定序變量或不滿足正態分佈假設的等間隔數據; 計算Kendall秩相關係數,適合於定序變量或不滿足正態分佈假設的等間隔數據。

    計算相關係數:當資料不服從雙變量正態分佈或總體分佈未知,或原始數據用等級表示時,宜用 spearman或kendall相關。

    總結:在大多數情況下選用spearman檢驗即可

'''可視化給出可能的方向'''
plt.scatter(tips.total_bill,tips.tip)
plt.title("total_bill與tip散點圖")
plt.xlabel("total_bill") 
plt.ylabel("tip") 
plt.show()

在這裏插入圖片描述

#pearson就是統計學中學過的相關係數
print(stats.pearsonr(tips.total_bill,tips.tip))
#線性相關度和P值
#相關係數=0.6757341092113643,p=6.692470646864041e-34
#p<0.01,拒絕原假設,存在相關性
(0.6757341092113643, 6.692470646864041e-34)
# spearman:等級相關係數(Ranked data)
rho,pval=stats.spearmanr(tips.total_bill,tips.tip)
print(rho,pval)
#p<0.01,拒絕原假設,兩變量存在相關性
0.6789681219001009 2.501158440923619e-34
#多組數據的spearmanr獨立性檢驗
x2n=np.random.randn(100,2)
y2n=np.random.randn(100,2)
rho,pval=stats.spearmanr(x2n,y2n)
print(rho)
print(pval)
print("\n")
rho,pval=stats.spearmanr(x2n.T,y2n.T,axis=1)
print(rho)
print(pval)
[[ 1.          0.04819682  0.22357036 -0.0589619 ]
 [ 0.04819682  1.          0.02417042 -0.09821782]
 [ 0.22357036  0.02417042  1.         -0.05353735]
 [-0.0589619  -0.09821782 -0.05353735  1.        ]]
[[0.         0.63394219 0.02535319 0.56008632]
 [0.63394219 0.         0.81133805 0.33095957]
 [0.02535319 0.81133805 0.         0.59679005]
 [0.56008632 0.33095957 0.59679005 0.        ]]


[[ 1.          0.04819682  0.22357036 -0.0589619 ]
 [ 0.04819682  1.          0.02417042 -0.09821782]
 [ 0.22357036  0.02417042  1.         -0.05353735]
 [-0.0589619  -0.09821782 -0.05353735  1.        ]]
[[0.         0.63394219 0.02535319 0.56008632]
 [0.63394219 0.         0.81133805 0.33095957]
 [0.02535319 0.81133805 0.         0.59679005]
 [0.56008632 0.33095957 0.59679005 0.        ]]
#Kendall's Tau:非參數等級相關係數
x=[1, 2, 3, 4, 5, 5, 4, 6,-1]
y=[3, 4, 3, 4, 5, 5, 3, 7, 7]
'''
tau=(P-Q)/sqrt((P+Q+T)*(P+Q+U))
P:同步數據對數,Q:異步,T:tie in x,U:tie in y
x中1-2增加,y中3-4增加,即爲同步P
x中2-3增加,y中4-3減少,即爲異步Q
x中兩個數相等,但y中不相等,即爲T
y中兩個數相等,但x中不相等,即爲U
'''
plt.scatter(x,y)
plt.title("x與y散點圖")
plt.xlabel("x") 
plt.ylabel("y") 
plt.show()

tau, p_value = stats.kendalltau(x,y)#Kendall's Tau:非參數等級相關係數
print(tau, p_value) #p>0.05,接受原假設,不相關

rho,pval=stats.spearmanr(x,y) #用spearmanr獨立性檢驗
print(rho,pval) #p>0.05,接受原假設,不相關

在這裏插入圖片描述
0.3444233600968322 0.22913623766848912
0.3247514077354534 0.3938410708377398

3.數值型~類別型(自變量類別型,因變量數值型)

  • 服務員男女性別中顧客給小費是否不同?

t檢驗:比較兩個樣本(比較兩組均值)

stats.ttest_ind(rvs1,rvs2) # 對兩個樣本進行t檢驗

#結果分析:原假設兩樣本無差異,當p值越小時越拒絕
rvs1 = stats.norm.rvs(loc=5, scale=10, size=500)
rvs2 = stats.norm.rvs(loc=5, scale=10, size=500)
print(stats.ttest_ind(rvs1, rvs2))
#p值較大,接受原假設,兩個樣本的均值無明顯差異
Ttest_indResult(statistic=-0.7847691950148168, pvalue=0.4327751444523158)
rvs1=tips[tips['sex']=='Male']['tip']
print(rvs1.mean())
rvs2=tips[tips['sex']=='Female']['tip']
print(rvs2.mean())
print(stats.ttest_ind(rvs1, rvs2))  
#P值較大,不能拒絕原假設:男女性別與小費的多少無差異
3.0896178343949052
2.833448275862069
Ttest_indResult(statistic=1.3878597054212687, pvalue=0.16645623503456763)
#如果同一個樣本重複抽樣,stats.ttest_rel()需要用這個檢驗,但必須保證兩組數據長度相等
print(stats.ttest_rel(rvs1[:87],rvs2))
#Ttest_relResult(statistic=1.3639526706337008, pvalue=0.1761417001637746)
#t檢驗比較的是兩組數的點估計和理想值得比較
Ttest_relResult(statistic=1.3639526706337008, pvalue=0.1761417001637746)

Kolmogorov-Smirnov 雙樣本檢測 ks_2samp(比較兩組分佈)

stats.ks_2samp(rvs1, rvs2) #判斷兩樣本分佈是否有差異

#檢查兩樣本分佈之間是否存在差異,原假設兩樣本之間不存在差異
rvs1=tips[tips['sex']=='Male']['tip']
rvs2=tips[tips['sex']=='Female']['tip']
print(stats.ks_2samp(rvs1, rvs2)) 
#p值較大,接受原假設,兩樣本的分佈不存在差異

#畫圖檢驗一下,加上total_bill作爲x軸,tip作爲y軸
plt.title("total_bill與tip關係圖")
plt.xlabel('total_bill')
plt.ylabel('tip')
plt.plot(tips[tips['sex']=='Male']['total_bill'],tips[tips['sex']=='Male']['tip'],'bo',label='Male')
plt.plot(tips[tips['sex']=='Female']['total_bill'],tips[tips['sex']=='Female']['tip'],'go',label='Female')
plt.legend(["Male","Female"],loc="best", frameon=True, title=" sex", ncol=1)
plt.show()
Ks_2sampResult(statistic=0.0797276520975182, pvalue=0.8545295823550555)

在這裏插入圖片描述

#進一步探索,費率,在國外餐廳費率即指小費/消費
rvs1=tips[tips['sex']=='Male']['tip']/tips[tips["sex"]=='Male']['total_bill']
rvs2=tips[tips['sex']=='Female']['tip']/tips[tips["sex"]=='Female']['total_bill']

fig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, 4))

ax0.set_title('Male')
ax0.set_xlabel("tip/total_bill")
ax0.set_ylabel("數量")
ax0.hist(rvs1, bins=50, facecolor='g', alpha=0.8)

ax1.set_title('Female')
ax1.set_xlabel("tip/total_bill")
ax1.set_ylabel("數量")
ax1.hist(rvs2, bins=50, rwidth=0.8)

#fig.tight_layout()
plt.show()

#從兩個直方圖上看有些分佈相似,但需要進一步探索

#看一下均值和標準差
print('Male:',rvs1.mean(),rvs1.std())
print('Female:',rvs2.mean(),rvs2.std())

#t檢驗(均值是否有明顯不同,原假設是均值基本一樣無差異)
print(stats.ttest_ind(rvs1, rvs2))  
#P值較大,不能拒絕原假設:男女性別對費率的影響無差異

#正態分佈檢驗
print(stats.normaltest(rvs1)) #結果拒絕
print(stats.normaltest(rvs2)) #結果拒絕

print(stats.ks_2samp(rvs1, rvs2)) #判斷兩樣的分佈是否存在差異
# p=0.08440693699139794,可以說是接受原假設,具有相同的分佈,但是正態分佈檢驗拒絕了,所以還可以做更多的探索
# 由於p值相對較小,也可以說拒絕原假設,不具有相同的分佈,p值的大小需要根據實際業務邏輯進行設定
# 最常見的p值設置是0.01,0.05,0.1三個閥值
# ANOVA方差分析、ANCOVA協方差分析、MANOVA多因素方差分析等方法做更多的探索

在這裏插入圖片描述

Male: 0.15765054700429748 0.06477787270951386
Female: 0.16649073632892475 0.0536317262299475
Ttest_indResult(statistic=-1.0833972270477996, pvalue=0.2797103849605489)
NormaltestResult(statistic=174.74433683510114, pvalue=1.1343560308586256e-38)
NormaltestResult(statistic=36.21379581439844, pvalue=1.368592496283602e-08)
Ks_2sampResult(statistic=0.1651658247309466, pvalue=0.08440693699139794)

單因素ANOVA方差分析

原假設H0:所有組的均數相同
方差分析檢驗對數據的假設條件:
    1. 樣本之間相互獨立
    2. 樣本均來自正態分佈
    3. 方差齊次性:各組方差相等
對誤差平方和,因素平方和進行F檢驗。如果F檢驗爲1左右,認爲不能拒絕原假設
print(stats.f_oneway(rvs1,rvs2))
#接着上面構造的數據
rvs1=tips[tips['sex']=='Male']['tip']/tips[tips["sex"]=='Male']['total_bill']
rvs2=tips[tips['sex']=='Female']['tip']/tips[tips["sex"]=='Female']['total_bill']
print(stats.f_oneway(rvs1,rvs2)) #p=0.279710384960558,認爲不能拒絕原假設,rvs1與rvs2均值相同

'''
注意:
原假設的三個條件,其中方差齊次性:各組方差相等,但也不是說需要完全相等。
如何檢驗方差齊次性假設?
方差齊次性:stats.fligner(rvs1,rvs2) # 原假設方差相等
'''
x=[1,2,3,4,5]
y=[1,2,3,4,5]
print(stats.fligner(x,y))
print('兩組數的方差:',rvs1.var(),rvs2.var())
print(stats.fligner(rvs1,rvs2)) #在方差檢驗過程中我們也接受方差是齊次的,雖然我們計算他們的方差明顯是不相等的,但相差不大
F_onewayResult(statistic=1.1737495515748593, pvalue=0.279710384960558)
FlignerResult(statistic=6.590905151254103e-31, pvalue=0.9999999999999993)
兩組數的方差: 0.0041961727927699805 0.0028763620584040393
FlignerResult(statistic=0.9521374099494737, pvalue=0.3291758341219779)

ANOVA的非參數版本:Kruskal-Wallis H-test

H0: 各組中值近似相等
    對數據亦有假設條件:Chi2分佈,因此樣本容量需不小於5
    stats.kruskal(rvs1,rvs2)
相比於單因素ANOVA方差分析更加寬鬆
rvs1=tips[tips['sex']=='Male']['tip']/tips[tips["sex"]=='Male']['total_bill']
rvs2=tips[tips['sex']=='Female']['tip']/tips[tips["sex"]=='Female']['total_bill']
print(stats.kruskal(rvs1,rvs2)) #p值較大,接受原假設,即中位數基本相同,兩組變量無明顯差異,且相互獨立
KruskalResult(statistic=2.2351202029645436, pvalue=0.13490613264268328)
#練習:星期幾對小費是否有影響
display(pd.crosstab(tips.tip,tips.day).head())  #生成交叉表
Thur=tips[tips['day']=='Thur']['tip']
Fri=tips[tips['day']=='Fri']['tip']
Sat=tips[tips['day']=='Sat']['tip']
Sun=tips[tips['day']=='Sun']['tip']
print(stats.f_oneway(Thur,Fri,Sat,Sun)) #單因素ANOVA方差分析
#F_onewayResult(statistic=1.6723551980998699, pvalue=0.1735885553040592)

'''
方差分析檢驗對數據得假設:
1.樣本之間相互獨立
2.樣本均來自正態分佈
3.方差齊次性:各組方差相等
'''
print(stats.fligner(rvs1,rvs2))  #方差齊次性檢驗
#FlignerResult(statistic=1.6183029033640117, pvalue=0.20332858592898514)
#P值較大,認爲方差齊次

#如果不滿足以上任意一條
'''
ANOVA的非參數版本
Kruskal-Wallis H-test
H0:各組中值相等
對數據也有假設:Chi2卡方分佈,因此樣本容量需不小於5
給出得結果寬鬆一些,沒有ANOVA強
'''
count=pd.crosstab(tips.tip,tips.day).head()  #構造交叉表
print(stats.chi2_contingency(count,correction=False))  #卡方檢驗,p值較大,各類別變量間相互獨立

print(stats.kruskal(rvs2,rvs1))  #ANOVA的非參數版本檢驗
#KruskalResult(statistic=0.7615717066668545, pvalue=0.38283710822789807)
day Fri Sat Sun Thur
tip
1.00 1 3 0 0
1.01 0 0 1 0
1.10 0 1 0 0
1.17 0 1 0 0
1.25 0 2 0 1
F_onewayResult(statistic=1.6723551980998699, pvalue=0.1735885553040592)
FlignerResult(statistic=0.9521374099494737, pvalue=0.3291758341219779)
(13.809523809523808, 0.3130368414958159, 12, array([[0.4, 2.8, 0.4, 0.4],
       [0.1, 0.7, 0.1, 0.1],
       [0.1, 0.7, 0.1, 0.1],
       [0.1, 0.7, 0.1, 0.1],
       [0.3, 2.1, 0.3, 0.3]]))
KruskalResult(statistic=2.2351202029645436, pvalue=0.13490613264268328)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章