【问题标题】:What is the internal implementation of pandas Series.map()?pandas Series.map() 的内部实现是什么?
【发布时间】:2020-05-18 06:13:21
【问题描述】:

我注意到 pandas Series.map() 对于字典映射非常快

准备数据如下:

a=np.random.randint(0,1000,10**5)
s=pd.Series(a)
d=dict(zip(np.arange(1000),np.random.random(1000)))

时间

%timeit -n10 s.map(d)
%timeit -n10 np.vectorize(d.get)(a)

给予

1.42 ms ± 168 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
20.6 ms ± 386 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

第二种方法是我在 stackoverflow 上找到的执行 numpy dict 映射的典型建议。

numpy还有一个典型的解决方案如下

%%timeit -n10 
b = np.copy(a)
for k, v in d.items():
    b[a==k] = v

给了

43.9 ms ± 2.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

它甚至更慢,更糟糕的是,它给出了错误的结果。因为b 是int 类型,所以赋值b[a==k] = v 将返回b 将全为零!

所以我想知道 pandas Series.map() 的内部实现是什么?它是否在 numpy 中实现?具有相同性能的与 Series.map() 等效的 numpy 是什么?我试图深入研究 Series.map() 的源代码,但无法理解。

【问题讨论】:

    标签: python pandas performance numpy


    【解决方案1】:

    Series.map 将调用 _map_values(),这是 pandas/core/base.py 的一部分

    你正在使用一个字典,所以你通过第一个 if is_dict_like(mapper): 子句来获取 mapper,然后在第 1161-1162 行你得到这个基本情况的映射函数(非扩展类型,默认 @ 987654327@)

    else:
        map_f = lib.map_infer
    

    如果您随后转到代码的那部分,在 pandas/_libs/lib.pyx 中找到,您将看到 map_infer is implemented in cython


    正如他们在 cmets 中指出的那样,这对于特定输入来说只有这么快:

    # we can fastpath dict/Series to an efficient map
    # as we know that we are not going to have to yield
    # python types
    

    【讨论】:

    • 非常感谢您的快速回答。我未能追踪 lib.pyx。顺便说一句,在 numpy 中是否可以使用等效的快速方法?
    • @user15964 是的,追溯并不是一件简单的事情。根据 numpy,我不确定,但我知道有一些知识渊博的用户,如果你围绕这个问题创建一个问题,他们可能会有答案。
    • numpy 没有等效的映射器。事实上,它对字典没有什么特别的作用。 vectorize 代码的时间与列表理解的时间相同,np.array([d[i] for i in a])。 Pandas 显然正在使用自定义编译代码的一个或多个函数(通过pyxcython)。
    猜你喜欢
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 1970-01-01
    • 2017-08-01
    相关资源
    最近更新 更多