【问题标题】:Why is pandas .isin much faster than "in"?为什么 pandas .isin 比“in”快得多?
【发布时间】:2020-01-26 00:28:30
【问题描述】:

我正在我的 DataFrame 中创建一个指示列来表示不同列的值是否在列表中。

我的第一次尝试使用了基本的 python“in”运算符,我的进度条显示它需要 83 小时才能运行。然后我尝试使用熊猫“.isin()”,不到一秒钟。我的 DataFrame 有大约 40,000,000 行,我正在搜索的列表有大约 100,000 个项目。该列表已被过滤以删除重复项 (lst=list(set(original_list)))。我比较的项目是大约 20 个字符的字符串。

这是我的第一次尝试(需要 83 小时):

df['indicator']=df['col1'].progress_apply(lambda x: 1 if x in lst else 0)

这是我的第二次尝试(不到一秒):

df['indicator']=df['col1'].isin(tqdm(lst))

谁能解释为什么第二个会导致如此巨大的进步? Why is Pandas .isin() method faster than "=="的答案并没有真正解释。

【问题讨论】:

  • 你的问题应该是Why *isin* faster than *apply(lambda x: x in lst)*,一个是矢量化的,另一个不是。
  • 然后in 使用Series.apply,这是一个循环,但开销更大。 Series.isin 使用了一些复杂的重塑更快的方法。
  • 时间复杂度方面,因为.apply 大致是一个for 循环,所以您的第一行代码具有O(N*M) 复杂性,而您的第二行具有O(max(N, M))(或O(N+M) ) 复杂性,这是一个很大的区别。

标签: python pandas


【解决方案1】:

这两种方法的差异主要是由x in X 操作的性能引起的。当 X 是一个列表并且 O(1)如果 X 是一个集合时,这个测试是复杂的 O(size_of_X)

如果您在progress_apply 之前将lst 转换为set,您将获得与Series.isin 大致相同的性能

这是一个快速基准测试

SERIES = pd.Series([str(i) for i in range(100000)])
LIST = [str(i) for i in range(-10000, 10000)]

%timeit SERIES.isin(LIST)
# 9.2 ms

SERIES.map(lambda x: x in LIST)
# 22000 ms

%timeit SET = set(LIST); SERIES.map(lambda x: x in SET)
# 24.8 ms

【讨论】:

  • 谢谢!这个例子中的 lst 实际上是 list(set(my original list including duplicates)),所以不是这样。应该在帖子中提到这一点。
  • @jmh123 没关系。使集合中的查找更快的原因不是它没有重复项,而是由于散列而得到O(1) 查找的事实。阅读数据结构(谷歌!)了解更多信息;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-17
  • 1970-01-01
  • 2010-11-17
  • 2023-03-29
  • 2022-06-12
  • 1970-01-01
  • 2014-04-21
相关资源
最近更新 更多