在2D numpy数组中查找公共元素

时间:2017-05-30 14:54:17

标签: python numpy intersection

如果我有两个(或更多)2D数组,如何在给定行号的数组之间只获得公共元素。例如,我有以下格式的数组:

time, position, velocity, acceleration

我想让两个数组只有相同的时间元素,所以第0行。我可以使用

np.intersect1d(array1[:, 0], array2[:, 0])

它给出了所有常见的时间,但是我想要从array1 / 2中提取所有匹配的行/列,或者删除非公共时间元素。到底 array1array2将具有完全相同的尺寸,因此我可以去:

pos_difference = array1[:, 1] - array2[:, 2]

数组的大小可能不同,例如:

array1 = [[1, 100.0, 0.0, 0.0], [2, 110.0, 0.0, 0.0], [3, 120.0, 0.0, 0.0]]
array2 = [[1, 101.0, 0.0, 0.0], [3, 119, 0.0, 0.0]]

我想只提取公共时间元素,因此array1和array2只包含Time = 1和Time = 3,因为它们是公共时间元素。然后我可以去:

pos_difference = array1[:, 1] = array2[:, 1]

这将是两个阵列同时的位置差异:

# First row will be when time=1 and second row will be when time=3
pos_difference = [[0, -1, 0.0, 0.0], [0, 1, 0.0, 0.0]]

3 个答案:

答案 0 :(得分:2)

如果你有这些数组:

import numpy as np
array1 = np.array([[1, 100.0, 0.0, 0.0], [2, 110.0, 0.0, 0.0], [3, 120.0, 0.0, 0.0]])
array2 = np.array([[1, 101.0, 0.0, 0.0], [3, 119, 0.0, 0.0]])

正如你所说,你可以使用np.intersect1d来获得交集,唯一剩下的就是索引数组:

intersect = np.intersect1d(array1[:, 0], array2[:, 0])

array1_matches = array1[np.any(array1[:, 0] == intersect[:, None], axis=0)]
array2_matches = array2[np.any(array2[:, 0] == intersect[:, None], axis=0)]

然后你可以减去它们:

>>> array1_matches - array2_matches
array([[ 0., -1.,  0.,  0.],
       [ 0.,  1.,  0.,  0.]])

这假定您的时间是唯一的并且已经排序。如果它们未分类,您可以在之前对它们进行排序:

>>> array1 = array1[np.argsort(array1[:, 0])]
>>> array2 = array2[np.argsort(array2[:, 0])]

如果时间不是唯一的,我不知道你想怎么处理,所以我不能在那里建议你。

答案 1 :(得分:0)

您想使用numpy.in1d

array1 = array1[np.in1d(array1[:,0], array2[:,0]), assume_unique=True]
array2 = array2[np.in1d(array2[:,0], array1[:,0]), assume_unique=True]

或者,如果您不想更改原件:

array3 = array1[np.in1d(array1[:,0], array2[:,0]), assume_unique=True]
array4 = array2[np.in1d(array2[:,0], array3[:,0]), assume_unique=True]

请注意,在这两种情况下,我都使用简化数组作为第二个in1d的目标,以减少搜索时间。如果您想进一步优化,可以将其包装在if语句中,以确保较小的数组是第一个in1d的目标。

然后执行array3-array4

def common_subtract(a1, a2, i = 0, unique = True):
    a1, a2 = np.array(a1), np.array(a2)
    if a1.shape[0] > a2.shape[0]:  
        a1 = a1[np.in1d(a1[:, i], a2[:, i], assume_unique = unique)]
        a2 = a2[np.in1d(a2[:, i], a1[:, i], assume_unique = unique)]
    else:
        a2 = a2[np.in1d(a2[:, i], a1[:, i], assume_unique = unique)]
        a1 = a1[np.in1d(a1[:, i], a2[:, i], assume_unique = unique)]
    return a1 - a2

答案 2 :(得分:0)

我发现使用intersect1d更清晰的方法来查找2D numpy数组中的常见元素。在这种情况下,已经定义了recent_bookscoding_books

start = time.time()
recent_coding_books = np.intersect1d([recent_books], [coding_books]) 
print(len(recent_coding_books))
print('Duration: {} seconds'.format(time.time() - start))