Python 卡方检验、克雷姆值
卡方檢驗是一種用途很廣的計數資料的假設檢驗方法。它屬于非參數檢驗的范疇,主要是比較兩個及兩個以上樣本率( 構成比)以及兩個分類變量的關聯性分析。其根本思想就是在于比較理論頻數和實際頻數的吻合程度或擬合優度問題。(更多參考:卡方檢驗、卡方分布)
?
不講過多理論,主要使用 python 實現卡方驗證。之前對于元素/特征/屬性 異常值的選擇情況,可以使用直方圖、箱型圖、Z分數法等篩選。如?Python 探索性數據分析(Exploratory Data Analysis,EDA) ,數據探索的同時,也可以排除單個變量的異常值。而對于離散屬性(或離散化)的分類,可以使用?等距分類、等頻分類 等,但是這樣分類不能體現出與其他屬性或結果的相關性。
?
當前則使用卡方驗證來將屬性分類。如客戶的婚姻情況對于貸款后是否回款還是有影響的,所以當前校驗離散值怎么分類更好。現在有一組數據,客戶的“婚姻情況”,更復雜點計算的話,“婚姻+年齡+性別” 相互作用還是比較強的,可同時將這幾個變量計算。此處只是有 婚姻情況測試。這些數據是歷史數據,有點客戶已經回款,有的未回款。
但是這些數據哪些是異常值,這些異常值是刪除,還是歸到其他類中呢?
首先進行粗分類,觀測他們的占比情況:
表1,基于客戶婚姻情況的粗分類
比值較近的可以劃分為同一類,如把 “再婚” 歸為 “已婚” ,“初婚” 歸為 “未婚” 。這時機器的算法,當然我們可以評經驗來分類 ,“再婚”、“初婚” 、“復婚” 其實都屬于“已婚”。
?
表2,該表格為各婚姻情況客戶是否回款的頻數
?
?
每個類別都是相互獨立,沒有交叉的,現在用另一種方法計算。假設是否回款的客戶的分布與總體保持一致。計算“已婚未回款的客戶數” =? 4124x5498/12405 =?1826(以所在行列的匯總值計算),最終結果如下:
?
表3,該表格為各婚姻情況客戶是否回款的期望頻數分布(理論推算值)
?
兩個表的數字差距越大,兩個表的獨立性越強,就表示兩個表的依賴度越高、粗分類結果越好。現在使用計算卡方距離:
?
?Ai為i水平的實際的觀察頻數,Ei為i水平的期望頻數。代入公式:
這就是卡方值,再計算卡方的 自由度 v:
v=(行數-1)(列數-1)=(2-1)(3-1) = 2
?
表4,卡方臨界值表部分數據
卡方臨界值 為 (一般取 p=0.05):
該臨界值小于實驗中的卡方值 23,差異明顯,拒絕0假設。
?
克雷姆值(Cramer'sV):
?克雷姆值是通過卡方值計算出來的公式如下:
其中,n 是數據集中的觀測值個數,克雷姆值總是在區間 [0,1]中,值越大表示變量的預測能力越高。根據經驗,通常去克雷姆值大于 0.1 的變量,或者取前 10% 的變量。 對于相同的特征屬性, IV值和克雷姆值的判別結果通常是一致的。(參考 WOE、VI 分類變量預測能力)
?
卡方值驗證,使用 python 腳本實現:
# -*- coding: UTF-8 -*- # python 3.5.0 # 卡方計算 __author__ = 'HZC'import math import sqlalchemy import numpy as np import pandas as pdclass CHISQUARE:def __init__(self,d):self.engine = sqlalchemy.create_engine("mssql+pymssql://%s:%s@%s/%s" %(d['user'],d['pwd'],d['ins'],d['db']))def get_df_from_query(self,sql):df = pd.read_sql_query(sql, self.engine)return dfdef get_variance(self,df):row_count = df.shape[0]-1col_count = df.shape[1]-1v = (row_count-1)*(col_count-1)return v#轉為矩陣求卡方距離def get_chi_square_value(self,df1,df2):df1 = df1.drop(['col_total'])df2 = df2.drop(['col_total'])del df1['row_total']del df2['row_total']mtr1 = df1.astype(int).as_matrix()mtr2 = df2.astype(int).as_matrix()mtr = ((mtr1-mtr2)**2)/mtr2return mtr.sum()#分類頻數 def get_classification(self,table_name,col_result,col_pred):sql = "select %s,%s from %s" % (col_result,col_pred,table_name)df = self.get_df_from_query(sql)df = df.groupby([col_result,col_pred]).agg({col_result:['count']})df = df.reset_index()df.columns = [col_result,col_pred, 'count']df = pd.pivot_table(df, values = 'count', index=col_result, columns = col_pred).reset_index()df['row_total'] = df.sum(axis=1)df.set_index(col_result, inplace=True)df.loc['ratio(%)'] = df.loc[0]*100/df.loc[1]print("==========================================================")print("原始數據粗分類:(百分比相近的可劃分為同一類)")print("==========================================================")print(df.astype(int))df = df.drop(['ratio(%)'])df.loc['col_total']=df.sum(axis=0)print("==========================================================")print("分類頻數匯總:(實際值)")print("==========================================================")print(df.astype(int))df2 = df.copy()total = df2[['row_total']].loc[['col_total']].values[0][0]for col in df2:df2[col] = df2[[col]].loc[['col_total']].values[0][0] * df2['row_total']/totaldf2 = df2.drop(['col_total'])df2.loc['col_total']=df2.sum(axis=0)print("==========================================================")print("期望頻數分布:(理論推算值)")print("與上表差距越大,兩表的獨立性越低、依存度越高,粗分類效果越好")print("==========================================================")print(df2.astype(int))print("==========================================================")x = self.get_chi_square_value(df,df2)#順序:(實際df,推算df)v = self.get_variance(df2) # v=(行數-1)(列數-1)print("卡方值:χ2 = %s" % x)print("自由度:v = %s" % v)print("==========================================================")if __name__ == "__main__":conn = {'user':'用戶名','pwd':'密碼','ins':'實例','db':'數據庫'} cs = CHISQUARE(conn)cs.get_classification("V_ClientInfoAll","是否回款","婚姻狀況")#cs.get_classification(表或視圖,回歸只/判斷值,"分類元素")只可分析兩個變量之間的關系值,輸出結果如下:
?
轉載于:https://www.cnblogs.com/hzc2012/p/8282336.html
總結
以上是生活随笔為你收集整理的Python 卡方检验、克雷姆值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot13 发布和监听事件
- 下一篇: websocket python爬虫_p