是否有直接运行pandas.DataFrame.isin的直接方法?


25

我有一个建模和评分程序,该程序大量使用了DataFrame.isin熊猫的功能,在数千个特定页面的每个页面中搜索单个用户的Facebook“喜欢”记录列表。这是程序中最耗时的部分,而不是建模或评分部分,这仅仅是因为它仅在一个内核上运行,而其余部分同时在几十个内核上运行。

尽管我知道我可以手动将数据帧分解为多个块并并行运行该操作,但是有没有直接的自动方法?换句话说,是否有任何一种程序包可以识别我正在执行的一项容易委派的操作并自动分发它?也许这要求太多,但是过去我对Python中已有的功能感到惊讶,因此我认为值得提出。

任何其他有关如何完成此操作的建议(即使不是通过某些神奇的独角兽程序包也是如此!)也将不胜感激。主要是,只是试图找到一种方法,以在每次运行中节省15至20分钟的时间,而无需花费等量的时间来编码解决方案。


您的值列表有多大?您是否尝试过将其作为一组?对于并行性,您可能对Joblib感兴趣。它易于使用,可以加快计算速度。与大量数据一起使用。
oao 2014年

另一种选择是将您的问题重新设计为联接。加入在熊猫更快stackoverflow.com/questions/23945493/...
布莱恩Spiering

还有一个选择是使用np.in1d,它也是更快的stackoverflow.com/questions/21738882/fast-pandas-filtering
Brian Spiering

Answers:


8

不幸的是,熊猫还没有实现并行化。如果您想参与此功能的开发,可以加入github问题

我不知道有什么“魔术独角兽包”用于此目的,所以最好的办法就是编写自己的解决方案。但是,如果您仍然不想花时间去学习新的东西,可以尝试MongoDB内置的两种方法(map reduce和agg框架)。参见mongodb_agg_framework




0

这个问题有一个关于pandas apply函数并行化的更常见版本-所以这是一个令人耳目一新的问题:)

首先,我想提一下swifter,因为您需要一个“打包”的解决方案,并且它在大多数有关熊猫并行化的问题上都出现了。

但是,我仍然想分享我的个人要点代码,因为在使用DataFrame几年后,我从未找到100%并行化解决方案(主要是apply函数),而且我总是不得不为我的“手册”代码。

多亏您的支持,我才得以通过其名称来支持任何(理论上)DataFrame方法(因此您不必保留isin,apply等的版本)的通用性。

我使用python 2.7和3.6在“ isin”,“ apply”和“ isna”函数上进行了测试。它不到20行,我遵循了“ subset”和“ njobs”之类的熊猫命名约定。

我还添加了一个与“ isin”的等效代码进行时间比较的功能,它的速度似乎比此要点要慢X2倍。

它包括2个功能:

df_multi_core-这是您调用的那个。它接受:

  1. 您的df对象
  2. 您要调用的函数名称
  3. 可以执行该功能的列的子集(有助于减少时间/内存)
  4. 并行运行的作业数(所有内核为-1或忽略)
  5. df函数接受的其他任何变形(例如“轴”)

_df_split-这是一个内部帮助器函数,必须全局定位到正在运行的模块(Pool.map是“与位置相关的”),否则我将在内部定位它。

这是我的要旨中的代码(我将在其中添加更多的pandas功能测试):

import pandas as pd
import numpy as np
import multiprocessing
from functools import partial

def _df_split(tup_arg, **kwargs):
    split_ind, df_split, df_f_name = tup_arg
    return (split_ind, getattr(df_split, df_f_name)(**kwargs))

def df_multi_core(df, df_f_name, subset=None, njobs=-1, **kwargs):
    if njobs == -1:
        njobs = multiprocessing.cpu_count()
    pool = multiprocessing.Pool(processes=njobs)

    try:
        splits = np.array_split(df[subset], njobs)
    except ValueError:
        splits = np.array_split(df, njobs)

    pool_data = [(split_ind, df_split, df_f_name) for split_ind, df_split in enumerate(splits)]
    results = pool.map(partial(_df_split, **kwargs), pool_data)
    pool.close()
    pool.join()
    results = sorted(results, key=lambda x:x[0])
    results = pd.concat([split[1] for split in results])
    return results

贝娄(Bellow)是并行isin的测试代码,比较了本机,多核要害和敏捷性能。在具有8个物理内核的I7机器上,我的速度提高了大约X4倍。我很想听听您从真实数据中得到什么!

from time import time

if __name__ == '__main__': 
    sep = '-' * 50

    # isin test
    N = 10000000
    df = pd.DataFrame({'c1': np.random.randint(low=1, high=N, size=N), 'c2': np.arange(N)})
    lookfor = np.random.randint(low=1, high=N, size=1000000)

    print('{}\ntesting pandas isin on {}\n{}'.format(sep, df.shape, sep))
    t1 = time()
    print('result\n{}'.format(df.isin(lookfor).sum()))
    t2 = time()
    print('time for native implementation {}\n{}'.format(round(t2 - t1, 2), sep))

    t3 = time()
    res = df_multi_core(df=df, df_f_name='isin', subset=['c1'], njobs=-1, values=lookfor)
    print('result\n{}'.format(res.sum()))
    t4 = time()
    print('time for multi core implementation {}\n{}'.format(round(t4 - t3, 2), sep))


    t5 = time()
    ddata = dd.from_pandas(df, npartitions=njobs)
    res = ddata.map_partitions(lambda df: df.apply(apply_f, axis=1)).compute(scheduler='processes')
    t6 = time()
    print('result random sample\n{}'.format(res.sample(n=3, random_state=0)))
    print('time for dask implementation {}\n{}'.format(round(t6 - t5, 2), sep))

--------------------------------------------------
testing pandas isin on (10000000, 2)
--------------------------------------------------
result
c1    953213
c2    951942
dtype: int64
time for native implementation 3.87
--------------------------------------------------
result
c1    953213
dtype: int64
time for multi core implementation 1.16
--------------------------------------------------
result
c1    953213
c2    951942
dtype: int64
time for dask implementation 2.88

@Therriault我添加了一个与dask的比较isin-似乎代码片段对'isin'最为有效-比dask快〜X1.75倍(相比,该apply函数仅比dask快5%快)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.