python生成Excel透视表

2021/10/4 11:41:00

本文主要是介绍python生成Excel透视表,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

        假设你有如下数据,

姓名科目成绩
小黑语文42
小娜语文23
小白语文98
小乐语文52
小黑数学30
小娜数学76
小白数学47
小乐数学73
小黑英语63
小娜英语83
小白英语4
小乐英语71

        想生成一个透视表,你肯定要去Excel工具里面操作,但是呢,数据多了可能会出错,所以我们可以借助python提供的 pandas 模块进行透视表生成。

        视频演示

<iframe allowfullscreen="true" data-mediaembed="bilibili" id="9onWQi8p-1633317518963" src="https://player.bilibili.com/player.html?aid=805960833&page=1"></iframe>

python透视表 生成演示

        话不多说,我们先来看看生成后表格的数据项:

        如上就是pandas生成的 Excel透视表,数据一目了然,看的非常清楚直观,前面两行和第四行是代码生成、便于拥有多个数据时进行区分的,如不需要,可进行删除,ALL是成绩的总和。

下面开始上代码教程

        这个工具是用Tkinter模块开发的,所以先导入Tkinter相关模块。

import tkinter as tk
import tkinter.font as tkFont
from tkinter.filedialog import askdirectory
import tkinter.messagebox
import tkinter.filedialog

        对于Tkinter图形界面详细开发教程这里就不多说,可自行百度。或者可查看

Python GUI之tkinter窗口视窗教程大集合

         还有一些其他的模块也一并导入

import os
import pandas as pd
import numpy as np
from pylab import mpl
from matplotlib import pyplot as plt

import tkinter as tk
import tkinter.font as tkFont
from tkinter.filedialog import askdirectory
import tkinter.messagebox
import tkinter.filedialog

         然后新建一个GUI界面,并在GUI界面添加如下操作元素:两个输入框和两个按钮,分别用来选择需要操作的Excel表和选择保存的文件夹。还有另外三个输入框与按钮,分别用来选择显示在透视表左边和透视表上方的数据项,以及需要比较的数据项,最后是一个清除输入框内容的按钮和一个生成文件的按钮。

        示例图如下:

        上方的图表功能这篇文章暂不讨论,下次再拿出来分享。 

         好了,现在开始放代码

import os
import pandas as pd
import numpy as np
import tkinter as tk
import tkinter.font as tkFont
from tkinter.filedialog import askdirectory
import tkinter.messagebox
import tkinter.filedialog
from pylab import mpl
from matplotlib import pyplot as plt
#制作图表时,需要加入这段代码,不然生成的图标会乱码
mpl.rcParams['font.sans-serif'] = ['Microsoft YaHei']

window = tk.Tk()
window.title('透视表生成(通用版)')
# 获取屏幕宽高
sw = window.winfo_screenwidth()
sh = window.winfo_screenheight()
# 设置屏幕的宽和高
ww = 600
wh = 500
x = (sw - ww) / 2
y = (sh - wh) / 2
# 根据屏幕宽高来让程序居中
window.geometry("%dx%d+%d+%d" % (ww, wh, x, y))
window.resizable(width=False, height=False)
# 设置字体
fontStyle = tkFont.Font(family="Lucida Grande", size=15)
fontStyleRadio = tkFont.Font(family="Lucida Grande", size=13)
# 应用标题
tk.Label(window, text="透视表生成(通用版)", font=fontStyle).pack()
dataState = ""

ty = "0"
def askd():
    if ty == "1":
        tks2()
    global paths
    # 打开文件 设置只能打开xls和xlsx文件
    paths = tkinter.filedialog.askopenfilename(title='打开表格', filetypes=[("xlsx", ".xlsx"), ("xls", ".xls")])
    path.set(paths)
    cc = paths.endswith(".xls")
    # 进行表格数据读取,将第一行数据放入Listbox中进行后续选择
    if cc == True:
        df = pd.read_excel(paths)
    else:
        df = pd.read_excel(paths, engine='openpyxl')
    labels = list(df.columns)
    global lb
    lb = tk.Listbox(window, font=fontStyle)
    for ite in labels:
        lb.insert('end', ite)
    lb.pack()
    print(paths)
    tks()

# 如果第二次选择表格,就将ty设置为1,当ty=1时,清空 Listbox 的数据
def tks():
    global ty
    ty = "1"
def tks2():
    lb.destroy()

index__ = []
# 左边的数值
def lbs1():
    tPath1.set(tPath1.get() + lb.get(lb.curselection()) + "、")
    index__.append(lb.get(lb.curselection()))
# 顶部的数值
def lbs2():
    tPath2.set(lb.get(lb.curselection()))

global values_
values2_ = []
# 要比较的数据
def lbs3():
    tPath3.set(tPath3.get() + lb.get(lb.curselection()) + "、")
    values2_.append(lb.get(lb.curselection()))

# 选择要保存的文件夹
def askd2():
    global paths2
    paths2 = askdirectory() + "/"
    path2.set(paths2)
    print(paths2)

# 设置frame容器
frame = tk.Frame(window, padx=3, pady=3)
frame.pack()
frame_left = tk.Frame(frame)
frame_right = tk.Frame(frame)
frame_left.pack(side='left')
frame_right.pack(side='right')

# 选择文件和选择文件夹的输入框
path = tk.StringVar()
path2 = tk.StringVar()
e1 = tk.Entry(frame_left, textvariable=path, width=50).pack(padx=5, pady=10)
e2 = tk.Entry(frame_left, textvariable=path2, width=50).pack(padx=5, pady=10)
# 三个数值的输入框
tPath1 = tk.StringVar()
tPath2 = tk.StringVar()
tPath3 = tk.StringVar()
t1 = tk.Entry(frame_left, textvariable=tPath1, width=50)
t2 = tk.Entry(frame_left, textvariable=tPath2, width=50)
t3 = tk.Entry(frame_left, textvariable=tPath3, width=50)
t1.pack(padx=5, pady=10)
t2.pack(padx=5, pady=10)
t3.pack(padx=5, pady=10)
# 按钮
tk.Button(frame_right, text='选择文件', font=fontStyle, width=18, height=1, command=lambda: askd()).pack(padx=3, pady=3)
tk.Button(frame_right, text='选择保存的文件夹', font=fontStyle, width=18, height=1, command=lambda: askd2()).pack(padx=3,pady=3)
tk.Button(frame_right, text='左边的数值', font=fontStyle, width=18, height=1, command=lambda: lbs1()).pack(padx=3, pady=3)
tk.Button(frame_right, text='顶部的数值', font=fontStyle, width=18, height=1, command=lambda: lbs2()).pack(padx=3, pady=3)
tk.Button(frame_right, text='比较的数据', font=fontStyle, width=18, height=1, command=lambda: lbs3()).pack(padx=3, pady=3)


frame2 = tk.Frame(window, padx=3, pady=3)
frame2.pack()
frame_left_01 = tk.Frame(frame2)
frame_right_01 = tk.Frame(frame2)
frame_left_01.pack(side='left')
frame_right_01.pack(side='right')
frame_left_02 = tk.Frame(frame_left_01)
frame_right_02 = tk.Frame(frame_left_01)
frame_left_02.pack(side='left')
frame_right_02.pack(side='right')
frame_left_03 = tk.Frame(frame_right_01)
frame_right_03 = tk.Frame(frame_right_01)
frame_left_03.pack(side='left')
frame_right_03.pack(side='right')

# 生成图表的单选按钮
var_1 = tk.StringVar()
var_1.set('A')
r1 = tk.Radiobutton(frame_left_02, text='不生成图表', font=fontStyleRadio, variable=var_1, value='A',).pack(padx=3, pady=3)
r2 = tk.Radiobutton(frame_right_02, text='生成折线图', font=fontStyleRadio, variable=var_1, value='B',).pack(padx=3, pady=3)

r3 = tk.Radiobutton(frame_left_03, text='生成柱状横图', font=fontStyleRadio, variable=var_1, value='C',).pack(padx=3, pady=3)
r4 = tk.Radiobutton(frame_right_03, text='生成柱状竖图', font=fontStyleRadio, variable=var_1, value='D',).pack(padx=3, pady=3)



frame = tk.Frame(window, padx=3, pady=3)
frame.pack()
frame_left2 = tk.Frame(frame)
frame_right2 = tk.Frame(frame)
frame_left2.pack(side='left')
frame_right2.pack(side='right')

tk.Button(frame_left2, text='清空', font=fontStyle, width=15, height=1, command=lambda: qk()).pack(padx=3, pady=3)
tk.Button(frame_right2, text='开始转换', font=fontStyle, width=15, height=1,
          command=lambda: ts(paths, paths2, t2.get(), t3.get(), var_1.get())).pack(padx=3, pady=3)

# 清空内容的方法
def qk():
    lb.destroy()
    path.set('')
    path2.set('')
    tPath1.set('')
    tPath2.set('')
    tPath3.set('')
    index__.clear()
    values2_.clear()
# 关键方法!!! 透视表生成的方法
def ts(path, paths2, columns_, values_, vars):
    # path 路径名  左边显示名称
    # 首先检测选择的文件是xls还是xlsx,如果说xls就用xlrd读取文件,不用额外填写。
    # 如果是xlsx,就要设置engine='openpyxl',使用openpyxl读取xlsx。 xlrd不能读取xlsx,openpyxl也不能读取xls文件。

    cc = path.endswith(".xls")
    if cc == True:
        df = pd.read_excel(paths)
    else:
        df = pd.read_excel(paths, engine='openpyxl')

    #                   index: 左边的数值  columns: 最上面的数值  values: 要比较的数值 aggfunc:有相同数据时相加 fill_value:空值设置为0  margins:求和
    c1 = df.pivot_table(index=index__, columns=[columns_], values=values2_, aggfunc=[np.sum], dropna=False, fill_value=0, margins=True)
    val_ = values_.replace('、', '')

    p11 = paths2 + val_ + '.xlsx'
    # 生成Excel文件
    c1.to_excel(p11)
    if vars != 'A':
        if vars == 'B':
            c1.plot(kind='line')
        if vars == 'C':
            c1.plot(kind='barh')
        if vars == 'D':
            c1.plot(kind='bar')
            # 生成图表
        plt.savefig(paths2 + val_ + '.png')
        plt.show()
    ts = tkinter.messagebox.showinfo(title='提示', message="转换成功!")
    if ts == 'ok':
        os.startfile(p11)
# 窗口循环显示
window.mainloop()

 如有不懂,可在下方提问。

 

 



这篇关于python生成Excel透视表的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程