Python 查找两个numpy数组之间的绝对最小值,但保留符号

Python 查找两个numpy数组之间的绝对最小值,但保留符号,python,pandas,numpy,difference,Python,Pandas,Numpy,Difference,考虑两个不同长度的数组: A = np.array([58, 22, 86, 37, 64]) B = np.array([105, 212, 5, 311, 253, 419, 123, 461, 256, 464]) 对于A中的每个值,我想找出A和B中的值之间的最小绝对差。我使用Pandas是因为我的实际数组是Pandas数据帧的子集,但也因为apply方法是一种方便(尽管速度较慢)的方法,可以在两个不同大小的数组之间取用差异: In [22]: pd.Series(A).apply

考虑两个不同长度的数组:

A = np.array([58, 22, 86, 37, 64])

B = np.array([105, 212,   5, 311, 253, 419, 123, 461, 256, 464])
对于
A
中的每个值,我想找出
A
B
中的值之间的最小绝对差。我使用
Pandas
是因为我的实际数组是Pandas数据帧的子集,但也因为
apply
方法是一种方便(尽管速度较慢)的方法,可以在两个不同大小的数组之间取用差异:

In [22]: pd.Series(A).apply(lambda x: np.min(np.abs(x-B)))
Out[22]:
0    47
1    17
2    19
3    32
4    41
dtype: int64
但是我也想保留该符号,因此所需的输出是:

0    -47
1     17
2    -19
3     32
4    -41
dtype: int64

[update]我的实际阵列
A
B
的长度约为5e4和1e6,因此低内存解决方案是理想的。另外,我希望避免使用Pandas,因为它在实际数组中非常慢。

code>np.argmin可以找到最小值的位置。因此,您可以简单地执行以下操作:

pd.Series(A).apply(lambda x: x-B[np.argmin(np.abs(x-B))])

让我们在这里使用广播减法。然后,我们使用
argmin
找到绝对最小值,然后在后续步骤中提取值

u = A[:,None] - B
idx = np.abs(u).argmin(axis=1)

u[np.arange(len(u)), idx]
# array([-47,  17, -19,  32, -41])

这使用的是纯NumPy广播,因此速度应该相当快。

因为您标记了
pandas

# compute the diff by broadcasting
diff = pd.DataFrame(A[None,:] - B[:,None])
# mininum value
min_val = diff.abs().min()

# mask with where and stack to drop na
diff.where(diff.abs().eq(min_val)).stack()
输出:

0  0   -47.0
   2   -19.0
   4   -41.0
2  1    17.0
   3    32.0
dtype: float64
理解力 我情不自禁。这不是你应该做的!但是,它很可爱

[min(x - B, key=abs) for x in A]

[-47, 17, -19, 32, -41]

简化的Big-O Numpy解决方案 如果
N=len(A)
M=len(B)
则此解决方案应为
O(N+M log(M))
如果
B
已排序,则不需要排序步骤。这就变成了
O(N+M)

对于剪裁的值,我们最终会将一个值与它自身进行比较,因此它是安全的

right_diff = A - C[right]
left_diff  = A - C[left ]

np.where(np.abs(right_diff) <= left_diff, right_diff, left_diff)

array([-47,  17, -19,  32, -41])
right\u diff=A-C[右]
左_diff=A-C[左]

np.where(np.abs(右差异)如果你在处理NumPy阵列,pandas从何而来?@cs95你是对的,pandas是不需要的。我忘了NumPy的广播,所以不知道如何减去不同大小的阵列,而不使用pandas和
apply
方法。你能有两个输出列吗:一个用于
absdiff
(然后您可以轻松地进行min-on),一个用于
符号
?或者您只需要广播
min\u abs\u diff\u preserve\u符号
pandas/numpy函数吗?“我使用pandas是因为我的实际数组是pandas数据帧的子集”如果它们是熊猫系列,请编辑标题。如果你想在我的实际数组中使用熊猫系列(A[None,:]-B[:,None]);s.lookup(s.abs().idxmin(),s.columns)Out[123]:数组([-47,17,-19,32,-41])
在我的实际数组中,
left\u diff=A-C[left]
由于索引错误而出错。也就是说,如果数组C的长度为100,并且
left
返回索引100,那么它将出错(因为索引为0-99)。将
left=np.最大值(a,0)-1
保留算法并修复索引问题?@GeneBurinsky道歉。我更新了我的帖子。应该是
np.max(a-1,0)
不要使用
np.max(a,0)-1
因为这将在实例中打破最小值出现在第一个位置,因为相应的位置将是
-1
。这是一个快速但非常占用内存的解决方案。这对较小的数组很好,但在我的实际数据中,我遇到了
内存错误
。从角度看,我的实际
a
是长度50e3和
B
是1e6,因此广播的内存需求非常大。
right_diff = A - C[right]
left_diff  = A - C[left ]

np.where(np.abs(right_diff) <= left_diff, right_diff, left_diff)

array([-47,  17, -19,  32, -41])