Python 阵列相交指数

Python 阵列相交指数,python,numpy,Python,Numpy,是否有一种快速方法可以将数组的每个元素与唯一标识符列表中的每个元素进行比较 使用for循环遍历每个唯一值是可行的,但速度太慢,无法使用。我一直在寻找矢量化的解决方案,但没有成功。任何帮助都将不胜感激 arrStart = [] startRavel = startInforce['pol_id'].ravel() for policy in unique_policies: arrStart.append(np.argwhere(startRavel == policy)) 样本输入:

是否有一种快速方法可以将数组的每个元素与唯一标识符列表中的每个元素进行比较

使用for循环遍历每个唯一值是可行的,但速度太慢,无法使用。我一直在寻找矢量化的解决方案,但没有成功。任何帮助都将不胜感激

arrStart = []
startRavel = startInforce['pol_id'].ravel()
for policy in unique_policies:
    arrStart.append(np.argwhere(startRavel == policy))
样本输入:

startRavel = [1,2,2,2,3,3]

unique_policies = [1,2,3]
arrStart = [[0], [1,2,3],[4,5]]
样本输出:

startRavel = [1,2,2,2,3,3]

unique_policies = [1,2,3]
arrStart = [[0], [1,2,3],[4,5]]

新数组的长度与唯一值数组的长度相同,但每个元素都是与大数组中唯一值匹配的所有行的列表。

以下是矢量化解决方案:

import numpy as np
startRavel = np.array([1,2,2,2,3,3])
unique_policies = np.array([1,2,3])
使用排序
startRavel

用于查找应在
startRavel
中插入
unique_policy
以维护订单的索引:

s_ix = np.searchsorted(s_startRavel, unique_policies)
# array([0, 1, 4])
然后使用获得的索引拆分数组。在
s_ix
上再次使用,以处理未排序的输入:

ix_r = np.argsort(s_ix)
ixs = np.split(ix, s_ix[ix_r][1:])
np.array(ixs)[ix_r]
# [array([0]), array([1, 2, 3]), array([4, 5])]
startRavel = np.array([1,3,3,2,2,2,5])
unique_policies = np.array([1,2,5,3])

ix_intersection(unique_policies, startRavel)
# array([array([0]), array([3, 4, 5]), array([6]), array([1, 2])])

一般解决方案:

让我们将其全部封装在一个函数中:

def ix_intersection(x, y):
    """
    Finds the indices where each unique
    value in x is found in y.
    Both x and y must be numpy arrays.
    ----------
    x: np.array
       Must contain unique values. 
       Values in x are assumed to be in y.
    y: np.array

    Returns
    -------
    Array of arrays. Each array contains the indices where a
    value in x is found in y
    """
    ix_y = np.argsort(y)
    s = np.searchsorted(y[ix_y], x)
    ix_r = np.argsort(s)
    ixs = np.split(ix_y, s[ix_r][1:])
    return np.array(ixs)[ix_r]

其他例子

让我们尝试使用以下阵列:

startRavel = np.array([1,3,3,2,2,2])
unique_policies = np.array([1,2,3])

ix_intersection(unique_policies, startRavel)
# array([array([0]), array([3, 4, 5]), array([1, 2])])
另一个例子是,这次使用的是未排序的输入:

ix_r = np.argsort(s_ix)
ixs = np.split(ix, s_ix[ix_r][1:])
np.array(ixs)[ix_r]
# [array([0]), array([1, 2, 3]), array([4, 5])]
startRavel = np.array([1,3,3,2,2,2,5])
unique_policies = np.array([1,2,5,3])

ix_intersection(unique_policies, startRavel)
# array([array([0]), array([3, 4, 5]), array([6]), array([1, 2])])

你在找口授吗?可能是defaultdict(列表)?我不是很确定,我只是想加快这段代码的速度,因为由于数据集的大小,现在需要10多个小时。我想我需要找到一种不依赖循环的方法。你可以使用集合而不是列表。如果你可以在numpy查询中根据pol_id排序,你可能只需要循环一次结果集。如果您想要一个非numpy数据结构,我会将它们附加到一个defaultdict(list)中,pol_id作为键。但是在numpy中使用它可能会更好,因为它可以让数据库引擎做一些工作。(我不使用numpy,所以无法发布答案)谢谢!我已经失败了好几个小时了,非常感谢!伟大的回答和解释!