使用Python Pandas处理亿级数据的方法


Posted in Python onJune 24, 2019

在数据分析领域,最热门的莫过于Python和R语言,此前有一篇文章《别老扯什么Hadoop了,你的数据根本不够大》指出:只有在超过5TB数据量的规模下,Hadoop才是一个合理的技术选择。这次拿到近亿条日志数据,千万级数据已经是关系型数据库的查询分析瓶颈,之前使用过Hadoop对大量文本进行分类,这次决定采用Python来处理数据:

硬件环境

  • CPU:3.5 GHz Intel Core i7
  • 内存:32 GB HDDR 3 1600 MHz
  • 硬盘:3 TB Fusion Drive

数据分析工具

  • Python:2.7.6
  • Pandas:0.15.0
  • IPython notebook:2.0.0

源数据如下表所示:

  Table Size Desc
ServiceLogs 98,706,832 rows x 14 columns 8.77 GB 交易日志数据,每个交易会话可以有多条交易
ServiceCodes 286 rows × 8 columns 20 KB 交易分类的字典表

数据读取

启动IPython notebook,加载pylab环境:

ipython notebook --pylab=inline

Pandas提供了IO工具可以将大文件分块读取,测试了一下性能,完整加载9800万条数据也只需要263秒左右,还是相当不错了。

import pandas as pd
reader = pd.read_csv('data/servicelogs', iterator=True)
try:
  df = reader.get_chunk(100000000)
except StopIteration:
  print "Iteration is stopped."

  1百万条 1千万条 1亿条
ServiceLogs 1 s 17 s 263 s

使用不同分块大小来读取再调用pandas.concat连接DataFrame,chunkSize设置在1000万条左右速度优化比较明显。

loop = True
chunkSize = 100000
chunks = []
while loop:
  try:
    chunk = reader.get_chunk(chunkSize)
    chunks.append(chunk)
  except StopIteration:
    loop = False
    print "Iteration is stopped."
df = pd.concat(chunks, ignore_index=True)

下面是统计数据,Read Time是数据读取时间,Total Time是读取和Pandas进行concat操作的时间,根据数据总量来看,对5~50个DataFrame对象进行合并,性能表现比较好。

Chunk Size Read Time (s) Total Time (s) Performance100,000224.418173261.358521200,000232.076794256.6741541,000,000213.128481234.934142√√2,000,000208.410618230.006299√√√5,000,000209.460829230.939319√√√10,000,000207.082081228.135672√√√√20,000,000209.628596230.775713√√√50,000,000222.910643242.405967100,000,000263.574246263.574246

使用Python Pandas处理亿级数据的方法

如果使用Spark提供的Python Shell,同样编写Pandas加载数据,时间会短25秒左右,看来Spark对Python的内存使用都有优化。

数据清洗

Pandas提供了DataFrame.describe方法查看数据摘要,包括数据查看(默认共输出首尾60行数据)和行列统计。由于源数据通常包含一些空值甚至空列,会影响数据分析的时间和效率,在预览了数据摘要后,需要对这些无效数据进行处理。

首先调用DataFrame.isnull()方法查看数据表中哪些为空值,与它相反的方法是DataFrame.notnull(),Pandas会将表中所有数据进行null计算,以True/False作为结果进行填充,如下图所示:

使用Python Pandas处理亿级数据的方法

Pandas的非空计算速度很快,9800万数据也只需要28.7秒。得到初步信息之后,可以对表中空列进行移除操作。尝试了按列名依次计算获取非空列,和DataFrame.dropna()两种方式,时间分别为367.0秒和345.3秒,但检查时发现 dropna() 之后所有的行都没有了,查了Pandas手册,原来不加参数的情况下, dropna() 会移除所有包含空值的行。如果只想移除全部为空值的列,需要加上 axis 和 how 两个参数:

df.dropna(axis=1, how='all')

共移除了14列中的6列,时间也只消耗了85.9秒。

接下来是处理剩余行中的空值,经过测试,在DataFrame.replace()中使用空字符串,要比默认的空值NaN节省一些空间;但对整个CSV文件来说,空列只是多存了一个“,”,所以移除的9800万 x 6列也只省下了200M的空间。进一步的数据清洗还是在移除无用数据和合并上。

对数据列的丢弃,除无效值和需求规定之外,一些表自身的冗余列也需要在这个环节清理,比如说表中的流水号是某两个字段拼接、类型描述等,通过对这些数据的丢弃,新的数据文件大小为4.73GB,足足减少了4.04G!

数据处理

使用DataFrame.dtypes可以查看每列的数据类型,Pandas默认可以读出int和float64,其它的都处理为object,需要转换格式的一般为日期时间。DataFrame.astype()方法可对整个DataFrame或某一列进行数据格式转换,支持Python和NumPy的数据类型。

df['Name'] = df['Name'].astype(np.datetime64)

对数据聚合,我测试了 DataFrame.groupby 和 DataFrame.pivot_table 以及 pandas.merge ,groupby 9800万行 x 3列的时间为99秒,连接表为26秒,生成透视表的速度更快,仅需5秒。

df.groupby(['NO','TIME','SVID']).count() # 分组
fullData = pd.merge(df, trancodeData)[['NO','SVID','TIME','CLASS','TYPE']] # 连接
actions = fullData.pivot_table('SVID', columns='TYPE', aggfunc='count') # 透视表

根据透视表生成的交易/查询比例饼图:

使用Python Pandas处理亿级数据的方法

将日志时间加入透视表并输出每天的交易/查询比例图:

total_actions = fullData.pivot_table('SVID', index='TIME', columns='TYPE', aggfunc='count')
total_actions.plot(subplots=False, figsize=(18,6), kind='area')

使用Python Pandas处理亿级数据的方法

除此之外,Pandas提供的DataFrame查询统计功能速度表现也非常优秀,7秒以内就可以查询生成所有类型为交易的数据子表:

tranData = fullData[fullData['Type'] == 'Transaction']

该子表的大小为[10250666 rows x 5 columns]。在此已经完成了数据处理的一些基本场景。实验结果足以说明,在非“>5TB”数据的情况下,Python的表现已经能让擅长使用统计分析语言的数据分析师游刃有余。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python使用邻接矩阵构造图代码示例
Nov 10 Python
Python中用psycopg2模块操作PostgreSQL方法
Nov 28 Python
Python数据分析之双色球统计单个红和蓝球哪个比例高的方法
Feb 03 Python
Python+OpenCV实现图像融合的原理及代码
Dec 03 Python
使用Python代码实现Linux中的ls遍历目录命令的实例代码
Sep 07 Python
在Python中使用MySQL--PyMySQL的基本使用方法
Nov 19 Python
python matplotlib拟合直线的实现
Nov 19 Python
NumPy中的维度Axis详解
Nov 26 Python
Python print不能立即打印的解决方式
Feb 19 Python
Python 之 Json序列化嵌套类方式
Feb 27 Python
Python异常原理及异常捕捉实现过程解析
Mar 25 Python
python 爬虫基本使用——统计杭电oj题目正确率并排序
Oct 26 Python
Python3批量生成带logo的二维码方法
Jun 24 #Python
解决python文件双击运行秒退的问题
Jun 24 #Python
对python中的控制条件、循环和跳出详解
Jun 24 #Python
django框架自定义模板标签(template tag)操作示例
Jun 24 #Python
解决Python内层for循环如何break出外层的循环的问题
Jun 24 #Python
Python 循环终止语句的三种方法小结
Jun 24 #Python
12个Python程序员面试必备问题与答案(小结)
Jun 24 #Python
You might like
php获取网页内容方法总结
2008/12/04 PHP
php opendir()列出目录下所有文件的实例代码
2016/10/02 PHP
js 获取服务器控件值的代码
2010/03/05 Javascript
JSQL 基于客户端的成绩统计实现方法
2010/05/05 Javascript
js getBoundingClientRect() 来获取页面元素的位置
2010/11/25 Javascript
来自国外的30个基于jquery的Web下拉菜单
2012/06/22 Javascript
javascript的alert box在java中如何显示多行
2014/05/18 Javascript
javascript判断css3动画结束 css3动画结束的回调函数
2015/03/10 Javascript
个人总结的一些JavaScript技巧、实用函数、简洁方法、编程细节
2015/06/10 Javascript
跟我学习javascript的定时器
2015/11/19 Javascript
js中实现字符串和数组的相互转化详解
2016/01/24 Javascript
ros::spin() 和 ros::spinOnce()函数的区别及详解
2016/10/01 Javascript
JavaScript九九乘法口诀表的简单实现
2016/10/04 Javascript
jQuery内容筛选选择器实例代码
2017/02/06 Javascript
Angular.Js中过滤器filter与自定义过滤器filter实例详解
2017/05/08 Javascript
webpack学习教程之publicPath路径问题详解
2017/06/17 Javascript
解析Vue2 dist 目录下各个文件的区别
2017/11/22 Javascript
js限制输入框只能输入数字(onkeyup触发)
2018/09/28 Javascript
关于vue-cli 3配置打包优化要点(推荐)
2019/04/22 Javascript
vue中使用 pako.js 解密 gzip加密字符串的方法
2019/06/10 Javascript
Tensorflow实现卷积神经网络的详细代码
2018/05/24 Python
Python测试模块doctest使用解析
2019/08/10 Python
详解python路径拼接os.path.join()函数的用法
2019/10/09 Python
使用Python构造hive insert语句说明
2020/06/06 Python
Marriott中国:万豪国际酒店查询预订
2016/09/02 全球购物
Kidsroom台湾:来自德国的婴儿用品
2017/12/11 全球购物
C语言中break与continue的区别
2012/07/12 面试题
建筑工程专业毕业生自荐信
2013/10/19 职场文书
社区十八大感言
2014/01/19 职场文书
法学毕业生自我鉴定
2014/01/31 职场文书
科研课题实施方案
2014/03/18 职场文书
大学班级学风建设方案
2014/05/01 职场文书
检察院对照“四风”认真查找问题落实整改措施
2014/09/26 职场文书
统计员岗位职责范本
2015/04/14 职场文书
python模块与C和C++动态库相互调用实现过程示例
2021/11/02 Python
MySQL如何使备份得数据保持一致
2022/05/02 MySQL