0
点赞
收藏
分享

微信扫一扫

Pandas自动分割汇总表写入到子表中

独兜曲 2022-09-07 阅读 167


作者简介:小小明,Pandas数据处理专家,致力于帮助无数数据从业者解决数据处理难题。

这是半年前写的一篇文章,里面涉及的方法可能有些过时,但处理思想仍有较高的参考价值,现在发布到csdn。

群友反馈:

Pandas自动分割汇总表写入到子表中_hdfs

我整理了一下需求大概就是下面的意思,根据汇总表的分区字段自动填入指定的分区文件中:

Pandas自动分割汇总表写入到子表中_hdfs_02

对于分区表的文件,例如A区.xlsx、B区.xlsx等,需要先将3行之后已经存在的数据删除后再进行写入。

B区.xlsx在自动填入后,结果如下:

Pandas自动分割汇总表写入到子表中_hdfs_03

其实初始需求非常简单,我们下面看看怎么做吧。

文章目录

  • ​​基本需求的解决方案​​
  • ​​汇总表的数据情况​​
  • ​​筛选出准备写入B区的数据​​
  • ​​覆盖写入到对应的分区文件​​
  • ​​遍历分区字段的简单办法​​
  • ​​基本需求的整体代码​​
  • ​​扩展需求的实现​​
  • ​​数据加载​​
  • ​​遍历计算出每个级别所涉及的区​​
  • ​​删除级别文件夹多余的文件并将xls转换为xlsx​​
  • ​​遍历出级别和区域​​
  • ​​写出结果​​
  • ​​扩展需求的完整实现代码​​

基本需求的解决方案

汇总表的数据情况

import pandas as pd
data = pd.read_excel("汇总.xlsx", sheet_name='明细')

所属区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

0

B区

111111

NaN

张一

招商银行

576.00

NaN

NaN

NaN

河南省

1

B区

111112

NaN

张二

招商银行

576.00

NaN

NaN

NaN

湖南省

2

B区

111113

NaN

张三

招商银行

1392.00

NaN

NaN

NaN

河南省

3

C区

2222

NaN

一一

招商银行

198.00

NaN

NaN

NaN

河南省

4

A区

222222

NaN

二二

招商银行

671.00

NaN

NaN

NaN

云南省

5

A区

123444

NaN

李四

中国银行

330.00

NaN

NaN

NaN

云南省

6

D区

123445

NaN

王五

中国银行

265.35

NaN

NaN

NaN

广东省

7

D区

123446

NaN

赵六

中国银行

265.35

NaN

NaN

NaN

广东省

8

D区

123447

NaN

七七

中国银行

90.00

NaN

NaN

NaN

广东省

对于B区的数据如何写入呢?

筛选出准备写入B区的数据

df = data[data["所属区"] == "B区"]

所属区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

0

B区

111111

NaN

张一

招商银行

576.0

NaN

NaN

NaN

河南省

1

B区

111112

NaN

张二

招商银行

576.0

NaN

NaN

NaN

湖南省

2

B区

111113

NaN

张三

招商银行

1392.0

NaN

NaN

NaN

河南省

df = df.iloc[:, 1:]
df.values.tolist()

[[111111, nan, '张一', '招商银行', 576.0, nan, nan, nan, '河南省'],
[111112, nan, '张二', '招商银行', 576.0, nan, nan, nan, '湖南省'],
[111113, nan, '张三', '招商银行', 1392.0, nan, nan, nan, '河南省']]

覆盖写入到对应的分区文件

workbook = load_workbook(filename="B区.xlsx")
sheet = workbook.active
# 先删除第4行之后的旧数据,预计1000行完全够用
sheet.delete_rows(idx=4, amount=1000)
# 然后在进行添加数据
for row in df.values.tolist():
sheet.append(row)
workbook.save(filename="B区.xlsx")
workbook.close()

遍历分区字段的简单办法

for area, df in data.groupby('所属区'):
print(area)
display(df)

A区

所属区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

4

A区

222222

NaN

二二

招商银行

671.0

NaN

NaN

NaN

云南省

5

A区

123444

NaN

李四

中国银行

330.0

NaN

NaN

NaN

云南省

B区

所属区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

0

B区

111111

NaN

张一

招商银行

576.0

NaN

NaN

NaN

河南省

1

B区

111112

NaN

张二

招商银行

576.0

NaN

NaN

NaN

湖南省

2

B区

111113

NaN

张三

招商银行

1392.0

NaN

NaN

NaN

河南省

C区

所属区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

3

C区

2222

NaN

一一

招商银行

198.0

NaN

NaN

NaN

河南省

D区

所属区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

6

D区

123445

NaN

王五

中国银行

265.35

NaN

NaN

NaN

广东省

7

D区

123446

NaN

赵六

中国银行

265.35

NaN

NaN

NaN

广东省

8

D区

123447

NaN

七七

中国银行

90.00

NaN

NaN

NaN

广东省

基本需求的整体代码

import pandas as pd
data = pd.read_excel("汇总.xlsx", sheet_name='明细')

for area, df in data.groupby('所属区'):
print(area)
if os.path.exists(f"{area}.xlsx"):
workbook = load_workbook(filename=f"{area}.xlsx")
else:
print(f"{area}.xlsx不存在")
continue
sheet = workbook.active
df = df.iloc[:, 1:]
# 先删除第4行之后的旧数据,预计1000行完全够用
sheet.delete_rows(idx=4, amount=1000)
# 然后在进行添加数据
for row in df.values.tolist():
sheet.append(row)
print(row)
print(f"保存到{area}.xlsx文件中")
workbook.save(filename=f"{area}.xlsx")
workbook.close()

A区
[222222, nan, '二二', '招商银行', 671.0, nan, nan, nan, '云南省']
[123444, nan, '李四', '中国银行', 330.0, nan, nan, nan, '云南省']
保存到A区.xlsx文件中
B区
[111111, nan, '张一', '招商银行', 576.0, nan, nan, nan, '河南省']
[111112, nan, '张二', '招商银行', 576.0, nan, nan, nan, '湖南省']
[111113, nan, '张三', '招商银行', 1392.0, nan, nan, nan, '河南省']
保存到B区.xlsx文件中
C区
[2222, nan, '一一', '招商银行', 198.0, nan, nan, nan, '河南省']
保存到C区.xlsx文件中
D区
[123445, nan, '王五', '中国银行', 265.35, nan, nan, nan, '广东省']
[123446, nan, '赵六', '中国银行', 265.35, nan, nan, nan, '广东省']
[123447, nan, '七七', '中国银行', 90.0, nan, nan, nan, '广东省']
保存到D区.xlsx文件中

好了经过以上步骤,就成功完成任务了,群友也表示感谢:

Pandas自动分割汇总表写入到子表中_hdfs_04

扩展需求的实现

不过好景不长,大早上新需求又来了:

Pandas自动分割汇总表写入到子表中_二级_05

现在的需求跟之前的区别有:

汇总表多了级别字段,需要根据不同的级别对应不同的文件夹

Pandas自动分割汇总表写入到子表中_二级_06

所属区的xlsx文件有时可能是xls,并不一定是xlsx的。

各级别文件夹中存在一些不能匹配汇总表的垃圾文件需要删除。

汇总表中所有的对应项目并不是都在级别文件夹中存在,不存在的只提示哪些不存在,无需额外处理。

下面是我的实现过程:

数据加载

import os
import pandas as pd

excel_dir=r"D:\hdfs\excel\汇总表拆分到分区表"

data = pd.read_excel(f"{excel_dir}/汇总.xlsx", sheet_name='明细')

级别

所属区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

0

一级

B区

111111

NaN

张一

招商银行

576.00

NaN

NaN

NaN

河南省

1

一级

B区

111112

NaN

张二

招商银行

576.00

NaN

NaN

NaN

湖南省

2

一级

B区

111113

NaN

张三

招商银行

1392.00

NaN

NaN

NaN

河南省

3

二级

C区

2222

NaN

一一

招商银行

198.00

NaN

NaN

NaN

河南省

4

二级

A区

222222

NaN

二二

招商银行

671.00

NaN

NaN

NaN

云南省

5

二级

A区

123444

NaN

李四

中国银行

330.00

NaN

NaN

NaN

云南省

6

三级

D区

123445

NaN

王五

中国银行

265.35

NaN

NaN

NaN

广东省

7

三级

D区

123446

NaN

赵六

中国银行

265.35

NaN

NaN

NaN

广东省

8

三级

E区

123447

NaN

七七

中国银行

90.00

NaN

NaN

NaN

广东省

遍历计算出每个级别所涉及的区

level_areas = {}
for i, row in data.iterrows():
areas = level_areas.setdefault(row['级别'], set())
areas.add(row['所属区'])

{'一级': {'B区'}, '二级': {'A区', 'C区'}, '三级': {'D区', 'E区'}}

删除级别文件夹多余的文件并将xls转换为xlsx

win32com.client需要通过

​pip install pywin32 ​

安装后使用

import win32com.client as win32

for level in data['级别'].unique():
areas = level_areas[level]
files = os.listdir(f"{excel_dir}/{level}")
for file in files:
tag = file.replace(".xlsx", "").replace(".xls", "")
filename = f"{excel_dir}/{level}/{file}"
if not tag in areas:
print(f"删除文件:{filename}")
os.remove(filename)
elif file.endswith(".xls"):
print(f"将 {filename} 转换为 {filename}x")
excel = win32.gencache.EnsureDispatch('Excel.Application')
try:
wb = excel.Workbooks.Open(filename)
wb.SaveAs(f"{filename}x", FileFormat=51) #FileFormat = 51 is for .xlsx extension
print("转换成功")
finally:
wb.Close() #FileFormat = 56 is for .xls extension
excel.Application.Quit()
os.remove(filename)

准备将 D:\hdfs\excel\汇总表拆分到分区表/一级/B区.xls 转换为 D:\hdfs\excel\汇总表拆分到分区表/一级/B区.xlsx
转换成功

注意:使用pywin32转换excel文件格式时,绝对路径的盘符后面的分隔符必须是反斜杠\,后面的路径分隔符用正斜杠或反斜杠都可以。

遍历出级别和区域

for (level, area), df in data.groupby(['级别', '所属区']):
print(level, area)
df = df.iloc[:, 2:]
display(df)

一级 B区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

0

111111

NaN

张一

招商银行

576.0

NaN

NaN

NaN

河南省

1

111112

NaN

张二

招商银行

576.0

NaN

NaN

NaN

湖南省

2

111113

NaN

张三

招商银行

1392.0

NaN

NaN

NaN

河南省

三级 D区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

6

123445

NaN

王五

中国银行

265.35

NaN

NaN

NaN

广东省

7

123446

NaN

赵六

中国银行

265.35

NaN

NaN

NaN

广东省

三级 E区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

8

123447

NaN

七七

中国银行

90.0

NaN

NaN

NaN

广东省

二级 A区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

4

222222

NaN

二二

招商银行

671.0

NaN

NaN

NaN

云南省

5

123444

NaN

李四

中国银行

330.0

NaN

NaN

NaN

云南省

二级 C区

身份证号

银行卡号

姓名

开户行

金额

摘要

用途

收款账号联行号

收款账号省份

3

2222

NaN

一一

招商银行

198.0

NaN

NaN

NaN

河南省

写出结果

from openpyxl import load_workbook

for (level, area), df in data.groupby(['级别', '所属区']):
print(level, area)
df = df.iloc[:, 2:]
out_file_name = f"{excel_dir}/{level}/{area}.xlsx"
if not os.path.exists(out_file_name):
print(out_file_name, "文件不存在,跳过")
continue
print("准备写出到:", out_file_name)
workbook = load_workbook(filename=out_file_name)
sheet = workbook.active
# 先删除第4行之后的旧数据,预计1000行完全够用
sheet.delete_rows(idx=4, amount=1000)
# 然后再进行添加数据
for row in df.values.tolist():
sheet.append(row)
print(row)
print(f"保存到{out_file_name}文件中")
workbook.save(filename=out_file_name)
workbook.close()

一级 B区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/一级/B区.xlsx
[111111, nan, '张一', '招商银行', 576.0, nan, nan, nan, '河南省']
[111112, nan, '张二', '招商银行', 576.0, nan, nan, nan, '湖南省']
[111113, nan, '张三', '招商银行', 1392.0, nan, nan, nan, '河南省']
保存到D:\hdfs\excel\汇总表拆分到分区表/一级/B区.xlsx文件中
三级 D区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/三级/D区.xlsx
[123445, nan, '王五', '中国银行', 265.35, nan, nan, nan, '广东省']
[123446, nan, '赵六', '中国银行', 265.35, nan, nan, nan, '广东省']
保存到D:\hdfs\excel\汇总表拆分到分区表/三级/D区.xlsx文件中
三级 E区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/三级/E区.xlsx
[123447, nan, '七七', '中国银行', 90.0, nan, nan, nan, '广东省']
保存到D:\hdfs\excel\汇总表拆分到分区表/三级/E区.xlsx文件中
二级 A区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/二级/A区.xlsx
[222222, nan, '二二', '招商银行', 671.0, nan, nan, nan, '云南省']
[123444, nan, '李四', '中国银行', 330.0, nan, nan, nan, '云南省']
保存到D:\hdfs\excel\汇总表拆分到分区表/二级/A区.xlsx文件中
二级 C区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/二级/C区.xlsx
[2222, nan, '一一', '招商银行', 198.0, nan, nan, nan, '河南省']
保存到D:\hdfs\excel\汇总表拆分到分区表/二级/C区.xlsx文件中

扩展需求的完整实现代码

import os
import pandas as pd
import win32com.client as win32
from openpyxl import load_workbook

excel_dir = r"D:\hdfs\excel\汇总表拆分到分区表"

data = pd.read_excel(f"{excel_dir}/汇总.xlsx", sheet_name='明细')

# 遍历计算出每个级别所涉及的区
level_areas = {}
for i, row in data.iterrows():
areas = level_areas.setdefault(row['级别'], set())
areas.add(row['所属区'])
print("各级别所拥有的区", level_areas)

# 删除级别文件夹多余的文件并将xls转换为xlsx
for level in data['级别'].unique():
areas = level_areas[level]
files = os.listdir(f"{excel_dir}/{level}")
for file in files:
tag = file.replace(".xlsx", "").replace(".xls", "")
filename = f"{excel_dir}/{level}/{file}"
if not tag in areas:
print(f"删除文件:{filename}")
os.remove(filename)
elif file.endswith(".xls"):
print(f"将 {filename} 转换为 {filename}x")
excel = win32.gencache.EnsureDispatch('Excel.Application')
try:
wb = excel.Workbooks.Open(filename)
wb.SaveAs(f"{filename}x", FileFormat=51)
print("转换成功")
finally:
wb.Close() #FileFormat = 56 is for .xls extension
excel.Application.Quit()
os.remove(filename)

# 写出结果
for (level, area), df in data.groupby(['级别', '所属区']):
print(level, area)
df = df.iloc[:, 2:]
out_file_name = f"{excel_dir}/{level}/{area}.xlsx"
if not os.path.exists(out_file_name):
print(out_file_name, "文件不存在,跳过")
continue
print("准备写出到:", out_file_name)
workbook = load_workbook(filename=out_file_name)
sheet = workbook.active
# 先删除第4行之后的旧数据,预计1000行完全够用
sheet.delete_rows(idx=4, amount=1000)
# 然后再进行添加数据
for row in df.values.tolist():
sheet.append(row)
print(row)
print("保存到", out_file_name, "文件中")
workbook.save(filename=out_file_name)
workbook.close()

各级别所拥有的区 {'一级': {'B区'}, '二级': {'A区', 'C区'}, '三级': {'D区', 'E区'}}
一级 B区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/一级/B区.xlsx
[111111, nan, '张一', '招商银行', 576.0, nan, nan, nan, '河南省']
[111112, nan, '张二', '招商银行', 576.0, nan, nan, nan, '湖南省']
[111113, nan, '张三', '招商银行', 1392.0, nan, nan, nan, '河南省']
保存到 D:\hdfs\excel\汇总表拆分到分区表/一级/B区.xlsx 文件中
三级 D区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/三级/D区.xlsx
[123445, nan, '王五', '中国银行', 265.35, nan, nan, nan, '广东省']
[123446, nan, '赵六', '中国银行', 265.35, nan, nan, nan, '广东省']
保存到 D:\hdfs\excel\汇总表拆分到分区表/三级/D区.xlsx 文件中
三级 E区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/三级/E区.xlsx
[123447, nan, '七七', '中国银行', 90.0, nan, nan, nan, '广东省']
保存到 D:\hdfs\excel\汇总表拆分到分区表/三级/E区.xlsx 文件中
二级 A区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/二级/A区.xlsx
[222222, nan, '二二', '招商银行', 671.0, nan, nan, nan, '云南省']
[123444, nan, '李四', '中国银行', 330.0, nan, nan, nan, '云南省']
保存到 D:\hdfs\excel\汇总表拆分到分区表/二级/A区.xlsx 文件中
二级 C区
准备写出到: D:\hdfs\excel\汇总表拆分到分区表/二级/C区.xlsx
[2222, nan, '一一', '招商银行', 198.0, nan, nan, nan, '河南省']
保存到 D:\hdfs\excel\汇总表拆分到分区表/二级/C区.xlsx 文件中

上面只是示例数据,所以看出来有啥效果,但是群友要处理的实际数据有几百个文件夹,用代码处理的优势一下子就体现出来了。看看群友的反馈吧:

Pandas自动分割汇总表写入到子表中_分区表_07


举报

相关推荐

0 条评论