我想合并一个数组中的两个相等元素,假设我有一个这样的数组
np.array([[0,1,1,2,2],
[0,1,1,2,2],
[0,2,2,2,2]])
如果我指挥得当,我想制作这样的东西
np.array([[0,0,2,0,4],
[0,0,2,0,4],
[0,0,4,0,4]])
如果我要向上移动,这就是
np.array([[0,2,2,4,4],
[0,0,0,0,0],
[0,2,2,2,2]])
我当前的代码只是循环遍历一个普通列表
for i in range(4):
for j in range(3):
if mat[i][j]==matrix[i][j+1] and matrix[i][j]!=0:
matrix[i][j]*=2
matrix[i][j+1]=0
如果可能的话,我更喜欢 numpy 和没有循环
最佳答案
如果没有循环,这个任务看似很难完成!你需要一堆高级 numpy
技巧才能让它工作。我在这里浏览了它们,但我会尽可能链接到其他资源。
来自 here ,进行逐行比较的最佳方法是:
a = np.array([[0,1,1,2,2],
[0,1,1,2,2],
[0,2,2,2,2]])
b = np.ascontiguousarray(a).view(np.dtype((np.void, a.dtype.itemsize * a.shape[1])))
b
array([[[0 0 0 0 1 0 0 0 1 0 0 0 2 0 0 0 2 0 0 0]],
[[0 0 0 0 1 0 0 0 1 0 0 0 2 0 0 0 2 0 0 0]],
[[0 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 2 0 0 0]]],
dtype='|V20')
b.shape
(3, 1)
请注意,最里面的括号不是额外的维度,而是一个 np.void
对象,可以与类似 np.unique
的对象进行比较.
尽管如此,获取您想要保留的索引并不是一件容易的事,但这里是单行代码:
c = np.flatnonzero(np.r_[1, np.diff(np.unique(b, return_inverse = 1)[1])])
哎呀。有点乱。基本上你正在寻找线条变化的索引,以及第一行。通常你不需要 np.unique
调用,可以只做 np.diff(b)
,但你不能减去 np.void
。 np.r_
是 np.concatenate
的快捷方式,可读性更强。 np.flatnonzero
为您提供新数组不为零的索引(即您要保留的索引)
c
array([0, 2], dtype=int32)
好了,现在你可以使用一些奇特的东西了 ufunc.reduceat
数学来做你的加法:
d = np.add.reduceat(a, c, axis = 0)
d
array([[0, 2, 2, 4, 4],
[0, 2, 2, 2, 2]], dtype=int32)
好的,现在要添加零,我们只需使用 advanced indexing 将其插入 np.zero
数组即可。
e = np.zeros_like(a)
e[c] = d
e
array([[0, 2, 2, 4, 4],
[0, 0, 0, 0, 0],
[0, 2, 2, 2, 2]])
我们开始吧!您可以通过在开始和结束处转置或翻转矩阵来朝其他方向前进。
def reduce_duplicates(a):
b = np.ascontiguousarray(a).view(np.dtype((np.void, a.dtype.itemsize * a.shape[1])))
c = np.flatnonzero(np.r_[1, np.diff(np.unique(b, return_inverse = 1)[1])])
d = np.add.reduceat(a, c, axis = 0)
e = np.zeros_like(a)
e[c] = d
return e
reduce_duplicates(a.T[::-1,:])[::-1,:].T #reducing right
array([[0, 0, 2, 0, 4],
[0, 0, 2, 0, 4],
[0, 0, 4, 0, 4]])
我没有 numba
所以我无法根据其他建议测试速度(知道 numba
它可能更慢),但它是无环和 numpy 的。
关于PYTHON:如何合并相等元素的numpy数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44580615/