无序分类变量的统计分析

发布时间:2023-05-19

无序分类变量的基本概念

无序分类变量是指变量分组之后,组与组之间没有顺序关系的分类变量。它们通常采用哑变量来表示,其中1表示某类,0表示不是这类。 在统计学分析中,无序分类变量是一种常用的数据类型,广泛应用于社会科学、医学、生物学等领域。因此,理解无序分类变量及其分析方法显得尤为重要。

无序分类变量的种类

无序分类变量的种类较多,常见的包括:

  1. 性别(男、女)
  2. 教育程度(小学、初中、高中、本科、研究生、博士)
  3. 宗教信仰(基督教、伊斯兰教、佛教、无神论等)
  4. 婚姻状态(已婚、未婚、离异)
  5. 民族(汉族、少数民族)

无序分类变量的资料形式

无序分类变量的资料形式通常采用哑变量表示。例如,对于一个涉及性别的问题,1表示男,0表示女。对于一个涉及宗教信仰的问题,1表示基督教,0表示其他信仰或无信仰。

import pandas as pd
sex = pd.get_dummies(data['性别'])
print(sex)

无序分类变量的统计学检验方法

常用的无序分类变量的统计学检验方法包括:

1. 卡方检验

卡方检验是用来检验两个或多个分类变量之间是否独立的方法,它基于对实际值和期望值之间的差别进行计算。

from scipy.stats import chi2_contingency
# sex和education都是哑变量
chi2_contingency(pd.crosstab(data['性别'], data['教育程度']))

2. Fisher精确检验

当样本量较小时,卡方检验的精度可能会受到影响。此时,可以使用Fisher精确检验。

from scipy.stats import fisher_exact
# sex和education都是哑变量
fisher_exact(pd.crosstab(data['性别'], data['教育程度']))

3. 启发式的检验方法

启发式的无序分类变量检验方法主要包括: 1)检查各组别的频率,若某组别的频率小于5,则对数据进行合并;
2)计算每个组别的样本比例,若比例差异较大,则对数据进行合并。

# sex和alcoholism都是哑变量
contingency_table = pd.crosstab(data['性别'], data['酗酒'], margins=False) 
cont_table = contingency_table.iloc[:, [0, 1]] 
# sex = 1表示男性,sex = 0表示女性
# alcoholism = 1表示有酗酒史,alcoholism = 0 表示无酗酒史
p0 = (cont_table.iloc[0, 0] + cont_table.iloc[1, 0]) / cont_table.values.sum() 
p1 = (cont_table.iloc[0, 1] + cont_table.iloc[1, 1]) / cont_table.values.sum() 
if np.abs(p1 - p0) > 0.2:
    contingency_table.iloc[:, 1] = (contingency_table.iloc[:, 1] + 1) % 2

举例说明无序分类变量分析方法

以肝癌患病与吸烟、饮酒行为的关系为例,分析吸烟和饮酒是否与肝癌患病有关联。

import pandas as pd
import numpy as np
from scipy.stats import chi2_contingency
from scipy.stats import fisher_exact
from matplotlib import pyplot as plt
# 构造数据
data = pd.DataFrame({
    "sex": [1, 0, 0, 1, 0, 1, 0, 1, 1, 0],
    "alcoholism": [1, 1, 0, 1, 0, 0, 0, 1, 1, 0],
    "smoker": [1, 1, 0, 1, 0, 1, 0, 0, 0, 0],
    "liver_cancer": [0, 0, 1, 1, 1, 0, 1, 1, 1, 1],
})
# 使用卡方检验
print(chi2_contingency(pd.crosstab(data['alcoholism'], data['liver_cancer'])))
print(chi2_contingency(pd.crosstab(data['smoker'], data['liver_cancer'])))
# 使用Fisher精确检验
print(fisher_exact(pd.crosstab(data['alcoholism'], data['liver_cancer'])))
print(fisher_exact(pd.crosstab(data['smoker'], data['liver_cancer'])))
# 使用启发式的检验方法
contingency_table = pd.crosstab(data['alcoholism'], data['liver_cancer'], margins=False) 
cont_table = contingency_table.iloc[:, [0, 1]] 
p0 = (cont_table.iloc[0, 0] + cont_table.iloc[1, 0]) / cont_table.values.sum() 
p1 = (cont_table.iloc[0, 1] + cont_table.iloc[1, 1]) / cont_table.values.sum() 
if np.abs(p1 - p0) > 0.2:
    contingency_table.iloc[:, 1] = (contingency_table.iloc[:, 1] + 1) % 2
contingency_table = pd.crosstab(data['smoker'], data['liver_cancer'], margins=False) 
cont_table = contingency_table.iloc[:, [0, 1]] 
p0 = (cont_table.iloc[0, 0] + cont_table.iloc[1, 0]) / cont_table.values.sum() 
p1 = (cont_table.iloc[0, 1] + cont_table.iloc[1, 1]) / cont_table.values.sum() 
if np.abs(p1 - p0) > 0.2:
    contingency_table.iloc[:, 1] = (contingency_table.iloc[:, 1] + 1) % 2
# 绘制条形图
fig, ax = plt.subplots(1, 2, figsize=(10, 5))
ax[0].bar(contingency_table.index, contingency_table[0], label="No liver cancer")
ax[0].bar(contingency_table.index, contingency_table[1], label="Liver cancer", bottom=contingency_table[0])
contingency_table = pd.crosstab(data['smoker'], data['liver_cancer'], margins=False) 
ax[1].bar(contingency_table.index, contingency_table[0], label="No liver cancer")
ax[1].bar(contingency_table.index, contingency_table[1], label="Liver cancer", bottom=contingency_table[0])
plt.legend()
plt.show()