处理2D列表python

时间:2018-01-05 11:12:08

标签: python multidimensional-array

我想浏览一个2D数字列表,我想对每个元素及其周围元素进行一些计算。每当一个数字位于"墙上时#34;它应该自己计算。 例如

list1 =[[1,2,3],
        [4,5,6],
        [7,8,9]]

list1[1][1] = 5 + 4 + 2 + 6 + 8 #element in the middle will be replaced by the 
number itself + its surrounding numbers

list1[0][0] = 1 + 1 + 1 + 2 + 4 
#element in the left top corner will be replace by the 
number itself + its surrounding 
(as there is no element above or left from it, it will be + the number itself (here 1))

我想在double for循环中做一些if语句来处理角落和墙壁上的数字:

for i in range(len(list1)):
    for j in range(len(list1[i])):

      if j == 0 : #elements at the left wall
        #do something
      elif i == 0 and j == 0: #element in the top left corner

      ...

我的第一个问题是:

有更智能的方法来处理2D列表的周围环境吗? 是否有一个函数可以做类似的事情:

if Index out of range:
  do something (not throwing and error message but calculate like above)

我的第二个问题是:

我想首先计算所有值,然后立即更新矩阵的值。 我将把新值放在第一个列表的副本中

list2 = list1[:] #copy using slice method

但似乎list2始终与list1相同,当for循环到达第二个元素时,它已经用新值替换了第一个元素

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

更新:

虽然操作卷积,但在这种情况下,可以通过简单的矢量化加法更快地计算,如my other answer中所述。

您所描述的是2维卷积运算,是一种在信号处理中经常出现的运算。典型的应用是图像过滤。 Here是一个很好的解释,但它基本上归结为你想要做的事情。

在SciPy convolve2d中有一个NumPy操作实现。卷积的智能实现将比简单的基于循环的方法更快,因此通常值得使用现有的方法。对于您的情况,您可以执行以下操作:

import numpy as np
from scipy import signal

data = np.array([[1,2,3],
                 [4,5,6],
                 [7,8,9]])
kernel = np.array([[0, 1, 0],
                   [1, 1, 1],
                   [0, 1, 0]])
result = signal.convolve2d(data, kernel, boundary='symm', mode='same')
print(result)

>>> array([[ 9, 13, 17],
           [21, 25, 29],
           [33, 37, 41]])

答案 1 :(得分:0)

我已经意识到,对于你的情况,这是相当简单的(一个权重为1或0的小内核),你也可以手动进行操作,只能以矢量化的方式进行:

import numpy as np

data = np.array([[1,2,3],
                 [4,5,6],
                 [7,8,9]])
result = np.zeros_like(data)
result += data
result[1:] += data[:-1]
result[:-1] += data[1:]
result[:, 1:] += data[:, :-1]
result[:, :-1] += data[:, 1:]
result[0] += data[0]
result[-1] += data[-1]
result[:, 0] += data[:, 0]
result[:, -1] += data[:, -1]
print(result)

>>> array([[ 9, 13, 17],
           [21, 25, 29],
           [33, 37, 41]])

我认为理论上这应该更快,因为你只是在做补充,虽然它有更多的Python-C跳转(可能有些可以保存),所以它可能最终取决于矩阵的大小。 / p>

更新:

经过几次快速测试后,在我的机器中输入大小为30x30或更大的情况下,这种方法确实更快,所以除非您的输入非常小(在这种情况下性能无关紧要),您应该更喜欢这种方法