【问题标题】:Generating mask array for existence of each element of a list in another list为另一个列表中列表的每个元素的存在生成掩码数组
【发布时间】:2020-11-17 13:48:15
【问题描述】:

您认为有更快的方法吗? 或者在运行时和内存方面更有效的方式。

>>> list1 = ['a', 'b', 'c', 'd']
>>> list2 = ['b', 'c']
>>> mask_array = [True if x in list2 else False for x in list1]
>>> mask_array
[False, True, True, False]

【问题讨论】:

  • x in list2 是线性时间,将list2 转换为set 将获得更好的性能。

标签: python arrays numpy mask


【解决方案1】:
list1 = ['a', 'b', 'c']
list2 = ['b', 'c']

set2 = set(list2)
mask_array = [x in set2 for x in list1]

集合的查找操作平均花费 O(1),远低于在列表中查找 O(n)。

在这里你可以看到差异很大:

from time import time
import random
import numpy as np

random.seed(7)

list1 = [random.randrange(1000000) for i in range(100000)]
list2 = [random.randrange(1000000) for i in range(100000)]

start = time()
mask_array = [True if x in list2 else False for x in list1]
stop = time()
print(stop - start) # 93.71739292144775

start = time()
set2 = set(list2)
mask_array = [True if x in set2 else False for x in list1]
stop = time()
print(stop - start) # 0.022114992141723633

start = time()
mask_array = np.isin(list1, list2)
stop = time()
print(stop - start) # 0.03964031219482422

90 秒 vs

在这种情况下,您可以看到我的解决方案比np.isin 解决方案更快。

【讨论】:

  • 但是请把True if something else False 替换为something,这很痛苦:P
  • True if x in set2 else False,等同于x in set2
【解决方案2】:

由于您标记了numpy,因此您可以使用np.isin 获取掩码以获得更高性能的方法:

>>> list1=['a','b','c','d']
>>> list2=['b','c']

>>> np.isin(list1, list2)
>>> array([False,  True,  True, False])

时间,

a = np.random.randint(0,200_000, 100_000)
b = np.random.randint(0,10_000, 10_000)

%timeit np.isin(a,b)
# 8.78 ms ± 192 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
set2 = set(b)
mask_array = [x in set2 for x in a]
# 15.9 ms ± 606 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

【讨论】:

  • 我测量了你和我的解决方案的执行时间,numpy 似乎执行得更慢。你知道为什么吗?是不是很奇怪?
  • 不奇怪@RiccardoBucco 列表方法只是O(n),我们使用O(1) 查找对列表进行单次扫描,不应该很慢。我们在这里谈论一个简单的操作。得到的时间与你的略有不同
  • 您可能有更好的时机,因为您使用的是 numpy 数组而不是列表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2012-10-28
  • 2018-06-21
  • 1970-01-01
  • 2021-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多