接上文
生成一个近视指标。看看不同年龄段的近视比例
df['idx_of_nearSight'] = (df['sight_impaired'] == True ) & ((df['right_s'] < -0.5) |(df['left_s'] < -0.5))
df['idx_of_nearSight'].value_counts()
df.groupby('type')['idx_of_nearSight'].value_counts(normalize=True).unstack()
这里可以看出近视比例随着学段,不断上升了
那么做一个卡方检验。
crs_of_nearSight = df.groupby('type')['idx_of_nearSight'].value_counts(normalize=True).unstack()
crs_of_nearSight
import scipy.stats as ss
ss.chi2_contingency(crs_of_nearSight)
保存crs_of_nearSight是为了后面用。
这样就可以得到卡方检验的结果。
crs_of_nearSight = df.groupby('type')['idx_of_nearSight'].value_counts().unstack()
crs_of_nearSight
import scipy.stats as ss
ss.chi2_contingency(crs_of_nearSight)
卡方检验必须用绝对数,所以 value_counts()里面的normalize不能有。
结果,χ2值是1244,非常大,非常显著。
为了写到论文里面,把这个表格赋值到剪切板里。发送到excel。好编辑。
import scipy.stats as ss
ss.chi2_contingency(crs_of_nearSight)
crs_of_nearSight
y = ss.chi2_contingency(crs_of_nearSight)
y
crs_of_nearSight.loc['chi2'] = y[0]
crs_of_nearSight.loc['P'] = y[1]
crs_of_nearSight
crs_of_nearSight.to_clipboard()
删去chi2和P的后面的格就可以。
接下来可以看各个年级的近视率了。
这里生成一个交叉表,还是需要reindex
用pivot_table 也是可以的。
pd.pivot_table(index='nianji', data=df)['idx_of_nearSight']
x = pd.pivot_table(index='nianji', data=df)['idx_of_nearSight']
nianji_order
x.reindex(nianji_order)
y = x.reindex(nianji_order)
plt.plot(y)
plt.xticks(rotation=45)
得到近视率
可以看出,近视率从小学到初中,一路攀升。
这里也可以用crosstab
pd.crosstab(index = df['nianji'], columns = df['idx_of_nearSight'])
可以得到各个年级的近视人数。
还是做一个图
pd.crosstab(index = df['nianji'], columns = df['idx_of_nearSight'], normalize = 'index')
pd.crosstab(index = df['nianji'], columns = df['idx_of_nearSight'], margins='row')
算百分比的。
列出行总数的。
当然这个表也可以计算卡方。
还是做一个图。
x = pd.crosstab(index = df['nianji'], columns = df['idx_of_nearSight'], normalize = 'index')[True]
fig, ax = plt.subplots()
ax.plot(x.reindex(nianji_order))
ax.set_xticklabels(labels = nianji_order, rotation= 45)
另外还想分男女生作图。
pd.pivot_table(index='nianji', columns = 'sex', data= df)['idx_of_nearSight']
用pivot_table 比较简洁。
也可以用grouby或者crosstab
x = df.groupby(['nianji', 'sex'])['idx_of_nearSight'].mean().unstack()
x.reindex(nianji_order)
可以得到结果。
做一个图看看。
plt.plot(x.reindex(nianji_order))
发现,没有标明男女,那还是分别作图。
fig, ax = plt.subplots()
ax.plot(y['男'], label = '男生')
ax.plot(y['女'], label = '女生')
plt.legend()
plt.xticks(rotation=45)
发现,小学阶段,女生近视率比男生高,一直到初中,初中阶段也是女生近视率略高,这可能是因为,女生都比男生爱学习???
另外一个任务就是,区分 视力不良的程度。 5.0当然是最好的,4.9算是轻度,4.6-4.8算是中度不良,4.5及以下,就是重度。
#---------------------------------------------------------#
#---- * 区分,轻度,重度,中度 * ----#
#---------------------------------------------------------#
xx = pd.cut(df['left'], bins = [0, 4.6, 4.85, 4.95, 6], right = True, labels = ["bad", "mid", "little", "good"])
xx.value_counts()
yy = pd.cut(df['left'], bins = [0, 4.6, 4.85, 4.95, 6], right = True)
yy.value_counts()
可以看出,good的是5.0的。4.6-4.9的是轻度,单纯从左眼来看。
视力好的,有4933个人。轻度不良的(4.9)的有1007.因为区间是 (4.85, 4.95】
中度的是1471,区间是(4.55, 4.85】,重度的是 1366,区间是4.5及以下。
视力不良判别,程度判断指标,只能分开左右眼来判断。分组也很麻烦。左右眼判断要分别开。这个就不做了。
比较简单的是分左右眼,统计均值。
pd.pivot_table(index='nianji', columns = ['sex'], values =['right', 'left'] , data = df)
pd.crosstab(index = df['nianji'], columns=df['sex'], values=df['right'], aggfunc = 'mean')
pd.crosstab(index = df['nianji'], columns=df['sex'], values= df['left'], aggfunc = 'mean')
df.groupby(['nianji', 'sex'])['right', 'left'].mean().unstack()
上述三种方式,都可以。
x = df.groupby(['nianji', 'sex'])['right', 'left'].mean().unstack()
x
用groupby。
x = x.reindex(nianji_order)
x
right_mean = x.loc[:, 'right']
left_mean = x.loc[:, 'left']
right_mean['男']
left_mean['女']
fig, ax = plt.subplots()
plt.plot(right_mean['男'], label = "男生, 右眼")
plt.plot(right_mean['女'], label = "女生, 右眼", linestyle = '--')
plt.plot(left_mean['男'], label = "男生, 左眼")
plt.plot(left_mean['女'], label = "女生, 左眼", linestyle = '--')
plt.legend(loc='best')
plt.xticks(rotation=45)
可以看出,视力的顶峰是一年级时期。或者大班时期,这时候,视力发育成熟,基本都是5.0.从小学开始,一路下降。