删除numpy数组的对角元素

时间:2017-10-13 18:44:58

标签: python numpy

给定输入

A = np.array([[1,2,3],[4,5,6],[7,8,9]])
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

需要输出:

array([[2, 3],
       [4, 6],
       [7, 8]])

使用迭代或循环很容易做到这一点,但应该有一个简洁的方法来做到这一点,而不使用循环。感谢

7 个答案:

答案 0 :(得分:7)

方法#1

使用masking -

的一种方法
A[~np.eye(A.shape[0],dtype=bool)].reshape(A.shape[0],-1)

示例运行 -

In [395]: A
Out[395]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

In [396]: A[~np.eye(A.shape[0],dtype=bool)].reshape(A.shape[0],-1)
Out[396]: 
array([[2, 3],
       [4, 6],
       [7, 8]])

方法#2

使用非对角线元素的常规模式,可以使用范围数组广播添加进行跟踪 -

m = A.shape[0]
idx = (np.arange(1,m+1) + (m+1)*np.arange(m-1)[:,None]).reshape(m,-1)
out = A.ravel()[idx]

方法#3 (Strides Strikes!)

滥用先前方法中的非对角元素的常规模式,我们可以引入np.lib.stride_tricks.as_strided和一些slicing帮助,如此 -

m = A.shape[0]
strided = np.lib.stride_tricks.as_strided
s0,s1 = A.strides
out = strided(A.ravel()[1:], shape=(m-1,m), strides=(s0+s1,s1)).reshape(m,-1)

运行时测试

作为funcs的方法:

def skip_diag_masking(A):
    return A[~np.eye(A.shape[0],dtype=bool)].reshape(A.shape[0],-1)

def skip_diag_broadcasting(A):
    m = A.shape[0]
    idx = (np.arange(1,m+1) + (m+1)*np.arange(m-1)[:,None]).reshape(m,-1)
    return A.ravel()[idx]

def skip_diag_strided(A):
    m = A.shape[0]
    strided = np.lib.stride_tricks.as_strided
    s0,s1 = A.strides
    return strided(A.ravel()[1:], shape=(m-1,m), strides=(s0+s1,s1)).reshape(m,-1)

计时 -

In [528]: A = np.random.randint(11,99,(5000,5000))

In [529]: %timeit skip_diag_masking(A)
     ...: %timeit skip_diag_broadcasting(A)
     ...: %timeit skip_diag_strided(A)
     ...: 
10 loops, best of 3: 56.1 ms per loop
10 loops, best of 3: 82.1 ms per loop
10 loops, best of 3: 32.6 ms per loop

答案 1 :(得分:1)

只需要numpy,假设一个方阵:

new_A = numpy.delete(A,range(0,A.shape[0]**2,(A.shape[0]+1))).reshape(A.shape[0],(A.shape[1]-1))

答案 2 :(得分:1)

我知道我参加这个聚会很晚,但是我相信这是一个简单的解决方案。所以要删除对角线吗?好的,很酷:

  • 用NaN代替
  • 过滤除NaN之外的所有内容(这会转换为一维,因为它不能假定结果为正方形)
  • 重置尺寸

`

 arr = np.array([[1,2,3],[4,5,6],[7,8,9]]).astype(np.float)
 np.fill_diagonal(arr, np.nan)
 arr[~np.isnan(arr)].reshape(arr.shape[0], arr.shape[1] - 1)

答案 3 :(得分:1)

解决步骤:

  • 平整数组
  • 删除对角元素的位置range(0, len(x_no_diag), len(x) + 1)
  • 将数组重塑为(num_rows,num_columns-1)

功能:

import numpy as np

def remove_diag(x):
    x_no_diag = np.ndarray.flatten(x)
    x_no_diag = np.delete(x_no_diag, range(0, len(x_no_diag), len(x) + 1), 0)
    x_no_diag = x_no_diag.reshape(len(x), len(x) - 1)
    return x_no_diag

示例:

>>> x = np.random.randint(5, size=(3,3))
array([[0, 2, 3],
       [3, 4, 1],
       [2, 4, 0]])
>>> remove_diag(x)
array([[2, 3],
       [3, 1],
       [2, 4]])

答案 4 :(得分:0)

如果您不介意创建新数组,则可以使用列表推导。

A = np.array([A[i][A[i] != A[i][i]] for i in range(len(A))])

运行与@Divakar相同的方法,

A = np.random.randint(11,99,(5000,5000))

skip_diag_masking
85.7 ms ± 1.55 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
skip_diag_broadcasting
163 ms ± 1.77 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
skip_diag_strided
52.5 ms ± 2.54 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
skip_diag_list_comp
101 ms ± 347 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

答案 5 :(得分:0)

也许基于Divakar's first solution但使用import pandas as pd df = pd.DataFrame({'Date': {0: '2020-08-29', 1: '2020-08-31', 2: '2020-09-01', 3: '2020-09-25', 4: '2020-09-26', 5: '2020-09-30'}, 'value': {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0}}) df['Date'] = pd.to_datetime(df['Date']).sort_values() m1 = df.groupby(df['Date'].dt.month)['Date'].transform('max') m2 = df['Date'].shift(-1) m = (m1 == m2) df['Max Date Per Month'] = m1 df['Shifted Date'] = m2 df['Keep/Drop'] = m df Out[33]: Date value Max Date Per Month Shifted Date Keep/Drop 0 2020-08-29 0 2020-08-31 2020-08-31 True 1 2020-08-31 0 2020-08-31 2020-09-01 False 2 2020-09-01 0 2020-09-30 2020-09-25 False 3 2020-09-25 0 2020-09-30 2020-09-26 False 4 2020-09-26 0 2020-09-30 2020-09-30 True 5 2020-09-30 0 2020-09-30 NaT False 而非len(array)的最干净的方法是:

array.shape[0]

答案 6 :(得分:-1)

另一种方法是使用numpy.delete()。假设方阵,您可以使用:

numpy.delete(A,range(0,A.shape[0]**2,A.shape[0])).reshape(A.shape[0],A.shape[1]-1)