代码之家  ›  专栏  ›  技术社区  ›  ron burgundy

两个具有重复值的Numpy数组之间的快速索引映射

  •  2
  • ron burgundy  · 技术社区  · 1 年前

    我试图在两个Numpy数组之间编写一个连接操作,惊讶地发现Numpy的 recfunctions.join_by 不处理重复值。

    我采取的方法是使用要连接的列,并在它们之间找到索引映射。从网上看,大多数仅Numpy的解决方案都存在无法处理重复的问题(您将在代码部分看到我的意思)。

    如果可能的话,我希望完全留在Numpy库中,以利用矢量化操作,所以理想情况下没有原生Python代码、Pandas(出于其他原因)或Numpy索引。

    以下是我研究过的几个问题:

    A way to map one array onto another in numpy? Find index mapping between two numpy arrays Numpy: For every element in one array, find the index in another array Index mapping between two sorted partially overlapping numpy arrays

    例如,数组 X Y 它们将使用来自它们中的每一个的柱连接, x y 分别。

    映射定义为,以及 f 这就是我想要的

    mapping = f(x, y)
    
    x = y[mapping]
    

    例如,

    x = np.array([1,1,2,100])
    y = np.array([1,2,3,4,5,6,7])
    
    
    mapping = [0, 0, 1, -] # '-' indicates masked
    x = y[mapping] 
    

    从网上查看类似问题,找到以下映射 x y np.where(np.isin(x,y)) 其对值进行重复数据消除。还有 np.searchsorted(x,y) 它不处理中的重复项 x 完全。我想知道是否还有别的办法。

    由于中的重复,以下不是正确的映射 x

    import numpy as np
    
    x = np.array([1,1,2,100])
    y = np.array([1,2,3,4,5,6,7])
    
    mapping = np.searchsorted(x, y)
    # [0 2 3 3 3 3 3]
    

    这也不是一个正确的映射,因为映射的长度需要与 x .

    import numpy as np
    
    x = np.array([1,1,2,100])
    y = np.array([1,2,3,4,5,6,7])
    
    mapping = np.where(np.isin(x, y))[0]
    # [0, 1, 2]
    
    2 回复  |  直到 1 年前
        1
  •  2
  •   Denel    1 年前

    使用 np.isin() 我们可以创建一个掩码,显示哪些值已经在另一个数组中,当你有了这个掩码时,你只需要找出索引。

    import numpy as np
    
    # Arrays to be joined
    x = np.array([1, 1, 2, 100, 4, 5, 3, 75])
    y = np.array([1, 2, 3, 4, 5, 6, 7])
    
    # Get mask with True and False values
    mask = np.isin(x, y)
    # [ True  True  True False  True  True  True False]
    
    # Get indices of every element
    indices = np.searchsorted(y, x)
    # [0  0  1  7  3  4  2  7]
    
    # Match indices with mask
    mapping = np.where(mask, indices, -1)
    # [ 0  0  1 -1  3  4  2 -1]
    

    我们创建掩码,获取索引,然后将索引与掩码进行匹配。不在y中的值得到值 -1

    此解决方案完全保留在Numpy库中

        2
  •  2
  •   Andrej Kesely    1 年前

    我不确定我是否很好地理解了你的问题,但你可以用 np.searchsorted 相反的论点:

    import numpy as np
    
    x = np.array([1, 1, 2, 100])
    y = np.array([1, 2, 3, 4, 5, 6, 7])
    
    mapping = np.searchsorted(y, x)
    mapping[mapping >= len(y)] = -1  # -1 to indicate "masked" values
    
    print(mapping)
    

    打印:

    [ 0  0  1 -1]