对于我们知道轴和重复的情况——并且重复是一个标量(所有元素的值相同),我们可以像这样构造一个切片索引:
In [1117]: a=np.array([[1, 1, 2, 2],[3, 3, 4, 4]])
In [1118]: axis=1; repeats=2
In [1119]: ind=[slice(None)]*a.ndim
In [1120]: ind[axis]=slice(None,None,a.shape[axis]//repeats)
In [1121]: ind
Out[1121]: [slice(None, None, None), slice(None, None, 2)]
In [1122]: a[ind]
Out[1122]:
array([[1, 2],
[3, 4]])
@Eelco's 使用 take 可以更轻松地专注于一个轴,但需要索引列表,而不是切片。
但repeat 确实允许不同的重复计数。
In [1127]: np.repeat(a1,[2,3],axis=1)
Out[1127]:
array([[1, 1, 2, 2, 2],
[3, 3, 4, 4, 4]])
知道axis=1 和repeats=[2,3] 我们应该能够构建正确的take 索引(可能使用cumsum)。切片不起作用。
但如果我们只知道轴,而重复次数未知,那么我们可能需要某种unique 或set 操作,如@redratear's 答案。
In [1128]: a2=np.repeat(a1,[2,3],axis=1)
In [1129]: y=[list(set(c)) for c in a2]
In [1130]: y
Out[1130]: [[1, 2], [3, 4]]
带有列表repeats 的take 解决方案。这应该选择每个重复块的最后一个:
In [1132]: np.take(a2,np.cumsum([2,3])-1,axis=1)
Out[1132]:
array([[1, 2],
[3, 4]])
已删除的答案使用unique;这是我逐行使用unique
In [1136]: np.array([np.unique(row) for row in a2])
Out[1136]:
array([[1, 2],
[3, 4]])
unique 比 set 更好,因为它保持元素顺序。 unique (或设置)还有另一个问题 - 如果原件有重复值怎么办,例如[[1,2,1,3],[3,3,4,1]].
这是一个很难从结果中推断出重复模式的情况。我必须先查看所有行。
In [1169]: a=np.array([[2,1,1,3],[3,3,2,1]])
In [1170]: a1=np.repeat(a,[2,1,3,4], axis=1)
In [1171]: a1
Out[1171]:
array([[2, 2, 1, 1, 1, 1, 3, 3, 3, 3],
[3, 3, 3, 2, 2, 2, 1, 1, 1, 1]])
但是 cumsum 在已知的重复上很好地解决了它:
In [1172]: ind=np.cumsum([2,1,3,4])-1
In [1173]: ind
Out[1173]: array([1, 2, 5, 9], dtype=int32)
In [1174]: np.take(a1,ind,axis=1)
Out[1174]:
array([[2, 1, 1, 3],
[3, 3, 2, 1]])