zoukankan      html  css  js  c++  java
  • 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

    <人追求理想之时,便是坠入孤独之际.> By 史泰龙
  • 相关阅读:
    C++ std::stack 基本用法
    linux6 安装 ntopng
    linux 6安装 redis2.6
    Linux6搭建Tomcat服务器
    EXSI6.5忘记root密码
    python3笔记--数字
    python3笔记--运算符
    python3基本数据类型
    python3笔记
    centos6.X升级python3.X方法
  • 原文地址:https://www.cnblogs.com/jason-Gan/p/12311430.html
Copyright © 2011-2022 走看看