我试图获取numpy数组中所有重复元素的索引,但我目前找到的解决方案对于大型(>20000个元素)输入数组来说效率非常低(大约需要9秒)。想法很简单:
records_array
是一个numpy时间戳数组(datetime
),我们希望从中提取重复时间戳的索引time_array
是一个numpy数组,包含在records_array
中重复的所有时间戳records
是一个django QuerySet(可以很容易地转换为列表),包含一些Record对象。我们希望创建一个由Record的tagId属性的所有可能组合组成的对列表,这些组合对应于从records_array
中找到的重复时间戳。
以下是我目前使用的工作(但效率低下)代码:
tag_couples = [];
for t in time_array:
users_inter = np.nonzero(records_array == t)[0] # Get all repeated timestamps in records_array for time t
l = [str(records[i].tagId) for i in users_inter] # Create a temporary list containing all tagIds recorded at time t
if l.count(l[0]) != len(l): #remove tuples formed by the first tag repeated
tag_couples +=[x for x in itertools.combinations(list(set(l)),2)] # Remove duplicates with list(set(l)) and append all possible couple combinations to tag_couples
字符串
我很确定这可以通过使用Numpy来优化,但是我找不到一种方法来比较records_array
和time_array
的每个元素,而不使用for循环(这不能只使用==
进行比较,因为它们都是数组)。
9条答案
按热度按时间gajydyqb1#
numpy的矢量化解决方案,在
unique()
的魔力上。字符串
下面的代码是原始答案,它需要更多的内存,使用
numpy
广播并调用unique
两次:型
与预期的
res = [array([0, 3, 4]), array([1, 8]), array([2, 5, 7])]
一样4sup72z82#
包含2M个元素的数组
np.where
比defaultdict
快,但是比pandas.core.groupby.GroupBy.indices
和np.unique
慢。pandas
的解决方案是大型阵列的最快解决方案。最多包含80k个元素的阵列
defaultdict
是约2400个元素的数组的快速选项,特别是具有大量唯一元素的数组。%timeit
第一代字符串
使用2M个元素的测试
的数据
的
的
的
使用多达80k个元素进行测试
的
型
型
型
型
型
型
型
型
型
型
型
型
bkkx9g8r3#
你也可以这样做:
字符串
这将给你给予一组数组,数组的索引是唯一的元素。
型
又道:列表解析中的进一步变化也可以丢弃单个唯一值,并解决许多唯一单个出现元素的速度问题:
型
这给出:
型
drkbr07n4#
编辑:这个答案查找重复的连续项,而不是一个项的所有副本。例如,在数组
[1,2,2,3,2]
中,它将返回[1,2]
而不是[1,2,4]
。由于这仍然是非常有效的,并且可能对某些人有用,我将留下答案。我发现不使用
np.unique
,而使用np.diff
的速度明显更快,并且更好地处理非排序的初始数组。为了说明这一点,我运行了@特伦顿麦金尼的基准测试,测试了两个试验数字(200万和20 k),以表明diff解决方案可以消除其他数字。它也不需要排序数组或对数组进行排序,这是一个显著的好处。
函数如下:
字符串
200万元素
x1c 0d1x的数据
20 k个元素
的
完整测试代码
型
1u4esq0p5#
所以我无法摆脱for循环,但我能够将其配对为使用for循环,并使用
set
数据类型和list.count()
方法:字符串
在这里,你循环遍历indivs集合,它包含值(没有重复),然后如果你发现一个有重复的项目,循环遍历整个列表。如果这对你来说不够快,我正在寻找numpy替代方案。如果需要的话,生成器对象也可以加快速度。
编辑:gg 349的答案包含了我正在研究的numpy解决方案!
cxfofazt6#
你可以做一些沿着线:
字符串
编辑-好的,所以在我快速回复后,我已经离开了一段时间,我看到我已经被投票否决了,这是公平的,因为
numpy.argsort()
是一个比我的建议好得多的方法。我确实投票赞成numpy.unique()
的答案,因为这是一个有趣的功能。但是,如果你使用timeit,你会发现,型
型
进一步编辑以下问题@尼古拉斯
我不确定你能做到。有可能得到两个对应于断点的索引数组,但是你不能用np把数组的不同“行”分成不同大小的块。
型
但这可能已经足够好了,这取决于你想用这些信息做什么。
5fjcxozz7#
字符串
4dbbbstv8#
np.unique
所有索引@gg349的解决方案打包成一个函数:
字符串
它本质上与
np.unique
相同,但返回 all 索引,而不仅仅是 first 索引。示例用法:
型
输出量:
型
sauutmhj9#
numba.jit
另一种解决方案,但使用
numba.jit
:字符串
使用@特伦顿麦金尼和用户27443的基准测试:
x1c 0d1x的数据
请注意,所有解决方案的性能都取决于数组的大小和唯一标签的数量,因此我建议您自己测试自己的数据。