Python學生成績數據可視化與排名預測


一、摘要:

本項目通過對學生成績信息讀取和可視化來展現學生學業情況,並建立模型對排名進行預測。

二、選題背景:

學成成績排名預測是一項非常重要的研究內容,本文針對學生成績排名預測的問題,采用多元線性回歸對學生成績進行回歸分析,得到的關於成績排名的回歸模型,能夠有效的對學生的排名進行預測

三、數據說明:

成績數據通過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()

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)

查看每一門課程的平均分 ,通過觀察柱狀圖可看出每個課程平均成績均在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()

求出總分以便進行排名

 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]

將求得的總分添加進成績表格

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

對總分求均值,查看總分分布情況,通過觀察趨勢圖可以看出學生成績大致服從均值為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))

 

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()

計算排名並添加進表格

1 #對總分進行從高到低排序
2 sum_score.sort(reverse=True)
3 sum_score[:20]

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

1 len(rank)

1 len(sum_score)

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]

1 len(score_list)

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

1 len(paiming)

 

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

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

 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()

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()

上述線性回歸模型只在大部分區間使用,為了顧及更多數據我們調整容量即使用二次函數來進行擬合,二次函數擬合的准確率大於剛才的一次函數模型,可以覆蓋更多的區間

 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()

完整代碼:

  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()

五、總結:

針對學生成績進行了一元線性回歸分析和多元線性回歸,通過擬合曲線可得知成績與排名的關系更加符合多元線性回歸模型。使用該預測模型可在得知學生總分的情況下大致的預測出學生排名。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM