【问题标题】:pandas inner join performance issue熊猫内部连接性能问题
【发布时间】:2016-08-27 07:17:54
【问题描述】:

我有两个 csv 文件,我将它们加载到 pandas 数据框中。一个文件很大,大约 10M 行和 20 列(所有字符串类型),大小约为 1G 字节,另一个文件很小,大约 5k 行,5 列,大小约为 1M。我想通过两个数据框之间的单个公共列进行内部连接。

我就是这样加入的,

mergedDataSet = pd.merge(smallDataFrame, largeDataFrame, on='uid', how='inner')

如果我对大数据集的 1% 进行采样,我尝试过,程序运行顺利,没有任何问题,并且在 5 秒内完成,所以我验证了我的代码的功能应该没问题。

但如果我加入真正的大数据集,程序将在大约 20-30 秒后终止,错误消息为Process finished with exit code 137 (interrupted by signal 9: SIGKILL)。我在 Mac OSX 上使用带有 miniconda 的 Python 2.7,我从 PyCharm 运行。我的机器有 16G 内存,远大于 1G 文件的大小。

想知道是否有任何想法来调整 pandas 中数据框连接的性能,或任何其他用于内部连接的快速解决方案?

我的另一个困惑是,为什么程序被杀死了?由谁以及为什么原因?

编辑 1,在进行内部连接时在 /var/log/system.log 中捕获错误,

Aug 27 11:00:18 foo-laptop com.apple.CDScheduler[702]: Thermal pressure state: 1 Memory pressure state: 0
Aug 27 11:00:18 foo-laptop com.apple.CDScheduler[47]: Thermal pressure state: 1 Memory pressure state: 0
Aug 27 11:00:33 foo-laptop iTerm2[43018]: Time to encode state for window <PseudoTerminal: 0x7fb3659d3960 tabs=1 window=<PTYWindow: 0x7fb3637c0c80 frame=NSRect: {{0, 0}, {1280, 800}} title=5. tail alpha=1.000000 isMain=1 isKey=1 isVisible=1 delegate=0x7fb3659d3960>>: 0.02136099338531494
Aug 27 11:00:41 foo-laptop iTerm2[43018]: Time to encode state for window <PseudoTerminal: 0x7fb3659d3960 tabs=1 window=<PTYWindow: 0x7fb3637c0c80 frame=NSRect: {{0, 0}, {1280, 800}} title=5. tail alpha=1.000000 isMain=0 isKey=0 isVisible=1 delegate=0x7fb3659d3960>>: 0.01138699054718018
Aug 27 11:00:46 foo-laptop kernel[0]: low swap: killing pid 92118 (python2.7)
Aug 27 11:00:46 foo-laptop kernel[0]: memorystatus_thread: idle exiting pid 789 [CallHistoryPlugi]
Aug 27 11:00:56 foo-laptop iTerm2[43018]: Time to encode state for window <PseudoTerminal: 0x7fb3659d3960 tabs=1 window=<PTYWindow: 0x7fb3637c0c80 frame=NSRect: {{0, 0}, {1280, 800}} title=5. tail alpha=1.000000 isMain=0 isKey=0 isVisible=1 delegate=0x7fb3659d3960>>: 0.01823097467422485
Aug 27 11:00:58 foo-laptop kernel[0]: process WeChat[85077] caught causing excessive wakeups. Observed wakeups rate (per sec): 184; Maximum permitted wakeups rate (per sec): 150; Observation period: 300 seconds; Task lifetime number of wakeups: 2193951
Aug 27 11:00:58 foo-laptop com.apple.xpc.launchd[1] (com.apple.ReportCrash[92123]): Endpoint has been activated through legacy launch(3) APIs. Please switch to XPC or bootstrap_check_in(): com.apple.ReportCrash
Aug 27 11:00:58 foo-laptop ReportCrash[92123]: Invoking spindump for pid=85077 wakeups_rate=184 duration=245 because of excessive wakeups
Aug 27 11:01:03 foo-laptop com.apple.CDScheduler[702]: Thermal pressure state: 0 Memory pressure state: 0
Aug 27 11:01:03 foo-laptop com.apple.CDScheduler[47]: Thermal pressure state: 0 Memory pressure state: 0

问候, 林

【问题讨论】:

  • 也许 'uid' 列中的值是多对多的,例如对于值 1,您在第 1 帧中获得 100 条记录,在第 2 帧中获得 10 条记录,因此连接会产生 1000 条记录。可能发生的情况是您的框架变得如此之大,以至于无法放入内存或占用所有资源。
  • 我同意 @AndreyVykhodtsev - 如果您在 uid 列中有重复项 - 它们将在合并的 DF 中相乘(例如,如果您有 3x uids 值 1 合二为一DF 和 2x uids 在第二个 DF 中的值为 1 - 在合并的 DF 中您将有 6 行uid==1)。很可能您的 Python 进程被 OOM(内存不足)杀手杀死 - 检查 /var/log/system.log (/var/log/messages)
  • 是的,只要检查两边的 df['uid'].value_counts() 即可。或 df1[df1.uid.isin(df2.uid.unique())]['uid'].value_counts()
  • @AndreyVykhodtsev,看来您的猜测是正确的。您介意添加回复,以便我可以将其标记为答案以造福他人吗?顺便说一句,你能解释一下这句话是什么意思df1[df1.uid.isin(df2.uid.unique())]['uid'].value_counts(),被isin(df2.uid.unique())] 部分弄糊涂了。
  • @AndreyVykhodtsev,我同意 Lin Ma - 如果您将其作为答案发布(最好是一个小例子),它可能会帮助其他人;)

标签: python performance python-2.7 pandas dataframe


【解决方案1】:

检查两边“uid”列的基数。您的联接很可能使数据成倍增加。例如,如果您在 dataframe1 的 100 条记录和 dataframe2 的 10 条记录中有值为 1 的 uid,则您的联接将产生 1000 条记录。

要检查基数,我会执行以下操作:

df1[df1.uid.isin(df2.uid.unique())]['uid'].value_counts()
df2[df2.uid.isin(df1.uid.unique())]['uid'].value_counts()

此代码将检查 'uid' 的值是否存在于其他框架的 uid 中并且是否有重复项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多