2

我有一个 numpy 字符串数组,其中一些重复,我想将每个元素与每个其他元素进行比较,以生成一个新的 1 和 0 向量,指示每对(i,j)是相同还是不同。

例如["a","b","a","c"]-> 12 元素 (4*3) 向量[1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1]

有没有办法在 numpy 中快速做到这一点,而无需通过所有元素对进行双循环?我的数组有大约 240,000 个元素,因此以天真的方式完成它需要很长时间。

我知道numpy.equal.outer,但显然numpy.equal没有在字符串上实现,所以我似乎需要一些更聪明的方法来比较它们。

4

2 回答 2

3

构建一个包含字符串哈希值(使用内置hash()函数)的数组。

eg = ['a', 'b', 'c', 'a']
hashed = np.array([hash(s) for s in eg])
result = np.equal.outer(hashed, hashed)

输出:

[[ True False False  True]
 [False  True False False]
 [False False  True False]
 [ True False False  True]]

如果只有 1 个字符长的字符串,您可以使用ord()代替hash()

给定一个长度为 1 的字符串,当参数是 unicode 对象时,返回一个表示字符的 Unicode 代码点的整数,或者当参数是 8 位字符串时,返回字节的值。例如,ord('a') 返回整数 97,ord(u'\u2020') 返回 8224。

于 2017-03-10T18:00:38.177 回答
1

tl;博士

你不想要那个。

细节

首先让我们注意您实际上是在构建一个三角矩阵:对于第一个元素,将其与其余元素进行比较,然后递归地重复其余元素。但是,您不使用三角形。在您的示例中,您只需切断对角线(每个元素始终等于自身)并将行合并到一个列表中。

如果对源列表进行排序,则无需将每个元素与其余元素进行比较,只需与下一个元素进行比较。您必须使用元组保持元素的位置,以便在排序后跟踪它。

您将在 O(n log n) 时间内对对列表进行排序,然后扫描它并在 O(n) 时间内找到所有匹配项。在您的情况下,排序和查找匹配项都非常简单快捷。

之后,您必须创建“位向量”,即 O(n^2) long。它将包含len(your vector) ** 2元素,或240k 元素向量的 576亿个元素。即使您将每个元素表示为一位,也需要 53.6 Gbit 或 8.7 GBytes 的内存。

可能你不想要那个。我建议您在 O(n log n) 时间内找到一个对列表,也按 O(n log n) 时间的第一和第二位置对其进行排序,然后通过查看该列表重新创建所需位图的任何部分对;二进制搜索真的很有帮助。如果您的匹配项比元素对少得多,那么结果甚至可能适合 RAM。

于 2017-03-10T18:42:04.553 回答