东南大学青年大学习统计

运行截图

image.png

环境安装

  • 你可以按照下面的方式下载代码到本地

    1
    git clone --depth 1 https://github.com/huzai9527/studyAnalysis.git SUSmember-dev
  • 本项目在python 3 下运行,并且依赖pands,你可以在终端运行以下命令进行安装

    1
    pip install pandas

所需要的文件以及格式

  • 本院总名单,按照如下格式,首行为班级名称,首列为索引号(excel自带),将班级同学名字替换即可
    image.png
  • 班级累计分数:首行为列名第一列列名空,第二列列名累计分数
  • 第一列为填班级名,第二列为保存的班级名
    image.png
  • 最后是大学习的统计情况,此文件是上级下发的,只要移到此目录即可
    image.png
  • 注: 总名单以及班级累计分数可以在下载好的文件中直接修改

    安装好环境以及准备好相应文件后,在终端运行(文件目录路径下)

    1
    python SUSmember.py 无锡分校-东南-第十一期
  • 运行完成输出,各班详细情况,并在结果文件夹生成EXCELL统计文件
    image.png

有不是团员的只要在总名单中删除即可

数据分析—-数据清洗

一、导入数据

1
2
3
4
import pandas as pd
import numpy as np
from pandas import Series,DataFrame
import xlrd
1
2
df = DataFrame(pd.read_excel('datas/grades.xlsx')) 
print(df)
   Unnamed: 0  Unnamed: 1  Unnamed: 2  Unnamed: 3
0         蒋广佳        43.0        69.0        61.0
1          廖菲        80.0        64.0        62.0
2         沈秀玲        68.0        74.0        98.0
3          韦丹        48.0        53.0        64.0
4         张梦雅        72.0        73.0        96.0
5         赵雅欣        60.0         NaN        70.0
6         曹海广        74.0        60.0        20.0
7         陈泽灿        38.0        21.0        92.0
8         NaN        88.0        67.0        84.0
9         高海亮        86.0        74.0        96.0
10        顾晓冬        84.0        60.0        90.0
11        侯星宇        64.0       111.0         NaN
12        江宜哲        60.0        33.0        70.0
13        NaN         NaN         NaN         NaN
14        梁杨杨        68.0        54.0        94.0
15         刘辉         NaN        63.0        98.0
16        罗嘉豪        39.0        44.0        56.0
17        施亚君        90.0        63.0        90.0
18         孙添        64.0        63.0        78.0
19         王杰        74.0         NaN        76.0
20         王泽        52.0        48.0        94.0
21        NaN        60.0        69.0        74.0
22        杨福程        70.0        49.0        76.0
23        尤澳晨        91.0        67.0        86.0
24         翟佳        78.0        73.0        88.0
25         张旭       100.0        60.0        98.0
26        支星哲        80.0        63.0       100.0
27        邹湘涛        54.0        40.0        90.0
  • 我们可以看见上面的数据是缺少标注的,列名缺少标注;并且有很多是空值,因此我们要对数据进行清洗,提高数据的质量。在这里数据清洗有四个要点简称“完全合一”
    • 整性:单条数据是否完整,统计的字段是否完善。
    • 面性:观察某一列的全部数值,选中一列,我们可以看到最大值,最小值,平均值。我们可以通过常识判断数据是否合理,比如:数据定义、单位标识、数值本身。
    • 法性:数据的类型、内容、大小的合法性。比如数据中存在非ASCII字符,性别存在未知,总分超过100等。
    • 性:数据是否存在重复记录,由于数据来源于不同的渠道,重复的情况是非常常见的。行数据、列数据都需要是唯一的。
  • 事实上数据清洗的标准有差不多七八条,有兴趣的可以了解一下,这里归纳为“完全合一”四条,按照这四条基本上可以解决数据清洗中的大部分问题,使得数据标准、干净、连续

二、开始数据清洗

1、完整性

problem 1:空行

  • solution: 删除
1
df.dropna(how="all",inplace=True)

problem 2:缺失值

  • solution:
    • 删除:删除数据缺失的记录
    • 均值:使用当前列的均值
    • 高频:使用当前列出现平率最高的数据
  • 首先我们先把列的标注补上
1
df = df.rename(columns={'Unnamed: 0':'index','Unnamed: 1':'math','Unnamed: 2':'english','Unnamed: 3':'c++'})
1
df = df.drop(columns='index')
1
print(df)
     math  english    c++
0    43.0     69.0   61.0
1    80.0     64.0   62.0
2    68.0     74.0   98.0
3    48.0     53.0   64.0
4    72.0     73.0   96.0
5    60.0      NaN   70.0
6    74.0     60.0   20.0
7    38.0     21.0   92.0
8    88.0     67.0   84.0
9    86.0     74.0   96.0
10   84.0     60.0   90.0
11   64.0    111.0    NaN
12   60.0     33.0   70.0
14   68.0     54.0   94.0
15    NaN     63.0   98.0
16   39.0     44.0   56.0
17   90.0     63.0   90.0
18   64.0     63.0   78.0
19   74.0      NaN   76.0
20   52.0     48.0   94.0
21   60.0     69.0   74.0
22   70.0     49.0   76.0
23   91.0     67.0   86.0
24   78.0     73.0   88.0
25  100.0     60.0   98.0
26   80.0     63.0  100.0
27   54.0     40.0   90.0
  • 现在我们想对df[‘math’]中缺失的值用平均值代替
1
df['math'].fillna(df['math'].mean(),inplace=True)
1
print(df)
          math  english    c++
0    43.000000     69.0   61.0
1    80.000000     64.0   62.0
2    68.000000     74.0   98.0
3    48.000000     53.0   64.0
4    72.000000     73.0   96.0
5    60.000000      NaN   70.0
6    74.000000     60.0   20.0
7    38.000000     21.0   92.0
8    88.000000     67.0   84.0
9    86.000000     74.0   96.0
10   84.000000     60.0   90.0
11   64.000000    111.0    NaN
12   60.000000     33.0   70.0
13   68.653846      NaN    NaN
14   68.000000     54.0   94.0
15   68.653846     63.0   98.0
16   39.000000     44.0   56.0
17   90.000000     63.0   90.0
18   64.000000     63.0   78.0
19   74.000000      NaN   76.0
20   52.000000     48.0   94.0
21   60.000000     69.0   74.0
22   70.000000     49.0   76.0
23   91.000000     67.0   86.0
24   78.000000     73.0   88.0
25  100.000000     60.0   98.0
26   80.000000     63.0  100.0
27   54.000000     40.0   90.0
  • 如果想用最高频率的数据对english进行填充,可以通过value_counts获取math字段最高频次english_maxf,然后对其进行填充
1
english_maxf = df['english'].value_counts().index[0]
1
df['english'].fillna(english_maxf,inplace=True)
1
print(df)
          math  english    c++
0    43.000000     69.0   61.0
1    80.000000     64.0   62.0
2    68.000000     74.0   98.0
3    48.000000     53.0   64.0
4    72.000000     73.0   96.0
5    60.000000     63.0   70.0
6    74.000000     60.0   20.0
7    38.000000     21.0   92.0
8    88.000000     67.0   84.0
9    86.000000     74.0   96.0
10   84.000000     60.0   90.0
11   64.000000    111.0    NaN
12   60.000000     33.0   70.0
13   68.653846     63.0    NaN
14   68.000000     54.0   94.0
15   68.653846     63.0   98.0
16   39.000000     44.0   56.0
17   90.000000     63.0   90.0
18   64.000000     63.0   78.0
19   74.000000     63.0   76.0
20   52.000000     48.0   94.0
21   60.000000     69.0   74.0
22   70.000000     49.0   76.0
23   91.000000     67.0   86.0
24   78.000000     73.0   88.0
25  100.000000     60.0   98.0
26   80.000000     63.0  100.0
27   54.000000     40.0   90.0

2、全面性

problem:列数据单位不统一

solution:将不同的单位的找出来,将其进行迭代替换,比如说将榜(lbs)转化为千克(kgs)

1
2
3
4
5
6
7
8
# 获取 weight 数据列中单位为 lbs 的数据
rows_with_lbs = df['weight'].str.contains('lbs').fillna(False)
print df[rows_with_lbs]
# 将 lbs 转换为 kgs, 2.2lbs=1kgs
for i,lbs_row in df[rows_with_lbs].iterrows():
# 截取从头开始到倒数第三个字符之前,即去掉 lbs。
weight = int(float(lbs_row['weight'][:-3])/2.2)
df.at[i,'weight'] = '{}kgs'.format(weight)

3、合理性

problem:非ASCII字符

solution:对于非ASCII字符,我们可以采用删除或者替换的方式,我们直接选择删除

1
df['name'].replace({r'[^\x00-\x7f]+':''},regex=True,inplace=True)

4、唯一性

problem1:一列有多个参数

solution:比如英文名字,是有两部分组成的,包含两个参数Firstname、Lastnamr,我们需要将name一列拆分为Firstname和Lastname两个字段,我们可以采用split方法,对其进行切分

1
2
df['First_namr','Last_name'] = df['name'].str.split(expand=True)
df.drop('name',axis=1,inplace=True)

problem2:重读数据

solution:我们校验数据是否存在重复数据,如果有重复数据,如果就用pandas提供的drop_duplicates()来删除重复数据。

1
df.drop_duplicates(['First_name','Last_name'],inplace=True)

数据分析—-pandas

核心数据结构 Series & DataFrame

1
2
3
import pandas as pd
import numpy as np
from pandas import Series, DataFrame

Series是一个定长的字典序列,它有两个基本属性index 、 value index 默认是 0 ,1,2,3 递增的,也可以自己指定索引 index=[‘a’, ‘b’, ‘c’]

创建Series的三种方式

1
2
3
4
5
6
7
x1 = Series([1,2,3,4])
x2 = Series(data=[1,2,3,4],index=['a','b','c','d'])
dic = {'a':1,'b':2,'c':3,'d':4}
x3 = Series(dic)
print(x1)
print(x2)
print(x3)
0    1
1    2
2    3
3    4
dtype: int64
a    1
b    2
c    3
d    4
dtype: int64
a    1
b    2
c    3
d    4
dtype: int64

DataFrame类似数据库中的表,可以将其看成是由有相同的索引的Series组成

创建DataFra几种方式

1
2
3
data = {"chinese":[90,80,70,60,50],'math':[70,80,70,90,60],'english':[30,50,70,80,60]}
df1 = DataFrame(data=data,index=['zhangfei','guanyu','zhaoyun','huangzhong','machao'])
print(df)
            chinese  english  math
zhangfei         90       30    70
guanyu           80       50    80
zhaoyun          70       70    70
huangzhong       60       80    90
machao           50       60    60
1
2
3
import xlrd
df2 = DataFrame(pd.read_excel('datas/grades.xlsx'))
df2 = df2.drop_duplicates()
1
print(df2)
     姓名   高数  英语  C++
0   蒋广佳   43  69   61
1    廖菲   80  64   62
2   沈秀玲   68  74   98
3    韦丹   48  53   64
4   张梦雅   72  73   96
5   赵雅欣   60  63   70
6   曹海广   74  60   20
7   陈泽灿   38  21   92
8    邓杰   88  67   84
9   高海亮   86  74   96
10  顾晓冬   84  60   90
11  侯星宇   64  69   96
12  江宜哲   60  33   70
13  李洪汀   76  56   84
14  梁杨杨   68  54   94
15   刘辉   68  63   98
16  罗嘉豪   39  44   56
17  施亚君   90  63   90
18   孙添   64  63   78
19   王杰   74  60   76
20   王泽   52  48   94
21  徐孟圆   60  69   74
22  杨福程   70  49   76
23  尤澳晨   91  67   86
24   翟佳   78  73   88
25   张旭  100  60   98
26  支星哲   80  63  100
27  邹湘涛   54  40   90

数据清洗

删除不必要的行或列

1
2
3
#删除行
df2 = df2.drop(columns=['姓名'])
print(df2)
     高数  英语  C++
0    43  69   61
1    80  64   62
2    68  74   98
3    48  53   64
4    72  73   96
5    60  63   70
6    74  60   20
7    38  21   92
8    88  67   84
9    86  74   96
10   84  60   90
11   64  69   96
12   60  33   70
13   76  56   84
14   68  54   94
15   68  63   98
16   39  44   56
17   90  63   90
18   64  63   78
19   74  60   76
20   52  48   94
21   60  69   74
22   70  49   76
23   91  67   86
24   78  73   88
25  100  60   98
26   80  63  100
27   54  40   90
1
2
3
#删除列
df2 = df2.drop(index = [27])
print(df2)
     高数  英语  C++
0    43  69   61
1    80  64   62
2    68  74   98
3    48  53   64
4    72  73   96
5    60  63   70
6    74  60   20
7    38  21   92
8    88  67   84
9    86  74   96
10   84  60   90
11   64  69   96
12   60  33   70
13   76  56   84
14   68  54   94
15   68  63   98
16   39  44   56
17   90  63   90
18   64  63   78
19   74  60   76
20   52  48   94
21   60  69   74
22   70  49   76
23   91  67   86
24   78  73   88
25  100  60   98
26   80  63  100

重命名列名

1
df2 = df2.rename(columns={'高数':'math','英语':'english'})

去除重复的值

1
df2 = df2.drop_duplicates()

更改数据格式

1
2
df2['math'] = df2['math'].astype('str')
#df2['math'].astype(np.int64)

清除数据间的空格

1
2
df2['math'] = df2['math'].map(str.strip) #删除左右两边的空格
df2['math'] = df2['math'].map(str.lstrip) #删除左边的空格(str.rstrip 右边的空格)

删除指定字符

1
df2['math'] = df2['math'].str.strip('$')

大小写转换

1
df2.columns = df2.columns.str.upper() #全部大写(lower()全部小写 title()首字母大写)
1
df2















































































































































































MATH ENGLISH C++
0 43 69 61
1 80 64 62
2 68 74 98
3 48 53 64
4 72 73 96
5 60 63 70
6 74 60 20
7 38 21 92
8 88 67 84
9 86 74 96
10 84 60 90
11 64 69 96
12 60 33 70
13 76 56 84
14 68 54 94
15 68 63 98
16 39 44 56
17 90 63 90
18 64 63 78
19 74 60 76
20 52 48 94
21 60 69 74
22 70 49 76
23 91 67 86
24 78 73 88
25 100 60 98
26 80 63 100

使用apply函数对数据进行清洗

1
2
3
#df2['MATH'] = df2['MATH'].apply(str.lower)
df2['MATH'] = df2['MATH'].astype(np.int64)
df2















































































































































































MATH ENGLISH C++
0 43 69 61
1 80 64 62
2 68 74 98
3 48 53 64
4 72 73 96
5 60 63 70
6 74 60 20
7 38 21 92
8 88 67 84
9 86 74 96
10 84 60 90
11 64 69 96
12 60 33 70
13 76 56 84
14 68 54 94
15 68 63 98
16 39 44 56
17 90 63 90
18 64 63 78
19 74 60 76
20 52 48 94
21 60 69 74
22 70 49 76
23 91 67 86
24 78 73 88
25 100 60 98
26 80 63 100

1
2
3
4
def plus(df):
df['Total'] = df['MATH']+df['ENGLISH']+df['C++']
return df
df2 = df2.apply(plus,axis=1)
1
print(df2)
    MATH  ENGLISH  C++  Total
0     43       69   61    173
1     80       64   62    206
2     68       74   98    240
3     48       53   64    165
4     72       73   96    241
5     60       63   70    193
6     74       60   20    154
7     38       21   92    151
8     88       67   84    239
9     86       74   96    256
10    84       60   90    234
11    64       69   96    229
12    60       33   70    163
13    76       56   84    216
14    68       54   94    216
15    68       63   98    229
16    39       44   56    139
17    90       63   90    243
18    64       63   78    205
19    74       60   76    210
20    52       48   94    194
21    60       69   74    203
22    70       49   76    195
23    91       67   86    244
24    78       73   88    239
25   100       60   98    258
26    80       63  100    243

pandas中常用的统计函数

1.jpg

1
print(df2.describe())
             MATH    ENGLISH         C++       Total
count   27.000000  27.000000   27.000000   27.000000
mean    69.444444  59.703704   81.148148  210.296296
std     16.113380  12.406000   17.933003   34.410212
min     38.000000  21.000000   20.000000  139.000000
25%     60.000000  55.000000   72.000000  193.500000
50%     70.000000  63.000000   86.000000  216.000000
75%     80.000000  68.000000   95.000000  239.500000
max    100.000000  74.000000  100.000000  258.000000
1
2


数据分析—numpy

1
2
import pandas as pd
import numpy as np

创建普通数组

1
2
a = np.array([1,2,3])
b = np.array([[1,2,3],[4,5,6],[7,8,9]])
1
b[1,1] = 10
1
2
3
4
print(a.shape)
print(b.shape)
print(a.dtype)
print(b)
(3,)
(3, 3)
int64
[[1 2 3]
 [4 5 6]
 [7 8 9]]

创建结构数组

1
2
3
4
5
6
7
personalType = np.dtype({
'names':['name','age','chinese','math','english'],
'formats':['S25','i','i','i','f']
})
students = np.array([("huzai",22,99,99,99.5),("huzai",22,99,99,99.5)],dtype=personalType)
age = students[:]['age']
print(np.mean(age))
22.0
1
print(students)
[(b'huzai', 22, 99, 99, 99.5) (b'huzai', 22, 99, 99, 99.5)]

创建连续数组

1
2
x1 = np.arange(1,11,2) #步长为2,从1开始的等差数组(不包括终值)
x2 = np.linspace(1,9,5) #将1-9分成5块,结果如上
1
2
print(x1)
print(x2)
[1 3 5 7 9]
[1. 3. 5. 7. 9.]

数组间的算数运算

1
2
3
4
print(np.add(x1,x2))
print(np.subtract(x1,x2))
print(np.multiply(x1,x2))
print(np.divide(x1,x2))
[ 2.  6. 10. 14. 18.]
[0. 0. 0. 0. 0.]
[ 1.  9. 25. 49. 81.]
[1. 1. 1. 1. 1.]

统计函数

数组中的最值 np.amin() amax()

1
2
3
4
a = np.array([[1,3,7],[2,5,8],[6,4,9]])
print(np.amin(a))
print(np.amin(a,0)) #每一列的最小值
print(np.amin(a,1)) #每行的最小值
1
[1 3 7]
[1 2 4]

统计最大值与最小值之差 ptp()

1
2
3
print(np.ptp(a))
print(np.ptp(a,0)) #每列最大值与最小值的差
print(np.ptp(a,1)) #每行最大值与最小值的差
8
[5 2 2]
[6 6 5]

统计数组的百分位数 percentile(a, p, axis) a:数组名 p 代表百分比 axis代表是行还是列

1
2
3
print(np.percentile(a,50))
print(np.percentile(a,50,0))
print(np.percentile(a,50,1))
5.0
[2. 4. 8.]
[3. 5. 6.]

统计数组中的中位数以及平均数 median() mean()

1
2
3
print(np.median(a))
print(np.median(a,0))
print(np.median(a,1))
5.0
[2. 4. 8.]
[3. 5. 6.]

数组中的加权平均值 average(a,weights)

1
2
3
4
b = np.array([1,2,3,4])
wts = np.array([1,2,3,4])
print(np.average(b))
print(np.average(b,weights=wts))
2.5
3.0

统计数组中的标准差(std())与方差(var())

1
2
print(np.std(b))
print(np.var(b))
1.118033988749895
1.25

Numpy排序

1
2
3
print(a)
print(np.sort(a))
print(np.sort(a,0))
[[1 3 7]
 [2 5 8]
 [6 4 9]]
[[1 3 7]
 [2 5 8]
 [4 6 9]]
[[1 3 7]
 [2 4 8]
 [6 5 9]]

作业题

1
2
3
4
5
6
st_type = np.dtype({
'names':['name','chinese','english','math'],
'formats':['S25','i','i','i']
})
grades = np.array([('zhangfei',66,65,30),('guanyu',95,85,98),('zhaoyun',93,92,96),('huangzhong',90,88,77),
('dianwei',80,90,90)],dtype=st_type)
1
print(grades)
[(b'zhangfei', 66, 65, 30) (b'guanyu', 95, 85, 98)
 (b'zhaoyun', 93, 92, 96) (b'huangzhong', 90, 88, 77)
 (b'dianwei', 80, 90, 90)]
1
2
3
4
chinese = grades[:]['chinese'] 
english = grades[:]['english']
math = grades[:]['math']
total = np.add(chinese,english,math)
1
print(total)
[131 180 185 178 170]
1
c_a,e_a,m_a = np.average(chinese),np.average(english),np.average(math)
1
print(c_a)
84.8
1
2