python讀取excel文件,做數據透視(單元格合並)


先描述下需求,如下圖一

             圖一

要統計各用戶id,昵稱以及其對應字的個數(1行數據算1個),以及其對應處理老師(ps:會有至少一個老師處理),以及各老師處理的個數及占比,

最后得到下圖二的結果

              圖二

"""
數據處理
1. 讀取數據中的 用戶id,用戶昵稱,字,老師id,老師昵稱
2. 統計用戶id及其字的個數(多少行),以及老師id的數量
3. 然后統計該用戶下各老師處理的數量及占比
"""

import xlrd,xlwt
from collections import Counter
workbook=xlrd.open_workbook('1月正式課情況.xlsx') # 打開文件
# sheet_name=workbook.sheet_names()  #所有sheet的名字
sheets=workbook.sheets()#返回可迭代的sheets對象
sh = sheets[0] # 此處0,表示取第一個sheet,0為索引,也可以通過sheet表名取sheet,方法是: workbook.sheet_by_name("sheet名")

# 動態獲取 用戶id 等所在的列索引
row_1 = sh.row_values(0) # 獲取第1行內容
user_id_index = row_1.index("用戶id")
user_nick_index = row_1.index("用戶昵稱")
teacher_id_index = row_1.index("老師id")
teacher_nick_index = row_1.index("老師昵稱")
# 取用戶id集合
col_user_id = sh.col_values(user_id_index)[1:]
# 統計用戶id列表的值及個數
user_id_and_count = dict(Counter(col_user_id))
user_ids = list(set(col_user_id))
rx = sh.nrows # 表格總行數

# 新建一個文件,准備寫入數據
wb = xlwt.Workbook()
new_sheet = wb.add_sheet('用戶-老師技術表') # sheet名,不填默認sheet1
row = ['用戶id', '用戶昵稱', '老師計數', '計數項:字', '老師id','老師昵稱','老師處理量','占比']

# 生成第一行
for i in range(0, len(row)):
    new_sheet.write(0, i, row[i])

cursor = 1

# 獲取用戶id和用戶昵稱,以及老師id及昵稱對應關系
user_id_nicks = {}
teacher_nick_dict = {}
for i in range(1,rx):
    id = int(sh.row_values(i)[user_id_index])
    nick = sh.row_values(i)[user_nick_index]
    teacher_id = sh.row_values(i)[teacher_id_index]
    teacher_nick = sh.row_values(i)[teacher_nick_index]
    if user_id_nicks.__contains__(id): # 判斷字典是否有該鍵,沒有則添加
        user_id_nicks[id] = nick
    if teacher_nick_dict.__contains__(id):
        teacher_nick_dict[teacher_id] = teacher_nick


def write_data(sheet, item, cursor):
    item_head_4 = item[0]
    item_tail_3 = item[1]
    len = item_head_4[2]  # 老師計數
    for i, v in enumerate(item_head_4): # 合並單元格就需要一列列寫入
        sheet.write_merge(cursor,cursor+len-1,i, i, v)
    flag = 0
    for m in item_tail_3:
        for i, v in enumerate(m):
            sheet.write(cursor+flag, i+4, v)
        flag += 1
    cursor = cursor + len
    return cursor


for user_id in user_ids:
    # 遍歷所有行
    teacher_id_list = []
    for i in range(rx):
        if user_id == sh.row_values(i)[user_id_index]:
            # 取出該user_id下的所有老師id及數量統計
            teacher_id_list.append(sh.row_values(i)[teacher_id_index])
    user_teacher_id_and_count = dict(Counter(teacher_id_list))
    user_teacher_count = len(user_teacher_id_and_count)
    char_num = user_id_and_count[user_id]
    # '用戶id', '用戶昵稱','老師計數', '處理量計數',  '老師id', '老師昵稱''老師處理量','占比'
    item_head_4 = [int(user_id),user_id_nicks.get(int(user_id)),user_teacher_count,char_num]
    item_tail_3 = []
    for k, v in user_teacher_id_and_count.items():
        item_tail_3.append([int(k), teacher_nick_dict.get(int(k)), v, "%.2f%%" % (v/char_num * 10000/100)])
    item = [item_head_4,item_tail_3]
    cursor = write_data(new_sheet,item,cursor)

# 要保存的文件名
wb.save('用戶-老師技術表.xls')

 

最后,想額外說的一點是上圖二中合並單元格得操作, 即上圖中write_data函數中使用的write_merge函數,因為對部分列的部分行單元格進行了合並,所有寫入數據時,不能和之前一樣標准地一行一列寫入,而是先寫入合並了行單元格的列數據,然后再一行行寫入未合並的行的列數據;

write_merge(x, x + m, y, y + n, string, sytle)
x表示行,y表示列,m表示跨行個數,n表示跨列個數,string表示要寫入的單元格內容,style表示單元格樣式。其中,x,y,m,n,都是以0開始計算的。

如:sheet.write_merge(21,21,0,1,u'合計',set_style('Times New Roman',220,True))

即在22行合並第1,2列,合並后的單元格內容為"合計",並設置了style。

本文參考資料: https://www.jb51.net/article/60510.htm


免責聲明!

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



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