python - 为什么 numpy select 比通过 apply 方法的自定义函数慢?

标签 python pandas numpy

说,我有以下数据框:

df = pd.DataFrame({'a':['a','b','c (not a)', 'this is (random)']*10000})
我想产生以下输出:
array(['same as column', 'b', 'c', 'this is']*10000, dtype=object)
为此,我定义了下面的函数并通过 pandas apply 方法传递它。
def fn(x):
    if ' (' in x:
        return x.split(' (')[0]
    elif x=='a':
        return 'same as column'
    else:
        return x

df['a'] = df['a'].apply(fn)
然后,其他人建议我使用矢量化,所以我使用下面的代码来生成我想要的输出。
df = np.select([df['a'].str.contains(' \('), df['a']=='a'], 
               [df['a'].str.split(' \(').str[0], 'same as column'], 
               default=df['a'])
这个矢量化版本的运行速度明显变慢,而不是运行得更快。21.4 ms ± 1.87 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)对于应用方法116 ms ± 21.7 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)用于矢量化
这里发生了什么?这正常吗(我认为矢量化是可用的最快选项)?还是我的代码有问题?

最佳答案

您在基准测试中比较不同的实现并得出错误的结论。相关因素是pandas str函数不是矢量化的,而是隐式循环。
使用 colab 实例,这些是您的基准测试的结果

%%timeit
df['a'].apply(fn)
100 loops, best of 3: 8.79 ms per loop
%%timeit
np.select([df['a'].str.contains(' \('), df['a']=='a'], 
    [df['a'].str.split(' \(').str[0], 'same as column'], 
    default=df['a'])
10 loops, best of 3: 51.3 ms per loop
如果我们想知道时间花在哪里
%%timeit
df['a'].str.contains(' \(')
df['a'].str.split(' \(').str[0]
10 loops, best of 3: 48.2 ms per loop
最后比较python的string splitpandas str.split
%timeit df['a'].str.split(' \(').str[0]
%timeit [x.split(' (')[0] for x in df['a'].to_list()]
10 loops, best of 3: 36.3 ms per loop
100 loops, best of 3: 6.59 ms per loop

关于python - 为什么 numpy select 比通过 apply 方法的自定义函数慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65507935/

相关文章:

python - 在 IPython 中释放巨大的 numpy 数组的内存

python - 使用 BeautifulSoup 解析标签

python - 从 github python 下载和访问数据

python - 如何使用 pd.melt 转换数据框

python - pandas 根据条件反转数字

python-3.x - 如何在 Numpy/MatplotLib 中可视化线性规划(具有任意不等式)的可行区域?

python - 获取数组范围的开始和结束

python - 使用 urllib 下载 HTTPS 页面,错误 :14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error

python - 值错误 : 'object too deep for desired array'

python - 列表中可变大小的 block 的总和,其中其他列表给出了大小