在 Pandas 中加入两个大型数据集的最佳方法

Posted

技术标签:

【中文标题】在 Pandas 中加入两个大型数据集的最佳方法【英文标题】:Best way to join two large datasets in Pandas 【发布时间】:2016-10-11 22:31:02 【问题描述】:

我正在从需要连接的两个不同数据库中下载两个数据集。当我将它们存储为 CSV 时,它们每个分别约为 500MB。分别装入内存,但是当我同时加载两者时,有时会出现内存错误。当我尝试将它们与熊猫合并时,我肯定会遇到麻烦。

在它们上进行外部联接的最佳方法是什么,以免出现内存错误?我手头没有任何数据库服务器,但如果有帮助,我可以在我的计算机上安装任何类型的开源软件。理想情况下,我仍然想只在 pandas 中解决它,但不确定这是否可能。

澄清一下:合并是指外部连接。每个表有两行:产品和版本。我想检查哪些产品和版本仅在左表、仅右表和两个表中。我用

pd.merge(df1,df2,left_on=['product','version'],right_on=['product','version'], how='outer')

【问题讨论】:

你运行的是什么操作系统? 请更详细地说明您希望此程序执行的操作以及连接应该在哪些字段上起作用。在最好的情况下,您可以将两个 CSV 文件合并在一起(逐行)。此外,如果您可以发布导致内存错误的代码,这将有很大帮助。 我在原问题中添加了更多细节 【参考方案1】:

这似乎是 dask 设计的任务。从本质上讲,dask 可以在内核外执行pandas 操作,因此您可以使用不适合内存的数据集。 dask.dataframe API 是pandas API 的一个子集,因此不应该有太多的学习曲线。请参阅Dask DataFrame Overview 页面了解更多 DataFrame 特定详细信息。

import dask.dataframe as dd

# Read in the csv files.
df1 = dd.read_csv('file1.csv')
df2 = dd.read_csv('file2.csv')

# Merge the csv files.
df = dd.merge(df1, df2, how='outer', on=['product','version'])

# Write the output.
df.to_csv('file3.csv', index=False)

假设'product''version' 是仅有的列,将merge 替换为:

df = dd.concat([df1, df2]).drop_duplicates()

我不完全确定这是否会更好,但显然未在索引上完成的合并在dask 中是“慢速”,因此值得一试。

【讨论】:

很好,但是如果 df1 也不适合内存怎么办? 这就是dask 的全部意义所在。它进行核外操作,因此您可以处理不适合内存的数据。它实质上将方便数据集的大小从“适合内存”扩展到“适合磁盘”。 有没有办法用大数据框做数据透视表? Dask 似乎没有提供该功能 Dask 似乎有很多问题。即使是简单的合并操作也会给出错误消息。列名末尾包含 \r 等。还有其他选择吗? Dask 正在开发中,它也不支持多索引。 :(【参考方案2】:

我建议你使用像 mysql 这样的 RDBMS...

所以你需要先load your CSV files into tables。

之后您可以执行检查:

哪些产品和版本仅在左表中

SELECT a.product, a.version
FROM table_a a
LEFT JOIN table_b b
ON a.product = b.product AND a.version = b.version
WHERE b.product IS NULL;

哪些产品和版本只在正确的表中

SELECT b.product, b.version
FROM table_a a
RIGHT JOIN table_b b
ON a.product = b.product AND a.version = b.version
WHERE a.product IS NULL;

两者都有

SELECT a.product, a.version
FROM table_a a
JOIN table_b b
ON a.product = b.product AND a.version = b.version;

Configure your MySQL Server,使其至少使用 2GB 内存

您可能还想为您的表使用 MyISAM 引擎,在这种情况下检查 this

与 Pandas 相比,它的运行速度可能会慢一些,但绝对不会出现内存问题。

另一种可能的解决方案:

增加内存 在多个集群节点上使用 Apache Spark SQL(分布式 DataFrame) - 虽然增加 RAM 会便宜得多

【讨论】:

谢谢。但是为什么操作系统不能用硬盘空间扩展RAM呢? 通常应该可以(至少对于 Windows 和 Linux,我没有使用 Mac OS 的经验),但效果极差 我使用的是 Windows,它显然没有使用我的 SSD HD 作为扩展 @nickpick,您是否将 SSD HD 配置为页面文件(交换文件)的单一来源?但正如我在答案中所说 - 使用 MySQL 或物理增加 RAM 会更好 好的,SQLite 呢?

以上是关于在 Pandas 中加入两个大型数据集的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

在 pandas 中加入数据帧时的内存问题(时间索引)

在 python 中处理大型数据集的最佳方法

pandas.concat 和 numpy.append 的大型数据集的内存错误

pandas.concat 和 numpy.append 的大型数据集的内存错误

如何在 Pandas 中加入 2 列词嵌入

如何避免大型数据集的Pandas DataFrame中的for循环