一般来说,用pandas处理小于100兆的数据,性能不是问题。当用pandas来处理100兆至几个G的数据时,将会比较耗时,同时会导致程序因内存不足而运行失败。
当然,像Spark这类的工具能够胜任处理100G至几个T的大数据集,但要想充分发挥这些工具的优势,通常需要比较贵的硬件设备。而且,这些工具不像pandas那样具有丰富的进行高质量数据清洗、探索和分析的特性。对于中等规模的数据,我们的愿望是尽量让pandas继续发挥其优势,而不是换用其他工具。
本文我们讨论pandas的内存使用,展示怎样简单地为数据列选择合适的数据类型,就能够减少dataframe近90%的内存占用。
处理棒球比赛记录数据
我们将处理130年的棒球甲级联赛的数据,数据源于
Retrosheet(http://www.retrosheet.org/gamelogs/index.html)
原始数据放在127个csv文件中,我们已经用csvkit
(https://csvkit.readthedocs.io/en/1.0.2/)
(https://data.world/dataquest/mlb-game-logs)
我们从导入数据,并输出前5行开始:
我们将一些重要的字段列在下面:date- 比赛日期
v_name- 客队名
v_league- 客队联赛
h_name- 主队名
h_league- 主队联赛
v_score- 客队得分
h_score- 主队得分
v_line_score- 客队线得分, 如010000(10)00.
h_line_score- 主队线得分, 如010000(10)0X.
park_id- 主办场地的ID
attendance- 比赛出席人数
我们可以用Dataframe.info()方法来获得我们dataframe的一些高level信息,譬如数据量、数据类型和内存使用量。
这个方法默认情况下返回一个近似的内存使用量,现在我们设置参数memory_usage为‘deep’来获得准确的内存使用量:
我们可以看到它有171907行和161列。pandas已经为我们自动检测了数据类型,其中包括83列数值型数据和78列对象型数据。对象型数据列用于字符串或包含混合数据类型的列。
由此我们可以进一步了解我们应该如何减少内存占用,下面我们来看一看pandas如何在内存中存储数据。
Dataframe对象的内部表示
在底层,pandas会按照数据类型将列分组形成数据块(blocks)。下图所示为pandas如何存储我们数据表的前十二列: