附录 B — Mytools
Python
B.1 工具说明
统计与分析课程自定义函数,主要目标:
- 降低使用Python进行常见数据分析时的难度。
- 提高数据分析结果的可读性。
- 引导用户选择合适的数据分析方法。
B.2 工具源代码
# 导入各种包
import pandas as pd
from pyreadstat import pyreadstat
import matplotlib.pyplot as plt
from scipy import stats
from tabulate import tabulate
from scipy.stats import somersd
import plotly.express as px
# 绘图设置
plt.rcParams["font.sans-serif"] = ["SimHei"] # 设置字体
def 使用plotly绘制类别变量柱状图(数据表, 类别变量):
temp = 数据表[类别变量].value_counts().reset_index()
fig = px.bar(temp, x=类别变量, y='count', labels={'count': '数量'})
# 显示图表
fig.show()
def 使用标准差判断数值变量异常值(数据表, 数值变量):
mean = 数据表[数值变量].mean()
std = 数据表[数值变量].std()
condition1 = (数据表[数值变量] < mean - 3 * std) | (数据表[数值变量] > mean + 3 * std)
# 识别异常值
outliers1 = 数据表[condition1]
print('使用标准差判断的异常值为:', outliers1)
def 计算单变量均值的置信区间(数据表路径及文件名, 变量名, 置信水平=0.95):
""" 计算指定数据表中数值变量的均值及在指定置信水平下的置信区间 """
# 打开数据文件
file_path = 数据表路径及文件名
df = pd.read_csv(file_path)
# 计算均值和标准误差
mean = df[变量名].mean()
std_error = stats.sem(df[变量名])
# 设定置信水平
confidence_level = 置信水平
# 设定自由度
自由度 = len(df[变量名]) - 1
# 计算置信区间
confidence_interval = stats.t.interval(
confidence_level, 自由度, loc=mean, scale=std_error)
# 输出结果
print(F"变量{变量名}均值:{mean: .2f}")
print(F"均值在置信水平{confidence_level}下的置信区间为:", confidence_interval)
return mean, confidence_interval
def 绘制单个类别变量柱状图(数据表, 变量: str):
""" 绘制单个类别变量柱状 """
x = 数据表[变量].value_counts().index
y = 数据表[变量].value_counts(normalize=True).values * 100
# 创建图
fig, ax = plt.subplots()
# 绘制柱状图
rects1 = ax.bar(x, y)
# 设置x轴变量名称
ax.set_xlabel(变量)
# 设置y轴最大值
ax.set_ylim(ymax=100)
# 在柱上方显示对应的值
ax.bar_label(rects1, fmt="%.1f", padding=3)
# 显示图形
plt.show()
def 读取SPSS数据(文件所在位置及名称):
""" 读取SPSS文件,保留标签内容和有序变量顺序 """
result, metadata = pyreadstat.read_sav(
文件所在位置及名称, apply_value_formats=True, formats_as_ordered_category=True)
return result, metadata
def 有序变量描述统计函数(表名, 变量名):
""" 对有序类别变量进行描述统计 """
result = 表名[变量名].value_counts(sort=False)
描述统计表 = pd.DataFrame(result)
描述统计表['比例'] = 描述统计表['count'] / 描述统计表['count'].sum()
描述统计表['累计比例'] = 描述统计表['比例'].cumsum()
return 描述统计表
def 数值变量描述统计1(数据表, 变量名):
result = 数据表[变量名].describe()
中位数 = result['median']
平均值 = result['mean']
标准差 = result['std']
return 中位数, 平均值, 标准差
def 数值变量描述统计(数据表, 变量名):
""" 对数值变量进行描述统计 """
result = 数据表[变量名].describe()
return result
def goodmanKruska_tau_y(df, x: str, y: str) -> float:
""" 计算两个定序变量相关系数tau_y """
""" 取得条件次数表 """
cft = pd.crosstab(df[y], df[x], margins=True)
""" 取得全部个案数目 """
n = cft.at['All', 'All']
""" 初始化变量 """
E_1 = E_2 = tau_y = 0
""" 计算E_1 """
for i in range(cft.shape[0] - 1):
F_y = cft['All'][i]
E_1 += ((n - F_y) * F_y) / n
""" 计算E_2 """
for j in range(cft.shape[1] - 1):
for k in range(cft.shape[0] - 1):
F_x = cft.iloc[cft.shape[0] - 1, j]
f = cft.iloc[k, j]
E_2 += ((F_x - f) * f) / F_x
""" 计算tauy """
tau_y = (E_1 - E_2) / E_1
return tau_y
def 相关系数强弱判断(相关系数值):
""" 相关系数强弱的判断 """
if 相关系数值 >= 0.8:
return '极强相关'
elif 相关系数值 >= 0.6:
return '强相关'
elif 相关系数值 >= 0.4:
return '中等程度相关'
elif 相关系数值 >= 0.2:
return '弱相关'
else:
return '极弱相关或无相关'
def 制作交叉表(数据表, 自变量, 因变量):
return pd.crosstab(数据表[自变量], 数据表[因变量], normalize='columns', margins=True)
def 读取SPSS数据文件(文件位置及名称, 是否保留标签值=True):
数据表, metadata = pyreadstat.read_sav(
文件位置及名称, apply_value_formats=是否保留标签值, formats_as_ordered_category=True)
return 数据表
def p值判断(p: float, α=0.05):
""" p值判断 """
if p <= α:
return '拒绝虚无假设'
else:
return '接受虚无假设'
def 相关系数判断(系数: int):
"""
判断相关系数的强弱
"""
if 系数 >= 0.8:
return '极强相关'
elif 系数 >= 0.6:
return '强相关'
elif 系数 >= 0.4:
return '中等强度相关'
elif 系数 >= 0.2:
return '弱相关'
else:
return '极弱相关或无相关'
def 绘制柱状图(表名):
x = 表名.index
y = 表名['count'].values
fig, ax2 = plt.subplots()
ax2.bar(x, y)
plt.show()
def 两个无序类别变量的统计分析(数据表, 自变量, 因变量):
""" 对两个无序类别变量进行描述统计和推论统计,并给出辅助结论 """
# 计算相关系数
tau_y = goodmanKruska_tau_y(数据表, 自变量, 因变量)
# 制作交互分类表
交互表 = pd.crosstab(数据表[F"{自变量}"], 数据表[F"{因变量}"])
# 进行卡方检验
chi2, p, dof, ex = stats.chi2_contingency(交互表)
print(F"tau_y系数:{tau_y: 0.4f}", 相关系数判断(tau_y))
print(tabulate(交互表))
print(F"卡方值:{chi2: .2f}, p值:{p: .4f},自由度:{dof}。")
print(p值判断(p))
def 两个有序类别变量的统计分析(数据表, 自变量, 因变量):
""" 对两个有序类别变量进行描述统计和推论统计,并给出辅助结论 """
x = 数据表[F"{自变量}"].cat.codes
y = 数据表[F"{因变量}"].cat.codes
result = somersd(x, y)
# 制作交互分类表
交互表 = pd.crosstab(数据表[F"{自变量}"], 数据表[F"{因变量}"])
d_y = result.statistic
p = result.pvalue
print(F"Somers dy系数:{d_y: 0.4f}", 相关系数判断(d_y))
print(tabulate(交互表))
print(F"p值:{p: .4f}")
print(p值判断(p))
def 两个数值变量的统计分析(数据表, 自变量, 因变量):
""" 对两个数值变量进行统计分析,并给出辅助结论 """
x = 数据表[自变量]
y = 数据表[因变量]
r, p = stats.pearsonr(x, y)
fig = px.scatter(数据表, x, y, trendline='ols')
fig.show()
print(FR"决定系数r平方:{r*r :0.4f}")
print(决定系数强弱判断(r*r))
print(F"p值:{p: .4f}")
print(p值判断(p))
def 决定系数强弱判断(决定系数: float):
"""
<0.25 <0.06 微弱相关或不相关
0.25≤≤0.5 0.06≤≤0.25 低度相关
0.5≤≤0.75 0.25≤≤0.56 中度相关
>0.75 >0.56 高度相关
"""
if 决定系数 > 0.56:
return "高度相关"
elif 决定系数 > 0.25:
return "中度相关"
elif 决定系数 > 0.26:
return "低度相关"
else:
return "微弱相关或不相关"
def 相关比率强弱判断(相关比率: float):
"""
小于 0.01 微弱相关或不相关
[0.01-0.06] 低度相关
[0.06-0.14] 中度相关
[0.14-0.99] 高度相关
1 完全相关
"""
if 相关比率 > 0.14:
return "高度相关"
elif 相关比率 > 0.06:
return "中度相关"
elif 相关比率 > 0.01:
return "低度相关"
else:
return "微弱相关或不相关"
def 类别变量与数值变量统计分析(数据表, 类别变量, 数值变量):
""" 对数值变量的不同类别进行对比,并给出辅助结论 """
from statsmodels.formula.api import ols
fig = px.box(数据表, x=类别变量, y=数值变量)
fig.show()
model = ols(F'{数值变量} ~ {类别变量}', 数据表).fit()
# 计算各个类别的平均值
category_means = 数据表.groupby(类别变量)[数值变量].mean()
# 打印各个类别的平均值
print("各个类别的平均值:")
print(category_means)
print(F"相关比率:{model.rsquared}")
print(相关比率强弱判断(model.rsquared))
print(F"F检验的p值:{model.f_pvalue}")
print(model.summary())