常见的统计分析方法
import numpy as np
import scipy.stats as spss
import pandas as pd鸢尾花数据集
https://github.com/mwaskom/seaborn-data
df = pd.read_csv("iris.csv",index_col="species")
v1 = df.loc["versicolor",:].petal_length.values
v2 = df.loc["virginica",:].petal_length.values符合正态分布(p>0.05)
# Shapiro-Wilk test
stat, p_value = spss.shapiro(v1)
stat, p_value = spss.shapiro(v2)方差齐,即v1和v2的方差没有显著性差异,即p>0.05
# 非参数检验,对于数据的分布没有要求
stat, p_value = spss.levene(v1,v2)
# 要求数据服从正态分布
stat, p_value = spss.bartlett(v1,v2)stat, p_value = spss.ttest_ind(v1,v2)配对 Paired Student’s t-test(本例中v1,v2并不是配对样本,这里仅用于演示)
stat, p_value = spss.ttest_rel(v1,v2)df.petal_length.groupby(df.index).apply(spss.shapiro)
# species
# setosa (0.971718966960907, 0.27151283621788025)
# versicolor (0.9741330742835999, 0.3379890024662018)
# virginica (0.9673907160758972, 0.1808987259864807)
# Name: sepal_width, dtype: objectp_value > 0.05方差齐
v1 = df.loc["versicolor",:].sepal_width.values
v2 = df.loc["virginica",:].sepal_width.values
v3 = df.loc["setosa",:].sepal_width.values
stat, p_value = spss.bartlett(v1,v2,v3)p_value < 0.05三个物种间的sepal_width有差异
stat, p_value = spss.f_oneway(v1, v2, v3)也可以使用statsmodels中的函数,结果一致
from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
df.loc[:,'species'] = df.index
aov_results = anova_lm(ols('sepal_width ~ species', data = df).fit())
aov_results
# df sum_sq mean_sq F PR(>F)
# species 2.0 11.344933 5.672467 49.16004 4.492017e-17
# Residual 147.0 16.962000 0.115388 NaN NaN3个物种两两之间的sepal_width都有显著性差异
from statsmodels.stats.multicomp import pairwise_tukeyhsd
tukey = pairwise_tukeyhsd(df.sepal_width, df.index)
print(tukey)
# Multiple Comparison of Means - Tukey HSD, FWER=0.05
# ============================================================
# group1 group2 meandiff p-adj lower upper reject
# ------------------------------------------------------------
# setosa versicolor -0.658 0.0 -0.8189 -0.4971 True
# setosa virginica -0.454 0.0 -0.6149 -0.2931 True
# versicolor virginica 0.204 0.0088 0.0431 0.3649 True
# ------------------------------------------------------------stat, p_value = spss.ranksums(v1, v2)stat, p_value = spss.wilcoxon(v1, v2)stat, p_value = spss.kruskal(v1, v2, v3)v1,v2符合正态分布
r, p_value = spss.pearsonr(v1,v2)v1,v2的分布没有特定的要求
r, p_value = spss.spearmanr(v1,v2)v1,v2的分布没有特定的要求
r, p_value = spss.kendalltau(v1,v2)df.cov(numeric_only=True)
# sepal_length sepal_width petal_length petal_width
# sepal_length 0.685694 -0.042434 1.274315 0.516271
# sepal_width -0.042434 0.189979 -0.329656 -0.121639
# petal_length 1.274315 -0.329656 3.116278 1.295609
# petal_width 0.516271 -0.121639 1.295609 0.581006df.corr(numeric_only=True)
# sepal_length sepal_width petal_length petal_width
# sepal_length 1.000000 -0.117570 0.871754 0.817941
# sepal_width -0.117570 1.000000 -0.428440 -0.366126
# petal_length 0.871754 -0.428440 1.000000 0.962865
# petal_width 0.817941 -0.366126 0.962865 1.000000汽车耗油量数据集https://github.com/mwaskom/seaborn-data
mpg = pd.read_csv("mpg.csv")pd.value_counts(mpg.origin)
# usa 249
# japan 79
# europe 70
# Name: origin, dtype: int64
# 百分比
pd.value_counts(mpg.origin,normalize=True)
# usa 0.625628
# japan 0.198492
# europe 0.175879
# Name: origin, dtype: float64两个以上的变量交叉分类的频数分布表
pd.crosstab(mpg.cylinders, mpg.origin)
# origin europe japan usa
# cylinders
# 3 0 4 0
# 4 63 69 72
# 5 3 0 0
# 6 4 6 74
# 8 0 0 103
pd.crosstab(mpg.cylinders, mpg.origin, margins = True)
# origin europe japan usa All
# cylinders
# 3 0 4 0 4
# 4 63 69 72 204
# 5 3 0 0 3
# 6 4 6 74 84
# 8 0 0 103 103
# All 70 79 249 398pd.crosstab(mpg.cylinders, mpg.origin, normalize = True)
# origin europe japan usa
# cylinders
# 3 0.000000 0.010050 0.000000
# 4 0.158291 0.173367 0.180905
# 5 0.007538 0.000000 0.000000
# 6 0.010050 0.015075 0.185930
# 8 0.000000 0.000000 0.258794pd.crosstab(mpg.cylinders, mpg.origin, normalize = 0)
# origin europe japan usa
# cylinders
# 3 0.000000 1.000000 0.000000
# 4 0.308824 0.338235 0.352941
# 5 1.000000 0.000000 0.000000
# 6 0.047619 0.071429 0.880952
# 8 0.000000 0.000000 1.000000pd.crosstab(mpg.cylinders, mpg.origin, normalize = 1)
# origin europe japan usa
# cylinders
# 3 0.000000 0.050633 0.000000
# 4 0.900000 0.873418 0.289157
# 5 0.042857 0.000000 0.000000
# 6 0.057143 0.075949 0.297189
# 8 0.000000 0.000000 0.413655在该函数中,参数“correction”用于设置是否进行连续性校正,默认为 True。对于大样本,且频数表中每个单元格的期望频数都比较大(一般要求大于 5),可以不进行连续性校正。
tb = pd.crosstab(mpg.cylinders, mpg.origin)
# χ2 值、 P 值、自由度、期望频数表
chi2, p_value, df, expected = spss.chi2_contingency(tb)
p_value
# 9.800693325588298e-35
expected
# array([[ 0.70351759, 0.79396985, 2.50251256],
# [ 35.87939698, 40.49246231, 127.6281407 ],
# [ 0.52763819, 0.59547739, 1.87688442],
# [ 14.77386935, 16.67336683, 52.55276382],
# [ 18.11557789, 20.44472362, 64.43969849]])R语言中fisher.test的故事以及示例
Agresti (1990, p. 61f; 2002, p. 91) Fisher's Tea Drinker A British woman claimed to be able to distinguish whether milk or tea was added to the cup first. To test, she was given 8 cups of tea, in four of which milk was added first. The null hypothesis is that there is no association between the true order of pouring and the woman's guess, the alternative that there is a positive association (that the odds ratio is greater than 1).
如果观察总例数 n 小于 40,或者频数表里的某个期望频数很小(小于 1),则需要使用 Fisher 精确概率检验
spss.fisher_exact这个函数的输入只能是2X2的二维列联表,R中的fisher.test输入可以不是2X2列联表。
OR$\in$(0,+inf)如果 OR 值大于 1,则说明该因素更容易导致结果事件发生
alternative可以选two-sided(默认,OR可能>1,也可能<1), less(OR<1), greater(OR>1)
tea_tasting = pd.DataFrame({"Milk":[3,1],"Tea":[1,3]},index=["Milk", "Tea"])
tea_tasting
# Milk Tea
# Milk 3 1
# Tea 1 3
OR, p_value = spss.fisher_exact(tea_tasting,alternative="greater")
OR, p_value
# (9.0, 0.24285714285714283)
# p > 0.05, association could not be established对每个对象分别用两种方法处理
from statsmodels.sandbox.stats.runs import mcnemar
tb = np.array([[11, 12],[2, 33]])
stat, p_value = mcnemar(tb, exact = False, correction = True)
p_value
# 0.016156931261181305https://www.heywhale.com/mw/notebook/61e3d3c7ddda3c0017b4658f
https://www.statsmodels.org/stable/generated/statsmodels.sandbox.stats.runs.mcnemar.html原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。