这几天工作中需要做个数据分析工作。一开始考虑直接用python内置库,简单的open file,但是不太方便,后来就选择了pandas。之前只是了解了pandas,但是没有实际操作过,为了完成这个需求,我各种百度,终于完成了。实现历程不多说,简单的说流程吧。
需求是,从网站上下载原始文件,自己做数据处理,然后和开发解析过的数据做对比!对比3个月的数据,下载原始文件的天数要加上8个小时,用字段去查询分组得到数据,然后写入自己的文件就行了。说起来简单,但是做起来,呃。。。。
pandas读文件,我的是dat类型文件,也可以用read_csv,一开始我是单个文件读,
import pandas as pd
#因为我的是无列名的数据,所以加了给cal列名
reader = pd.read_csv(r'XX.dat',iterator=True,names=['cal'])
dl[]
data = reader['cal'].str.split('|', expand=True) # +'\t' #将一列用|分割
rename_index = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
data.columns = rename_index #给列名重命名
data = data[(data[2] == 'XXX') | (data[2] == 'XXX2') | (data[2] == 'XXX3') | (data[2] == 'XXX4') | (data[2] == 'XXXX5')] #筛选自己需要的数据
#print(chunk)
dl.append(data)
后来读了一整个7月的,发现麻烦死了,所以就想办法批量读,但是批量读就会带来文件数据量太大的问题,我的一个dat就差不多3百万数据,一个月加起来就将近1亿条数据,一开始跑,本地电脑一下就被卡死了,又一通找,终于找到方法
import pandas as pd
import datetime
import time
import numpy as np
import openpyxl
import glob, os
path = r'XXXX' #文件夹路径
file = glob.glob(os.path.join(path, "*.dat"))
total=[]
for f in file:
df = pd.read_csv(f, iterator=True, names=['cal'])
loop = True
chunkSize = 300000
dl = []
while loop:
try:
chunk = df.get_chunk(chunkSize)
chunk = chunk['cal'].str.split('|', expand=True) # +'\t'
rename_index = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
chunk.columns = rename_index
chunk = chunk[(chunk['ICCID'] == 'XXX') | (chunk['ICCID'] == 'XXX2') | (chunk['ICCID'] == 'XXX3') | (chunk['ICCID'] == 'XXX4') | (chunk['ICCID'] == 'XXX5')]
dl.append(chunk)
except StopIteration:
loop = False
print('iteration is stopped')
df = pd.concat(dl)
total.append(df)
data=pd.concat(total)
print(data)
解决了读取文件,就要解决类型转换了,因为pandas读取dat文件的默认类型都是object,要把对应的日期列,及数据列改成datetime和int64类型,则有:
data[12]=pd.to_numeric(data[12]) #由object转换为数字
data[8]=pd.to_datetime(data[8]) #由object转换为datetime
#如果不将数据转为str,则导入的id如果超过11位数字就变为科学计算,所以我将id的类型一并转为str
def deal_str(data):
data = str(data)+'\t'
return data
data[2]=data[2].map(deal_str)
之后就是按要求的字段进行筛选,我的是用不同id、不同日期筛选后,将数量加总:
data_sum=data.groupby([2,8])[12].sum()
data_after_cal=data.groupby([2,8])[12].sum()/1024
一开始就以为这样就直接存文件了,但是直接存,是不会保存字段名的,就如我要筛选的是2,8,12的数据出来,写入到结果文件要包含列名为2,8,12,但是很遗憾,直接to_csv是不含列名的。,终于找到两种方法,这第一种方法,额,我试了不行
#data_sum=pd.DataFrame({'data_sum':data_sum},index=[1]).reset_index()
#data_after_cal=pd.DataFrame({'data_after_cal':data_after_cal},index=[1]).reset_index()
还好,第二中方法ok:
data_sum=data_sum.reset_index()
data_after_cal=data_after_cal.reset_index()
然后就存到文件了,但是我想把筛选后但没有做分组的数据和已经做分组并计算了总数的结果存到同一个文件的两个sheet表里,这个就简单多了,百度一搜就看到答案
with pd.ExcelWriter(r'XXXX.xls') as wr:
data_after_cal.to_excel(wr, sheet_name='除以1024后的总数', index=False, encoding='utf-8')
df.to_excel(wr,sheet_name='筛选后的数据', index=False,encoding='utf-8')
data_sum.to_excel(wr,sheet_name='分组后的总数', index=False,encoding='utf-8')
wr.save()
至此完成!!!总的来说,磕磕绊绊,但是功夫不负有心人,写这个博文记录自己的成长,也希望能帮到大家。