大家好,我是小一!
关注和星标『小一的学习笔记』,和小一一起学习数据分析!
点击关注|选择星标|干货速递
在数据分析的日常工作中,除了Excel数据的清洗,最常见的就是pdf、word、ppt等场景下的数据清洗,这种其实还有一个更高大上的名字,叫:办公自动化。
很多时候由于办公自动化场景下的数据是不规整的,所以在进行数据分析之前首要的就是进行数据提取。
例如,小一的朋友『长河』在实际工作中遇到的真实问题:
虽然我自己对word的 *** 作不是很熟悉,但是我也在思考过后提供了自己的解决方法:
由于我自己对于PDF的数据提取比较擅长,也曾经写过相关的 *** 作文档:Python办公自动化之PDF的详细 *** 作(全),所以如果原始数据是pdf,那我就会按照上面我说的方法进行 *** 作
但是长河他自己已经搞定了pdf的转换,那问题就变成了多个word的数据提取。
下面的文章就是他自己在实现过程中的真实思路,部分数据比较敏感,文中已经打码,但是不影响实际的阅读和练手
这个也是在实际工作中比较常遇到的问题,希望大家下次遇到的时候都能游刃有余
以下是『长河』投稿的正文:
1. 问题来源最近面临的一个问题是从word中读取表格数据,然后整理成excel格式。
如下所示:
如果表格不是很多,只有几张表,完全手动处理就好,但是如果有140张表,9年的数据,该怎么处理呢?
这个时候需要程序来帮我们自动化解决了。
2. 解决问题
明确问题之后,我们接下来需要解决问题。
如果要从word中提取表格,常用的包有docx , 对提取中的数据进行规范处理,需要使用pandas
2.1 明确数据的行和列如果要提取word表格中的行和列,则需要明白这个表格到底有多少行和列,然后再根据具体行和列进行数据的提取。
该部分内容可以参看B站的上的一些视频,用Python *** 作Word
代码如下:
from docx import document doc = document('one.docx') tables = doc.tables table = tables[0] # 表示读取的第一张表 # 查看一下多少行,多少列 print(len(table.rows),len(table.columns))
输出结果为:
5 14
说明我们提取的表格信息是一个5行14列的数据。接下来需要思考,每一行每一列是什么样子。
我们这里以第5行第2列为例进行说明:
继续写入代码为:
print(table.cell(4,1).text)
输出结果为:
13905 270 5583 1528 1791 2315 2439 ...
经过不断地尝试,我们终于知道自己需要的数据在什么地方了。
考虑到表头的太过于复杂,不好定位,需要自己重新写表头信息即可,我们需要的是整个学校的数据,也就是下图中的部分
接下来进行数据提取:
list1 = [] # 定义一个空的列表存储数据 for row in range(4,len(table.rows)): for column in range(len(table.columns)): list1.append(table.cell(row,column).text) print(len(list1)) print(list1)
提取出来的数据是一串很长的列表,输出结果为:
14 ['--大学--大学--大学---大学n ----n2186588n203224n146649n329602n214014n299323n47413n71033']
接下来进行迭代,转化成 [[],[],[]] 的形式
values = [] for i in list1: i = i.split('n') values.append(i) print(values)
结果处理完成,结果如下:
[['xx大学', 'xxxx大学', 'xx大学', ---'xxxx大学'],--- ['2186588', '203224', '146649', '329602', '214014', '299323', '47413', '71033']]2.3 转成 Dataframe格式
前面已经把values整理好了,接下来重新整理表头信息即可:
colums = ['xx','xx','xx'] data_part1 = pd.Dataframe(values,columns).T print(data_part1.head())
输出结果为:
学校名称 xxxxxx- ... xxxx xxxxxxx 0 XX大学 13905 ... 46526 2222470 1 XX大学 270 ... 0 67822 2 XX大学 5583 ... 331010 3557540 3 XX大学 1528 ... 12826 544980 4 XX大学 1791 ... 1270 844921 [5 rows x 14 columns]
考虑到一个word文件有两张表,第二张表的数据结构如下:
第二张表的表头与第一张表有所不同,处理方式一样,直接上代码即可:
table = tables[1] for row in range(3, len(table.rows)): for column in range(len(table.columns)): table2.append(table.cell(row, column).text) for h in table2: h = h.split('n') values2.append(h) data2 = pd.Dataframe(values2,column2).T data = pd.concat([data1,data2],axis =1)2.4 完整地处理一张表
一张完整的word有两张表,所以需要使用一个判断条件进行处理,将其分为奇数位表和偶数位表,其判断依据是某数除以2余数是否为 0,
具体的代码如下:
import pandas as pd from docx import document column1 = ['xx','xx','xx','xx','xx'] column2 = ['xx','xx','xx','xx','xx'] for t in range(len(tables)): if t % 2 == 0: table1 = [] value1 = [] table = docx.tables[t] for row in range(4, len(table.rows)): for column in range(len(table.columns)): table1.append(table.cell(row, column).text) for j in table1: j = j.split('n') value1.append(j) data1 = pd.Dataframe(value1, column1).T if t % 2 == 1: table2 = [] value2 = [] table = docx.tables[t] for row in range(3, len(table.rows)): for column in range(len(table.columns)): table2.append(table.cell(row, column).text) for h in table2: h = h.split('n') value2.append(h) data2 = pd.Dataframe(value2,column2).T data = pd.concat([data1,data2],axis =1)2.5 完整地处理多张表
如果是处理多张表,则需要设置路径,然后在具体的路径中进行处理
具体的代码如下:
import pandas as pd from docx import document import os column1 = ['xx','xx','xx','xx','xx'] column2 = ['xx','xx','xx','xx','xx'] # 设置路径 path = os.listdir('E:one-two') # print(path) for i in range(len(path)): docx = document('E:one-two{}'.format(path[i])) # print('第{}表'.format(i+1),docx) tables = docx.tables for t in range(len(tables)): if t % 2 == 0: table1 = [] value1 = [] table = docx.tables[t] for row in range(4, len(table.rows)): for column in range(len(table.columns)): table1.append(table.cell(row, column).text) for j in table1: j = j.split('n') value1.append(j) data1 = pd.Dataframe(value1, column1).T if t % 2 == 1: table2 = [] value2 = [] table = docx.tables[t] for row in range(3, len(table.rows)): for column in range(len(table.columns)): table2.append(table.cell(row, column).text) for h in table2: h = h.split('n') value2.append(h) data2 = pd.Dataframe(value2,column2).T data = pd.concat([data1,data2],axis =1) print('正在保存{}'.format(i+1)) data.to_excel('E:one-two{}.xlsx'.format(i),index=False)
最后的输出结果为:
学习编程会遇到很多问题和困惑。但是这个也是提高自己编程技术的关键所在。不断地探索,看B站视频,请教大佬,然后不停地print看输出结果,就会得到自己想要的东西!
感谢小一前辈提供的思路,笔芯笔芯!
一个word一个word的处理,这样反而能提高效率!
历史好文推荐:
一行Python代码去除照片背景
2021年最有用的数据清洗 Python 库
21年Q3季度基金持仓数据分析,满仓干还是等风来?
历史上的今天,3步轻松复现!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)