實踐-彙總大量EXCEL-Pandas
1.背景介紹
寫這篇文章出於兩個目的:
第一:肯定是想介紹一下標題的方法。
第二:想嘗試着用markdown來寫博客,順便學習一下這個工具。
背景:
最近我導師要我幫忙在學習通上,導出他教的某兩個課程(一個理論,一個實驗)的各8次作業成績表和8次簽到表,1次期中成績,1次期末成績。也就是 實驗課 有18張表彙總成一個統計表, 理論課 18張表彙總成一個統計表,總共要處理共36張表。然後把成績複製到統計表中,要對應好每一個學號的學生。這些表都是按一定規則進行排序的,所以每個表的排序情況是不一樣的,把每張表對應的學生的成績複製到彙總表的中,難度和工作量非常大。首先我不可能老實到每一張表去找一個學生的成績再複製到彙總表,那也太麻煩了。
2.手動複製到excel
本來一開始我就想用代碼,使用pandas來處理的。但是仔細想了一想辦法,發現手動的工作量應該也不是很大。首先我進行了以下操作:
2.1 處理統計表
從某張表中首先把學號,姓名複製出來放到統計表中,在excel中按學號升序排序;
2.2 處理作業表
在每一張表中也按學號升序排序,把作業成績那一列複製到總表裏。問題不大!!
2.3 處理簽到表
麻煩就開始來了!
1. 前幾行有多餘的行,得先刪除才能排序。
2. 以下圖片中的值都是文字表示的簽到狀態,我總不可能一個個手動更改成數字成績吧。
其中沒有成績,只有幾種狀態的文字,所以調用 excel函數:
=IF(OR(F2="已籤",F2="教師代簽"),1,IF(F2="簽到已過期",0.5,IF(F2="缺勤",0,)))
OK!搞定複製到統計表。但是這只是一張表,我還有7張+8張 。。ToT。。
2.4 期中,期末成績表
同樣刪掉前幾各無關行,按學號排序,取成績,複製到統計表。
2.5 彙總-總成績
8個作業(每門100分)佔總成績的16%,簽到佔8%,期中成績佔%30,期末成績佔46%。咋把這個成績按比例轉換匯總到總成績呢?
想了想就是尺度縮放,有點像機器學習裏面的歸一化的思想。
比如作業:先把8門成績加起來,再除以最大800分,得到一個比例,然後 16%最大佔總成績16分,用16乘以比例就得到轉轉的成績了。
=(SUM(C4:J4)*16/800)+SUM(K4:R4)+(S4*30/100)+(T4*46/100)
以上,處理完畢!!從開始到找方法,操作解決各種問題,花了我將近4個小時才完成。 要是再來一次肯定就快了,大概一到兩個小時的樣子吧。1個課程作業就2個小時,要是我導師把他教的課程,期末成績都丟給我,豈不是人都要搞傻。。。
3.使用Python+Pandas處理excel文件
痛定思痛,避免後面花過多時間折騰,還不如一次就使用代碼來批處理搞定,這樣你丟再多,咱也接着。還能避免導師查崗,摸摸魚。爽!開幹!
3.1 Pandas-讀取excel
3.1.1 讀取總表
statistic_table=pd.read_excel('./總評成績計算表.xlsx',sheet_name='理論')
第一個參數:路徑+文件名
第二個參數(可選):Excel的Sheet名,默認是選擇該表第一個sheet
3.1.2 讀取作業表,簽到表
#讀取作業表
#使用list來將讀取出的表暫存起來
assignments=[]
for ass_i in range(1,9):
ass_table=pd.read_excel('./intro/ass{0}.xls'.format(ass_i))
assignments.append(ass_table)
3.1.3 讀取期中,期末表
#讀取期中表
midterm=pd.read_excel('./intro/Midterm.xls')
#讀取期末表
finalterm=pd.read_excel('./intro/Final.xls')
3.2 預處理
因爲表的結構不是標準結構,可以看到前面都是很亂的,要麼自己手動處理原表刪掉不相干的行,要麼使用索引來操作。由於習慣使用numpy我傾向於後者。
不同表對應的統計表的列號
#統計表中列名對應的列
name2index=dict()
#作業
for i in range(2,10):
name2index['ass{}'.format(i-1)]=i
#簽到
for i in range(10,18):
name2index['sign{}'.format(i-9)]=i
name2index['mid']=18
name2index['final']=19
name2index['total']=20
name2index
3.3 Pandas索引切片
pd.iloc[raw,line]
raw:行號
line:列號
使用參考:
https://blog.csdn.net/w_weiying/article/details/81411257
3.4 Pandas遍歷
pd .iteritems()
將DataFrame迭代爲(列名, Series)對
使用參考:
https://www.cnblogs.com/keye/p/9673393.html
3.5 Pandas查找並取出某值所在的行
table.isin([name]),查找name所在的索引,返回bool值
table.iloc[:,1].isin([name]):查找table第一列name所在的行號
table[table.iloc[:,1].isin([name])]:將找到的name行號,將該所在行值取出來。
3.6 Pandas 給表賦值
table.iloc[i,j]=val
給表i和j位置賦值爲val
3.7 綜合代碼
#先取出2至最後一行的第0列,也就是取出所有學號
sid_table=statistic_table.iloc[2:,0]
#遍歷表,對應每一個學號所在的行號以及學號
for sid_ix,sid in sid_table.iteritems():
#遍歷學號
#統計表的行值:sid_ix
ass_scores=[] #用來保存該學號的所有作業成績
#遍歷作業表把對應成績放到對應列
for ass_ix,ass_table in enumerate(assignments):
#該表在統計表的列值
name_ix=name2index['ass{}'.format(ass_ix+1)]
#取出每個表對應學號的作業成績
score=float(ass_table[ass_table.iloc[:,1].isin([sid])].iloc[:,9].values[0])
ass_scores.append(score)
#將對應值插入統計表中
statistic_table.iloc[sid_ix,name_ix]=score
後面的表操作都差不多了,按照代碼仔細debug,把對應表的值都取出來然後賦值給總表,就ok了。
總結:
本篇博客的內容主要是來自我自己處理excel的真實案例,首先介紹如何手動操作excel,通過一些技巧批量處理和複製。隨後使用python,利用pandas的一些操作來處理excel達到批量處理的效果。