我是人 发表于 2020-8-12 10:17

【python】数据分析bug求助

卡方检验,调查500人,文化程度与性别是否相互独立


import numpy as np
import pandas as pd
from scipy import stats

sample_df = pd.read_excel('4-15.xlsx',header=0, index_col=0) # 注意要把性别列作为索引
sample_df


      高中及以上      初中      小学及以下
性别                        
男      44      36      140
女      60      60      160


# 编写一个用于卡方检验的工具
class ChisquareTest():
    def __init__(self,df):
      self.data = df.copy()
      self.summed_data = None
      self.expected_data = None
      self.chi2_data = None
      self.row_sum_name = '行合计'
      self.col_sum_name = '列合计'
      self.caculate_sum_finished = False
      self.caculate_expect_finished = False
      
    def caculate_sum(self, df = None):
      sum_original_data = df is None
      if sum_original_data:
            df = self.data.copy()
            
      df = df.apply(lambda row:row.sum(),axis = 1 )
      df.loc = df.apply(lambda col: col.sum(),axis = 0 )
      
      if sum_original_data:
            self.summed_data = df
            self.caculate_sum_finished = True
            
      return df
   
    def caculate_expect(self):
      if (not self.caculate_expect_finished):
            self.caculate_sum()
      self.expected_data = self.data.copy()
      total_sum = self.summed_data.loc
      for i in range(len(self.data)):
            for j in range(len(self.data.columns)):
                row_sum = self.summed_data.iloc
                col_sum = self.summed_data.loc
                self.expected_data.iloc = row_sum * col_sum / total_sum
            self.expected_data = self.caculate_sum(self.expected_data)
            self.caculate_expect_finished = True
            return self.expected_data
      
    def caculate_chi2(self):
      if (not self.caculate_expect_finished):
            self.caculate_expect()
      self.chi2_data = self.data.copy()
      for i in range(len(self.data)):
            for j in range(len(self.data.columns)):
                obs_value = self.data.iloc
                exp_value = self.expected_data.iloc
                self.chi2_data.iloc = (obs_value - exp_value) ** 2 / exp_value
      self.chi2_data = self.caculate_sum(df = self.chi2_data)
      return self.chi2_data


chi2test = ChisquareTest(sample_df)

# 求和列表
chi2test.caculate_sum()

      高中及以上      初中      小学及以下      行合计
性别                              
男      44      36      140      220
女      60      60      160      280
列合计      104      96      300      500


以上的都正常,下面的是问题

# 期望值表
chi2test.caculate_expect()

      高中及以上      初中      小学及以下      行合计
性别                              
男      45.76      42.24      132.0      220.0
女      60.00      60.00      160.0      280.0
列合计      105.76      102.24      292.0      500.0

这个结果和书上的不一样,书上的是


# 卡方统计表
chi2test.caculate_chi2()

      高中及以上      初中      小学及以下      行合计
性别                              
男      0.067692      0.921818      0.484848      1.474359
女      0.000000      0.000000      0.000000      0.000000
列合计      0.067692      0.921818      0.484848      1.474359

这个结果和书上的不一样,书上的是


问题应该是是,不对第二行“女”的数据进行处理,应该是函数中的问题,咋也没找到。


谢谢大家了!

我是人 发表于 2020-8-12 10:39

我找到原因了

函数定义中的 i 需要+1

    def caculate_expect(self):
      if (not self.caculate_expect_finished):
            self.caculate_sum()
      self.expected_data = self.data.copy()
      total_sum = self.summed_data.loc
      for i in range(len(self.data)):
            for j in range(len(self.data.columns)):
                row_sum = self.summed_data.iloc
                col_sum = self.summed_data.loc
                self.expected_data.iloc = row_sum * col_sum / total_sum
            self.expected_data = self.caculate_sum(self.expected_data)
            self.caculate_expect_finished = True
            return self.expected_data

我是人 发表于 2020-8-12 15:32

我是人 发表于 2020-8-12 10:39
我找到原因了

函数定义中的 i 需要+1


不对,这样也不对!

大家帮帮我!求求了!

我是人 发表于 2020-8-12 15:37

我知道了,我整错了三个缩进,就是这里最后三行的缩进,这样是正确的,就ok了。

不能粗心啊!

def caculate_expect(self):
      if (not self.caculate_expect_finished):
            self.caculate_sum()
      self.expected_data = self.data.copy()
      total_sum = self.summed_data.loc
      
      for i in range(len(self.data)):
            for j in range(len(self.data.columns)):
                row_sum = self.summed_data.iloc
                col_sum = self.summed_data.loc
                self.expected_data.iloc = row_sum * col_sum / total_sum
      self.expected_data = self.caculate_sum(self.expected_data)
      self.caculate_expect_finished = True
      return self.expected_data

ymhld 发表于 2020-8-13 23:48

python 缩进很重要
页: [1]
查看完整版本: 【python】数据分析bug求助