这是我在实际工作中使用到的工作小技巧(由于真实字段名称保密,以下字段名用加粗标出,并且使用与工作相同的含义做一些隐藏,无需在意实际情况,理解含义即可)
现在我需要对两个excel文件进行数据清洗,
一个文件中,存在唯一id字段对应数据,假如叫“测试号”;存在类型标签,假如叫“水果种类”;存在一个类似身份证号码的,每一位都有意义的代码,假如叫“有意义码”。
另一个文件中,存在对应上一个文件的id字段,但不唯一,一对多,是上一个文件中信息的扩展。
在需要进行清洗的数据中,我们只关注某一特定标签的数据,比如类型标签“水果种类”中,我们即将进行清洗的只有“桔子”。其他数据不要。
第一个文件中的唯一字段,由于各种原因,可能不唯一,存在问题,需要用代码快速检验若干应该唯一的字段是否唯一。
第二个文件中的若干字段和第一个文件中的字段应该是相对应的,需要将两个文件中的这些字段进行匹配,查看字段匹配结果是否一致。
文件中的“有意义码”中的第二位,按照字母对应着不同含义,如:'A'代表'牛奶','B'代表'蜂蜜','C'代表'可乐'……需要判断字符串属于哪种饮料,并对数据分类聚合统计。
类似SQL的:
select
饮料
,count(1)
from 表
group by 饮料
每个excel文件前n行都有一些备注信息和空行,直到第n+1行开始才是真正的结构化数据。需要在读取的时候跳过
导包:
import pandas as pd
from collections import defaultdict
用pandas包读excel文档,把文档数据读成DataFrame形式,并跳过前7行:
df1 = pd.read_excel('待清洗数据/文件1.xlsx',skiprows=7)
df2 = pd.read_excel('待清洗数据/文件2.xlsx',skiprows=7)
筛选标签,只保留需要的标签的数据:
注:这里嵌套使用的是布尔索引;df类型的数据,可以直接使用列名作为索引,反而不能直接用数字索引。
df1 = df1[df1['水果'] == '桔子']
df2 = df2[df2['水果'] == '桔子']
判断唯一:
有多少需要判断的字段都可以扩增 if else ,并且还可以顺便看下唯一数据的总量。
if df1['测试号'].nunique() != len(df1):
print('文档中测试号字段不唯一')
else:
print('文档中测试号字段唯一')
print('共有{0}张保单'.format(len(df1)))
print('*****************************')
if df1['其他需要判别的唯一字段'].nunique() != len(df1):
print('不唯一')
else:
print('唯一')
print('共有{0}条不重复数据'.format(len(df1)))
匹配字段:
同上,如果需要匹配多个字段,只需要继续添加 if else
match1 = df1.merge(df2, on='id号', how='outer', indicator=True)
not_match1 = match1[match1['_merge'] != 'both']
if not_match1.empty:
print('两个文档中id号字段完全匹配')
else:
print('以下为不匹配数据:')
print(not_match1[['id号', '_merge']])
判断字符:
drink_dict = {'A': '牛奶', 'B': '蜂蜜', 'C': '可乐'}
drink_count = defaultdict(int)
for plate_num in df1['有意义码']:
if plate_num[0] == '饮' : # 根据实际情况,这个判断可以不加
drink = drink_dict[plate_num[1]]
drink_count[drink] += 1
print(f'{plate_num}: {drink}')
else:
break
for drink, count in drink_count.items():
print(f'{drink}: {count}')
完