我正在比较两个数据帧以确定 df1 中的行是否开始于 df2 中的任何行。 df1 以千为单位,df2 以百万为单位。
这可以完成工作,但速度相当慢。
df1['name'].map(lambda x: any(df2['name'].str.startswith(x)))
在 df1 的子集(10 项)上运行时,结果如下:
35243 True
39980 False
40641 False
45974 False
53788 False
59895 True
61856 False
81083 True
83054 True
87717 False
Name: name, dtype: bool
Time: 57.8873581886 secs
当我将 df2 转换为列表时,它运行得更快:
df2_list = df2['name'].tolist()
df1['name'].map(lambda x: any(item.startswith(x + ' ') for item in df2_list))
35243 True
39980 False
40641 False
45974 False
53788 False
59895 True
61856 False
81083 True
83054 True
87717 False
Name: name, dtype: bool
Time: 33.0746209621 secs
为什么遍历列表比遍历系列更快?
最佳答案
any()
将在获得 True
值时提前返回,因此 startswith()
调用少于 数据框
版本。
这是一个使用 searchsorted()
的方法:
import random, string
import pandas as pd
import numpy as np
def randomword(length):
return ''.join(random.choice(string.ascii_lowercase) for i in range(length))
xs = pd.Series([randomword(3) for _ in range(1000)])
ys = pd.Series([randomword(10) for _ in range(10000)])
def is_any_prefix1(xs, ys):
yo = ys.sort_values().reset_index(drop=True)
y2 = yo[yo.searchsorted(xs)]
return np.fromiter(map(str.startswith, y2, xs), dtype=bool)
def is_any_prefix2(xs, ys):
x = xs.tolist()
y = ys.tolist()
return np.fromiter((any(yi.startswith(xi) for yi in y) for xi in x), dtype=bool)
res1 = is_any_prefix1(xs, ys)
res2 = is_any_prefix2(xs, ys)
print(np.all(res1 == res2))
%timeit is_any_prefix1(xs, ys)
%timeit is_any_prefix2(xs, ys)
输出:
True
100 loops, best of 3: 17.8 ms per loop
1 loop, best of 3: 2.35 s per loop
速度提高了 100 倍。
关于python - Pandas Dataframe 性能与列表性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39736195/