我正在使用 pandas 矢量化
str.split()
方法来提取从“~”上的拆分返回的第一个元素。 我还尝试使用 df.apply()
与 lambda 和 str.split()
来产生等效的结果。 使用 %timeit
时,我发现 df.apply()
的执行速度比矢量化版本更快。
我读到的有关矢量化的所有内容似乎都表明第一个版本应该具有更好的性能。 有人可以解释一下为什么我会得到这些结果吗?示例:
id facility
0 3466 abc~24353
1 4853 facility1~3.4.5.6
2 4582 53434_Facility~34432~cde
3 9972 facility2~FACILITY2~343
4 2356 Test~23 ~FAC1
上面的数据框大约有 500,000 行,我也测试过大约 100 万行,结果类似。这是一些输入和输出示例:
矢量化
In [1]: %timeit df['facility'] = df['facility'].str.split('~').str[0]
1.1 s ± 54.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Lambda 申请
In [2]: %timeit df['facility'] = df['facility'].astype(str).apply(lambda s: s.split('~')[0])
650 ms ± 52.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
有谁知道我为什么会出现这种行为?
Pandas 字符串方法只是“矢量化”,因为您不必自己编写循环。实际上并没有进行任何并行化,因为字符串(尤其是正则表达式问题)本质上很难(不可能?)并行化。如果你真的想要速度,你实际上应该回到 python 这里。
%timeit df['facility'].str.split('~', n=1).str[0]
%timeit [x.split('~', 1)[0] for x in df['facility'].tolist()]
411 ms ± 10.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
132 ms ± 302 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
有关何时循环比 pandas 函数更快的更多信息,请查看 For 循环与 pandas - 我何时应该关心?.
至于为什么
apply
更快,我相信正在应用的函数apply
(即str.split
)比Series.str.split
内部发生的字符串分裂轻得多。