一次较大规模数据处理的经历 PYTHON版

前一段时间遇到了一次数据处理的问题,原始数据是CSV数据(逗号分隔),近百万条,要根据不同的公式对每一条进行计算。在使用EXCEL进行计算时,只要一动就会重新计算,而且时常出现无响应的状态,有好几次强行关闭导致重头再来。

考虑到数据量大,使用EXCEL计算可能不适合,才导致不停地死机。最初打算使用数据库来计算,没有数据量的限制,在查询和更新的时候速度很快。但是每一行计算的时候,对于结果不是简单地赋值,而是分段乘以比例再累加计算(类似于电费阶梯计算),思来想去,不知道如何使用SQL语句实现,有可能需要很多个不同的语句。与其这么麻烦,不如写程序来实现,于是打算使用现在很流行的PYTHON语言来处理,一是简单易学,二是有丰富的模块,说不定就有解决该问题的方法。

经过了解,有一个模块PANDAS能够方便的处理CSV数据,而且非常灵活,打算试一试,最终成功解决了问题,现将过程记录以便以后再使用。

##导入numpy和pandas模块
import numpy as np
import pandas as pd
##设置显示的列数,全部显示,方便查看内容
pd.set_option('display.max_columns',None)
##每一列的标题
title=('列1','列2','列3','列4')
##设置每一列的数据类型
##不设置会自动识别,但是有可能出错
dataType={'列1':str,'列2':str,
          '列3':str,'列4':float}
##读取数据文件
##names指定每一列的标题
##encoding设置文件编码
##index_col=False,不使用第一列数据当索引,这时系统会对每一行数据生成索引,编号从零开始,而且索引号不是行号,即使排序后也不发生变化
##dtype设置每一列数据类型
data=pd.read_csv('data.csv',names=title,encoding='GBK',index_col=False,dtype=dataType)
##添加结果列,全部赋值为0
data['结果']=0
##编写对每一行计算函数,后面调用
def calc(row):
    result=0
    value=row['value']
    ##根据列1和列2的具体情况,分别设置阶梯分段计算语句
    ##以下为其中一种情况
    if value<200:result=0
    elif value<1000:result=(value-200)*0.6
    elif value<10000:result=(1000-200)*0.6\
                        +(value-1000)*0.7
    ........
    return result
##使用calc函数对表的每一行计算,并将结果赋值给结果列
##calc为上面定义的回调函数
##axis,1是对每一行计算;0是每一列
data['结果']=data.apply(calc,axis=1)
##对于计算的结果,按照列3聚合计算,方式为求和,当然除了求和,还有其他很多种类,比如次数、平均值等,下面对计算结果按照列3进行汇总
##类似于SQL句的select 列3,sum(结果)
##           from data
##           groupby 列3
result=data.groupby('列3').agg({'结果':np.sum})

以上过程已经基本解决了问题,对每一行计算结果后汇总,或者又进行简单地计算再汇总。随后又进行了新的尝试,上面每一条数据根据列1和列2的不同,分别计算结果,假设对于每一个列3的数据,第一次、第二次、第三次的计算方式又不一样,因此又增加了一列’次数’,并针对此处又编写了公式(在calc函数里面增加判断条件)。这里记录一下如何计算每一个列3信息的次数。

##首先调取所有列3的数据,也就是取唯一值
##类似于SQL句的select distinct 列3
##           from data
ids=data['列3'].unique()
##增加记录次数的列,全部赋值为0
data['次数']=0
##针对每一个列3的数据,列出相关所有的记录,按照时间排序,根据每一条记录的索引号(排序之后不会发生变化),来更新次数信息,这里以一个列3的数据举例:

##取出列3信息为ids[0]的所有记录,并按照时间排序,假设数据中有'时间'列
##排序有升序降序之分,通过ascending区分,此处按默认排序
ids0=data[data['列3']==ids[0]].sort_value('时间')

##此时已排序,取出所有ids[0]记录的索引,并按照1,2,3,4的顺序赋值给次数列
i=1
for iIndex in ids0.index:
      data.loc[iIndex,'次数']=i
      i=i+1

##将结算结果保存成EXCEL
##参数为文件名,编码格式
data.to_excel("result.xlsx",encoding="GBK")

EXCEL虽然慢,但是并非没有解决的办法,因此重新用EXCEL解决了一遍,详见《一次较大规模数据处理的经历 EXCEL版》。

一次较大规模数据处理的经历 PYTHON版》有1个想法

发表评论

您的电子邮箱地址不会被公开。