我有一个3D数组,维数为(2,4,500)。看一下[...,0],子数组看起来如下:
array([[ 700, 0, 2000, 0],
[-400, 0, 0, -200]])
我可以保证,对于这个子数组的给定行,所有值都将是非负数或非正数(即,我们不会在同一行中有正值和负值)。
我试图实现的是将两行相互偏移,而不管位置如何,这样最小的(绝对值)条目将首先减少。对于上面的例子,所需的输出数组是:
array([[ 100, 0, 2000, 0],
[ 0, 0, 0, 0]])
也就是说,我可以先用-200抵消700,然后用-400抵消剩下的500。
在另一示例中:
array([[ 100, 0, 2000, 0],
[ 0, 0, 0, -200]])
我希望结果是:
array([[ 0, 0, 1900, 0],
[ 0, 0, 0, 0]])
如果两行的条目具有相同的符号(例如,在上面的例子中将-200换成200),那么阵列应该保持原样。理想情况下,这可以直接应用于3D数组,但如果需要的话,我也很乐意循环遍历维度为(2,4)的2D子数组。
我的感觉是,一个整洁的解决方案必须存在,可能基于cumsum和argsort,但我一直无法使它工作。
编辑:每个子数组的终止条件是立即(如果两行的和具有相同的符号或为0),或者一旦其中一行变为零。
下面的代码示例应该能够突出我试图实现的目标:
import numpy as np
arr = np.array([[-700, 0, -2000, 0], [400, 0, 0, 200]])
out_arr = np.zeros_like(arr)
row0sum = np.nansum(arr[0])
row1sum = np.nansum(arr[1])
if np.sign(row0sum) * np.sign(row1sum) == -1:
if abs(row0sum) > abs(row1sum):
non_zeroing_index = 0
zeroing_index = 1
else:
non_zeroing_index = 1
zeroing_index = 0
size_order = np.argsort(abs(arr[non_zeroing_index]))
total_reducing_value = np.nansum(arr[zeroing_index])
for i, val in enumerate(arr[non_zeroing_index][size_order]):
if total_reducing_value == 0:
out_arr[non_zeroing_index, size_order[i]] = val
if val == 0:
continue
elif val > 0:
resulting_value = np.clip(val + total_reducing_value, 0, val)
reduction = resulting_value - val
out_arr[non_zeroing_index, size_order[i]] = resulting_value
total_reducing_value -= reduction
else:
resulting_value = np.clip(val + total_reducing_value, val, 0)
reduction = resulting_value - val
out_arr[non_zeroing_index, size_order[i]] = resulting_value
total_reducing_value -= reduction
else:
out_arr = arr
# move on to the next sub array
然而,在每个子数组上进行迭代必然会很慢,特别是如果必须进行数百次
1条答案
按热度按时间aij0ehis1#
你可以写一个offset函数来执行所有矩阵的任务:
编辑
如果您有较大的底片,请使用下面的函数: