在2D numpy数组中查找和删除回文行



从矩阵中查找/删除回文行的方法是什么。尽管标题建议矩阵是numpy ndarray,但如果它能带来更优雅的解决方案,它也可以是pandas DataFrame

显而易见的方法是使用for循环来实现这一点,但我感兴趣的是有一种更有效、更简洁的方法。

我的第一个想法是反向连接行和行,然后从连接的矩阵中提取重复项。但是这个重复的列表将同时包含初始行及其反向行。所以要删除回文的第二个实例,我仍然需要做一些循环操作。

我的第二个想法是以某种方式使用广播来获得行的笛卡尔乘积,并应用我自己的ufunc(可能是使用numba创建的(来获得2D布尔矩阵。但我不知道如何创建ufunc来获得矩阵轴,而不是标量。

编辑:

我想我应该为这个问题表述不清而道歉(英语不是我的母语(。我不需要找出任何一行本身是否是回文,但矩阵中是否有成对的行是回文。

我只需检查数组是否等于它在所有元素中的反射(围绕轴1(,如果为true,它是一个回文(如果我错了,请纠正我(。然后我索引出不是回文的行。

import numpy as np
a = np.array([
[1,0,0,1], # Palindrome
[0,2,2,0], # Palindrome
[1,2,3,4],
[0,1,4,0],
])
wherepalindrome = (a == a[:,::-1]).all(1)
print(a[~wherepalindrome])
#[[1 2 3 4]
# [0 1 4 0]]

Naphat的答案是走蟒蛇(numpythonic(的路。这应该是公认的答案。

但是,如果您的数组是真的大,您不想创建临时副本,并且您希望探索Numba的复杂性,您可以使用这样的东西:

import numba as nb
@nb.njit(parallel=True)
def palindromic_rows(a):
rows, cols = a.shape
palindromes = np.full(rows, True, dtype=nb.boolean)
mid = cols // 2
for r in nb.prange(rows):   # <-- parallel loop
for c in range(mid):
if a[r, c] != a[r, -c-1]:
palindromes[r] = False
break
return palindromes

这个装置只是取代了优雅的(a == a[:,::-1]).all(axis=1),但对于非常大的阵列来说,它几乎快了一个数量级,而且不会复制它们。

最新更新