一、摘要:

本项目通过对学生成绩信息读取和可视化来展现学生学业情况,并建立模型对排名进行预测。

二、选题背景:

学成成绩排名预测是一项非常重要的研究内容,本文针对学生成绩排名预测的问题,采用多元线性回归对学生成绩进行回归分析,得到的关于成绩排名的回归模型,能够有效的对学生的排名进行预测

三、数据说明:

成绩数据通过Excel表格函数批量生成。

 四、实施过程及代码:

1 import pandas as pd
2 import numpy as np
3 import matplotlib.pyplot as plt
4 plt.rcParams['font.sans-serif']=['SimHei']#这两句作用为防止中文乱码
5 plt.rcParams['axes.unicode_minus']=False
6 path = r'D:\program\逻辑回归录取预测\成绩表.xlsx'
7 data = pd.read_excel(path, sheet_name = '工作表1',usecols = [i for i in range(0,16)])
8 # data['列名称'] = 1
9 data.head()

成绩分析综合(E)python123 python做成绩分析_Data

1 print(len(data.index.values))
2 # 行索引 
3 print(data.index.values)
4 #  列数
5 print(len(data.columns.values))
6 #  列索引
7 print(data.columns.values)

成绩分析综合(E)python123 python做成绩分析_成绩分析综合(E)python123_02

查看每一门课程的平均分 ,通过观察柱状图可看出每个课程平均成绩均在74-76范围内,说明每门课学生掌握的程度和老师的教学质量无太大差别

1 course_name = data.columns.values[2:]
 2 course_score = []
 3 for name in course_name:
 4     sum = 0
 5     for score in data[name]:
 6         sum+=score
 7     course_score.append(sum/len(data[name]))
 8 print(course_score)
 9 plt.subplot(221)
10 plt.bar(course_name[:4], course_score[:4])
11 plt.tight_layout()
12 plt.title('课程平均分',fontsize=10)
13 plt.xlabel('课程')
14 plt.ylabel('平均分')
15 
16 plt.subplot(222)
17 plt.bar(course_name[4:7], course_score[4:7])
18 plt.tight_layout()
19 plt.title('课程平均分',fontsize=10)
20 plt.xlabel('课程')
21 plt.ylabel('平均分')
22 
23 plt.subplot(223)
24 plt.bar(course_name[7:9], course_score[7:9])
25 plt.tight_layout()
26 plt.title('课程平均分',fontsize=10)
27 plt.xlabel('课程')
28 plt.ylabel('平均分')
29 
30 plt.subplot(224)
31 plt.bar(course_name[9:11], course_score[9:11])
32 plt.tight_layout()
33 plt.title('课程平均分',fontsize=10)
34 plt.xlabel('课程')
35 plt.ylabel('平均分')
36 plt.show()

成绩分析综合(E)python123 python做成绩分析_线性回归_03

求出总分以便进行排名

1 org_score = []
 2 sum_score = []
 3 for i in range(len(data.index.values)):
 4     a = data.loc[i].values
 5     sum = 0
 6     for score in a[2:]:
 7         sum+=score
 8     org_score.append(sum)
 9     sum_score.append(sum)
10
1 org_score[:10]

成绩分析综合(E)python123 python做成绩分析_矩阵相乘_04

将求得的总分添加进成绩表格

1 data['总分'] = org_score
2 data.head()

成绩分析综合(E)python123 python做成绩分析_成绩分析综合(E)python123_05

对总分求均值,查看总分分布情况,通过观察趋势图可以看出学生成绩大致服从均值为1049的正态分布

1 sum_s = 0
 2 for i in org_score:
 3     sum_s+=i
 4 print(sum_s/len(data.index.values))
 5 xuhao = []
 6 pingjunfen = []
 7 for i in range(len(data.index.values)):
 8     xuhao.append(i+1)
 9     pingjunfen.append(sum_s/len(data.index.values))
10 print(len(xuhao))
11 print(len(pingjunfen))

成绩分析综合(E)python123 python做成绩分析_成绩分析综合(E)python123_06

 

1 fig,ax = plt.subplots()
2 ax.scatter(xuhao,pingjunfen,color='r')
3 ax.plot(xuhao,org_score,color='y')
4 plt.title('学生平均分分布')
5 plt.legend(('个人平均分','总体平均分'),loc='upper left')
6 plt.show()

成绩分析综合(E)python123 python做成绩分析_矩阵相乘_07

计算排名并添加进表格

1 #对总分进行从高到低排序
2 sum_score.sort(reverse=True)
3 sum_score[:20]

成绩分析综合(E)python123 python做成绩分析_Data_08

1 score_list = []
2 rank = []
3 for i in range(1,len(data.index.values)+1):
4     rank.append(i)
1 rank[:20]

成绩分析综合(E)python123 python做成绩分析_线性回归_09

1 len(rank)

成绩分析综合(E)python123 python做成绩分析_线性回归_10

1 len(sum_score)

成绩分析综合(E)python123 python做成绩分析_线性回归_11

1 for i in range(len(sum_score)):#得到分数与对应排名的表格
2     score_list.append(sum_score[i])
3     score_list.append(rank[i])
1 score_list[:20]

成绩分析综合(E)python123 python做成绩分析_Data_12

1 len(score_list)

成绩分析综合(E)python123 python做成绩分析_线性回归_13

1 paiming = []#存放排名信息
2 for i in range(len(org_score)):
3     if org_score[i] in score_list:
4         paiming.append(score_list[score_list.index(org_score[i])+1])
1 paiming

成绩分析综合(E)python123 python做成绩分析_矩阵相乘_14

1 len(paiming)

 

成绩分析综合(E)python123 python做成绩分析_Data_15

1 data['排名'] = paiming[:2029]#将排名信息添加进表格
2 data.head()

成绩分析综合(E)python123 python做成绩分析_矩阵相乘_16

1 path = r'D:\program\逻辑回归录取预测\成绩表-排名.xlsx'
2 pd.DataFrame(data).to_excel(path, sheet_name='Sheet1', index=False, header=True)#保存修改后的表格

建立线性回归函数,进行训练和预测

1 final_org = []
2 for i in sum_score:
3     final_org.append([i])
1 final_org

成绩分析综合(E)python123 python做成绩分析_成绩分析综合(E)python123_17

1 #定义线性回归函数
 2 '''
 3 线性回归算法
 4 '''
 5 class LinearRegression_1():
 6     def __init__(self):              #1.新建变量
 7         self.w = None
 8  
 9     def fit(self, X, y):              #2.训练集的拟合
10         X = np.insert(X, 0, 1, axis=1)   #增加一个维度
11 #         print (X.shape)        
12         X_ = np.linalg.inv(X.T.dot(X))   #公式:求X的转置(.T)与X矩阵相乘(.dot(X)),再求其逆矩阵(np.linalg.inv())
13         self.w = X_.dot(X.T).dot(y)      #上述公式与X的转置进行矩阵相乘,再与y进行矩阵相乘
14  
15     def predict(self, X):             #3.测试集的测试反馈
16         X = np.insert(X, 0, 1, axis=1)    #增加一个维度
17         y_pred = X.dot(self.w)            #X与self.w所表示的矩阵相乘         
18         return y_pred
1 #画出排名和成绩对应的变化趋势图。可以看出大概在950-1100的范围其趋势图接近一条直线
2 fig,ax = plt.subplots()
3 ax.scatter(sum_score,rank)
4 plt.title('Real Data')
5 plt.legend(('Data Points','Data Points'),loc='upper right')
6 plt.xlabel('分数')
7 plt.ylabel('排名')
8 plt.show()

成绩分析综合(E)python123 python做成绩分析_矩阵相乘_18

1 #确认训练数据和测试数据
2 paiming_train = rank[200:1200]
3 score_train = sum_score[200:1200]
4 paiming_real = rank[1200:1800]
5 score_test = final_org[1200:1800]
1 #确认训练数据和测试数据
2 paiming_train_1 = rank[200:1200]
3 score_train_1 = final_org[200:1200]
4 paiming_real_1 = rank[1200:1800]
5 score_test_1 = final_org[1200:1800]
1 r = LinearRegression_1()#建立线性回归模型
2 r.fit(score_train_1,paiming_train_1)#训练
3 paiming_test = r.predict(score_test_1)#将测试数据放入模型进行预测
1 #画出实际数据与预测数据的趋势图,可以看出在分数990-1040区间实际与预测值大致相同
2 fig,ax = plt.subplots()
3 ax.plot(score_test,paiming_test,color='r')
4 ax.scatter(score_test,paiming_real,color='b')
5 plt.legend(('LinearRegressionl','Real Data'),loc='upper right')
6 plt.xlabel('score')
7 plt.ylabel('rank')
8 plt.show()

成绩分析综合(E)python123 python做成绩分析_线性回归_19

上述线性回归模型只在大部分区间使用,为了顾及更多数据我们调整容量即使用二次函数来进行拟合,二次函数拟合的准确率大于刚才的一次函数模型,可以覆盖更多的区间

1 import numpy as np
 2 import matplotlib.pyplot as plt
 3 from sklearn.linear_model import LinearRegression
 4 from sklearn.linear_model import Lasso
 5 from sklearn.linear_model import Ridge
 6 x_data = np.array(sum_score)
 7 y_data = np.array(rank) 
 8 x_data = x_data.reshape(-1,1)
 9 y_data = y_data.reshape(-1,1)
10 X2 = np.hstack([x_data ** 3,x_data ** 2, x_data])
11 print(X2.shape)
12 model = LinearRegression()  # 线性回归
13 model.fit(X2,y_data)
14 y_pre = model.predict(X2)
15 t = np.arange(len(x_data))
16 print(model.coef_)
17 print(model.intercept_)
18 print(model.score(X2 ,y_data))
19 plt.plot(x_data,y_pre,color='r')
20 plt.scatter(x_data, y_data)
21 plt.legend(('Pridict','Data Points'),loc='upper right')
22 plt.show()

成绩分析综合(E)python123 python做成绩分析_线性回归_20

完整代码:

1 import pandas as pd
  2 import numpy as np
  3 import matplotlib.pyplot as plt
  4 plt.rcParams['font.sans-serif']=['SimHei']#这两句作用为防止中文乱码
  5 plt.rcParams['axes.unicode_minus']=False
  6 path = r'D:\program\逻辑回归录取预测\成绩表.xlsx'
  7 data = pd.read_excel(path, sheet_name = '工作表1',usecols = [i for i in range(0,16)])
  8 # data['列名称'] = 1
  9 data.head()
 10 
 11 print(len(data.index.values))
 12 # 行索引 
 13 print(data.index.values)
 14 #  列数
 15 print(len(data.columns.values))
 16 #  列索引
 17 print(data.columns.values)
 18 
 19 
 20 course_name = data.columns.values[2:]
 21 course_score = []
 22 for name in course_name:
 23     sum = 0
 24     for score in data[name]:
 25         sum+=score
 26     course_score.append(sum/len(data[name]))
 27 print(course_score)
 28 plt.subplot(221)
 29 plt.bar(course_name[:4], course_score[:4])
 30 plt.tight_layout()
 31 plt.title('课程平均分',fontsize=10)
 32 plt.xlabel('课程')
 33 plt.ylabel('平均分')
 34 
 35 plt.subplot(222)
 36 plt.bar(course_name[4:7], course_score[4:7])
 37 plt.tight_layout()
 38 plt.title('课程平均分',fontsize=10)
 39 plt.xlabel('课程')
 40 plt.ylabel('平均分')
 41 
 42 plt.subplot(223)
 43 plt.bar(course_name[7:9], course_score[7:9])
 44 plt.tight_layout()
 45 plt.title('课程平均分',fontsize=10)
 46 plt.xlabel('课程')
 47 plt.ylabel('平均分')
 48 
 49 plt.subplot(224)
 50 plt.bar(course_name[9:11], course_score[9:11])
 51 plt.tight_layout()
 52 plt.title('课程平均分',fontsize=10)
 53 plt.xlabel('课程')
 54 plt.ylabel('平均分')
 55 plt.show()
 56 
 57 org_score = []
 58 sum_score = []
 59 for i in range(len(data.index.values)):
 60     a = data.loc[i].values
 61     sum = 0
 62     for score in a[2:]:
 63         sum+=score
 64     org_score.append(sum)
 65     sum_score.append(sum)
 66     
 67 
 68 org_score[:10]
 69 
 70 data['总分'] = org_score
 71 data.head()
 72 
 73 sum_s = 0
 74 for i in org_score:
 75     sum_s+=i
 76 print(sum_s/len(data.index.values))
 77 xuhao = []
 78 pingjunfen = []
 79 for i in range(len(data.index.values)):
 80     xuhao.append(i+1)
 81     pingjunfen.append(sum_s/len(data.index.values))
 82 print(len(xuhao))
 83 print(len(pingjunfen))
 84 
 85 fig,ax = plt.subplots()
 86 ax.scatter(xuhao,pingjunfen,color='r')
 87 ax.plot(xuhao,org_score,color='y')
 88 plt.title('学生平均分分布')
 89 plt.legend(('个人平均分','总体平均分'),loc='upper left')
 90 plt.show()
 91 
 92 #对总分进行从高到低排序
 93 sum_score.sort(reverse=True)
 94 sum_score[:20]
 95 
 96 score_list = []
 97 rank = []
 98 for i in range(1,len(data.index.values)+1):
 99     rank.append(i)
100 
101 rank[:20]
102 
103 len(rank)
104 
105 len(sum_score)
106 
107 for i in range(len(sum_score)):#得到分数与对应排名的表格
108     score_list.append(sum_score[i])
109     score_list.append(rank[i])
110 
111 score_list[:20]
112 
113 len(score_list)
114 
115 paiming = []#存放排名信息
116 for i in range(len(org_score)):
117     if org_score[i] in score_list:
118         paiming.append(score_list[score_list.index(org_score[i])+1])
119 
120 paiming
121 
122 len(paiming)
123 
124 data['排名'] = paiming[:2029]#将排名信息添加进表格
125 data.head()
126 
127 path = r'D:\program\逻辑回归录取预测\成绩表-排名.xlsx'
128 pd.DataFrame(data).to_excel(path, sheet_name='Sheet1', index=False, header=True)#保存修改后的表格
129 
130 final_org = []
131 for i in sum_score:
132     final_org.append([i])
133 
134 final_org
135 
136 #定义线性回归函数
137 '''
138 线性回归算法
139 '''
140 class LinearRegression_1():
141     def __init__(self):              #1.新建变量
142         self.w = None
143  
144     def fit(self, X, y):              #2.训练集的拟合
145         X = np.insert(X, 0, 1, axis=1)   #增加一个维度
146 #         print (X.shape)        
147         X_ = np.linalg.inv(X.T.dot(X))   #公式:求X的转置(.T)与X矩阵相乘(.dot(X)),再求其逆矩阵(np.linalg.inv())
148         self.w = X_.dot(X.T).dot(y)      #上述公式与X的转置进行矩阵相乘,再与y进行矩阵相乘
149  
150     def predict(self, X):             #3.测试集的测试反馈
151         X = np.insert(X, 0, 1, axis=1)    #增加一个维度
152         y_pred = X.dot(self.w)            #X与self.w所表示的矩阵相乘         
153         return y_pred
154 
155 #画出排名和成绩对应的变化趋势图。可以看出大概在950-1100的范围其趋势图接近一条直线
156 fig,ax = plt.subplots()
157 ax.scatter(sum_score,rank)
158 plt.title('Real Data')
159 plt.legend(('Data Points','Data Points'),loc='upper right')
160 plt.xlabel('分数')
161 plt.ylabel('排名')
162 plt.show()
163 
164 #确认训练数据和测试数据
165 paiming_train = rank[200:1200]
166 score_train = sum_score[200:1200]
167 paiming_real = rank[1200:1800]
168 score_test = final_org[1200:1800]
169 
170 #确认训练数据和测试数据
171 paiming_train_1 = rank[200:1200]
172 score_train_1 = final_org[200:1200]
173 paiming_real_1 = rank[1200:1800]
174 score_test_1 = final_org[1200:1800]
175 
176 r = LinearRegression_1()#建立线性回归模型
177 r.fit(score_train_1,paiming_train_1)#训练
178 paiming_test = r.predict(score_test_1)#将测试数据放入模型进行预测
179 
180 #画出实际数据与预测数据的趋势图,可以看出在分数990-1040区间实际与预测值大致相同
181 fig,ax = plt.subplots()
182 ax.plot(score_test,paiming_test,color='r')
183 ax.scatter(score_test,paiming_real,color='b')
184 plt.legend(('LinearRegressionl','Real Data'),loc='upper right')
185 plt.xlabel('score')
186 plt.ylabel('rank')
187 plt.show()
188 
189 import numpy as np
190 import matplotlib.pyplot as plt
191 from sklearn.linear_model import LinearRegression
192 from sklearn.linear_model import Lasso
193 from sklearn.linear_model import Ridge
194 x_data = np.array(sum_score)
195 y_data = np.array(rank) 
196 x_data = x_data.reshape(-1,1)
197 y_data = y_data.reshape(-1,1)
198 X2 = np.hstack([x_data ** 3,x_data ** 2, x_data])
199 print(X2.shape)
200 model = LinearRegression()  # 线性回归
201 model.fit(X2,y_data)
202 y_pre = model.predict(X2)
203 t = np.arange(len(x_data))
204 print(model.coef_)
205 print(model.intercept_)
206 print(model.score(X2 ,y_data))
207 plt.plot(x_data,y_pre,color='r')
208 plt.scatter(x_data, y_data)
209 plt.legend(('Pridict','Data Points'),loc='upper right')
210 plt.show()

五、总结:

针对学生成绩进行了一元线性回归分析和多元线性回归,通过拟合曲线可得知成绩与排名的关系更加符合多元线性回归模型。使用该预测模型可在得知学生总分的情况下大致的预测出学生排名。