利用python分析合师2017体测数据

师范学校男女比例真的是3:7吗?哪些专业女生人数比较多?哪些专业男生比较多? .....

数据来源

数据是每年体测后班级群拿到的全校的体测数据xml格式的表,笔者直接用wps另存为csv格式文件,以便方便用pandas分析

1
2
3
4
5
6
import pandas  as pd 
import matplotlib.pyplot as plt

data=pd.read_csv('2017年合师体测原始数据.csv')
#我们看看表的前5行
data.head()
png

png

男女比例

1
2
3
4
5
6
7
8
9
10
#enmm 参加体测的人数
all_stu=len(pd.notnull(data['姓名']))
female_num=len(data[data['性别']=='女'])
male_num=len(data[data['性别']=='男'])
rate=male_num/all_stu

print("学生总数 %d"%all_stu)
print("男生总数 %d"%male_num)
print('女生总数 %d'%female_num)
print('男% d:女 %d'%(int(rate*10),10-int(rate*10)))
学生总数 15250
男生总数 6437
女生总数 8813
男 4:女 6

师范学校女生是要多一点 男4女6的样子 并不是37比 emmm男性单身狗要开始怀疑人生了.........

不同专业的男女比例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

new_data=data.copy()

#去掉班级前面的年级

def remove_year(x):
if type(x) is not str:
return ""
return x[5:]


new_data['班级名称']=data['班级名称'].map(lambda x: remove_year(x))


gb=new_data.groupby("班级名称")

rank={}

for (name,df) in gb:
all_stu=len(pd.notnull(df['姓名']))
female_num=len(df[df['性别']=='女'])
male_num=len(df[df['性别']=='男'])
rate=female_num/all_stu #统计女生的占比
rank[name]=rate

##对字典从大到小排序
female_rank=sorted(rank.items(),key=lambda x:x[1],reverse=True)


#女生比例最多的前30个专业:
print("合师女生最多的前30个专业:\n")
for (i,j) in enumerate(female_rank):
if i>29:
break
print(i+1,j)

#男生比例最多的前30个专业:
male_rank=sorted(rank.items(),key=lambda x:x[1],reverse=False)

print("\n")
print("合师男生最多的前30个专业:\n")
for (i,j) in enumerate(male_rank):
if i>29:
break
print(i+1,j[0]," ",1-j[1])
合师女生最多的前30个专业:

1 ('学前教育(专升本)2班', 1.0)
2 ('视觉传达设计1班', 1.0)
3 ('学前教育(专升本)1班', 0.9893617021276596)
4 ('学前教育班', 0.975)
5 ('英语(师范)2班', 0.9746835443037974)
6 ('英语(专升本)1班', 0.958904109589041)
7 ('服装与服饰设计(D)班', 0.9473684210526315)
8 ('英语(翻译)班', 0.9466666666666667)
9 ('英语(翻译)1班', 0.9444444444444444)
10 ('国家卓越教师培养计划试点班', 0.9375)
11 ('西班牙语班', 0.9333333333333333)
12 ('英语(师范)班', 0.9325842696629213)
13 ('卓越统计师班', 0.9310344827586207)
14 ('英语(专升本)2班', 0.9305555555555556)
15 ('市场营销(D)班', 0.9295774647887324)
16 ('英语(师范)1班', 0.9090909090909091)
17 ('小学教育(卓越教师)班', 0.9056603773584906)
18 ('商务英语2班', 0.9025974025974026)
19 ('汉语言文学(师范)1班', 0.9)
20 ('舞蹈表演班', 0.9)
21 ('服装与服饰设计(D)1班', 0.896551724137931)
22 ('英语(翻译)2班', 0.8918918918918919)
23 ('汉语言文学(师范)2班', 0.88)
24 ('服装与服饰设计(D)2班', 0.8666666666666667)
25 ('商务英语3班', 0.8518518518518519)
26 ('学前教育(中美合作)班', 0.8508771929824561)
27 ('英语(中美合作)班', 0.8490566037735849)
28 ('英语(专升本)3班', 0.8484848484848485)
29 ('酒店管理(D)1班', 0.8395061728395061)
30 ('小学教育2班', 0.8333333333333334)


合师男生最多的前30个专业:

1 体育教育2班   1.0
2 计算机科学与技术(3+1)班   0.9464285714285714
3 电气工程及其自动化1班   0.9444444444444444
4 电气工程及其自动化2班   0.9411764705882353
5 电气工程及其自动化班   0.9043478260869565
6 体育教育班   0.9032258064516129
7 体育教育(D)2班   0.8907563025210083
8 光电科学与工程1班   0.8703703703703703
9 软件工程班   0.8452380952380952
10 微电子科学与工程班   0.8382352941176471
11 运动康复班   0.8333333333333334
12 光电科学与工程2班   0.8301886792452831
13 电子信息工程2班   0.829059829059829
14 计算机科学与技术班   0.8223140495867769
15 软件工程1班   0.8171428571428572
16 光电信息科学与工程班   0.8059701492537313
17 网络工程班   0.8033707865168539
18 软件工程2班   0.8024691358024691
19 计算机科学与技术(嵌入式应用技术)班   0.7887323943661972
20 电子信息工程班   0.7843137254901961
21 材料科学与工程班   0.7837837837837838
22 新能源材料与器件班   0.7676056338028169
23 运动训练4班   0.7647058823529411
24 通信工程1班   0.7515527950310559
25 程(3+1)班   0.75
26 计算机科学与技术(专升本)班   0.7323943661971831
27 通信工程2班   0.7236842105263157
28 生物技术2班   0.7216494845360825
29 中美合作办学)班   0.7142857142857143
30 电子信息工程(D)班   0.7096774193548387

看来程序员单身不是没有理由的....好像可以找到理由了 23333

女生身材分布散点图

1
2
women_data=data[data['性别']=='女']
women_data.describe()
png

png

从上面数据可以看出来我校女生的平均身高是162cm 体重是53kg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
w_h=list(women_data['身高'])
w_w=list(women_data['体重'])


for (i, h) in enumerate(w_h):
if h==0:
continue
bmi=w_w[i]/(h/100)**2
c='g'
if bmi>23.9:
c='r'
elif bmi<18:
c='y'
alpha=0.3
plt.scatter(h,w_w[i],color=c,alpha=alpha,marker='.')
plt.xlabel("cm")
plt.ylabel("kg")
plt.title("hfnu2017 female")
plt.show()

png 上图为女生身高体重分布的散点图,红色表示体重属于偏胖的,绿色表示正常的体重范围,黄色表示偏轻的,emmm从图中可以看出来大多数人都是属于比较健康的体重,三种人群大体上符合高斯分布,个别点离散程度比较大。。。女性身高主要集中在160到175这个范围内,女性体重主要集中在40到70这个范围内

男生身材分布散点图

1
2
3
man_data=data[data['性别']=='男']
man_data.describe()

png

png

从上面数据可以看出来我校男生的平均身高是174cm 体重是67kg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
w_h=list(man_data['身高'])
w_w=list(man_data['体重'])


for (i, h) in enumerate(w_h):
if h==0:
continue
bmi=w_w[i]/(h/100)**2
c='g'
if bmi>23.9:
c='r'
elif bmi<18:
c='y'
alpha=0.3
plt.scatter(h,w_w[i],color=c,alpha=alpha,marker='.')
plt.xlabel("cm")
plt.ylabel("kg")
plt.title("hfnu2017 male")
plt.show()
png

png

上图为男生身高体重分布的散点图,红色表示体重属于偏胖的,绿色表示正常的体重范围,黄色表示偏轻的,emmm从图中可以看出来大多数人都是属于比较健康的体重,个别点离散程度比较大。。。
男生身高主要集中在160到185这个范围内
男生体重主要集中在40到100这个范围内
男生看上去身材偏胖的人数比女生多很多,看来女生比男生更懂得控制饮食

有趣的名字

1
2
3
for i in women_data['姓名']:
if len(i)>3:
print(i)
王熊观鹭
马葛雨辰
胡何思淼
陈王永晴
完颜瑞杰
李彦青青
陈钱庭雅
韩李紫砚
吴叶静婷
周洪玉美
邱月雪娇
胡段彦云
孙琦淼慧
赵何振子

高频率的女生名字

1
2
3
4
5
6
7
8
def  get_name(x):
if type(x) is not str:
return ""
return x[1:]
new_women_data=women_data.copy()
new_women_data['姓名']=women_data['姓名'].map(lambda x:get_name(x))

new_women_data['姓名'].value_counts()
敏     91
婷婷    77
静     72
慧     71
颖     57
雪     54
倩     54
悦     51
洁     51
婷     51
文静    46
梦婷    41
丹丹    40
玲     39
晨     37
莹莹    37
娟     35
媛媛    34
晶晶    34
丽     33
倩倩    33
娜     32
璐     32
艳     30
玉     30
琪     29
燕     29
芳     28
雨     27
梅     26
      ..
家香     1
文萱     1
宇为     1
艳辉     1
聃琦     1
淑慧     1
来霞     1
亚辉     1
诗珣     1
晓娜     1
广英     1
怀秀     1
焓秋     1
林丽     1
学芳     1
钰琪     1
凯雯     1
金凤     1
柳婷     1
润蕾     1
亚荣     1
佳音     1
贤倩     1
贵霞     1
杨凡     1
月琴     1
美艳     1
杜芹     1
家秀     1
紫琪     1
Name: 姓名, Length: 4213, dtype: int64

上面是我校女孩名字的出现频率的统计,估计很多人都能找到自己。。。

统计学习问题

预测50米跑成绩

如果已知一个人完成了体测中除了50米跑的所有项目,能否通过已知数据来预测他50米跑的成绩

1
2
3
4
5
6
7
8
9
import numpy as np

train_data=man_data[man_data['50米跑'].notnull()]
feature=['身高','体重','肺活量','立定跳远','坐位体前屈','引体向上']
new_data=train_data[['身高','体重','肺活量','立定跳远','坐位体前屈','引体向上','50米跑']].copy()
new_data['引体向上']=train_data['引体向上'].fillna(0)
new_data=new_data.dropna()
train_x=new_data[feature].as_matrix()
train_y=new_data['50米跑'].as_matrix()
1
2
3
4
5
6
## 
from sklearn.ensemble import GradientBoostingRegressor

gdbt=GradientBoostingRegressor()
gdbt.fit(train_x,train_y)
gdbt.score(train_x,train_y)
0.34125920404733578

用gdbt拟合的结果最终的loss是0.34效果还可以.