简体   繁体   English

处理2D列表Python的周围环境

[英]Dealing with surrounding of a 2D list python

I want to go through a 2D list of numbers and I want to do some calculations with each element and its surrounding elements. 我想浏览一个二维数字列表,并且要对每个元素及其周围的元素进行一些计算。 Whenever a number is at a "wall" it should calculate with itself. 只要数字在“墙”处,它就应该自己计算。 eg. 例如。

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))

I thought about doing some if-statements in a double for loop to deal with the numbers in the corners and at the walls: 我考虑过在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

      ...

my first question is: 我的第一个问题是:

is there a smarter way to deal with the surrounding of a 2D list? 有没有更聪明的方法来处理2D列表的周围环境? is there a function that can do something like: 是否有可以执行以下操作的功能:

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

my second question is: 我的第二个问题是:

i want to first calculate all values and then update the values of the matrix at once. 我想先计算所有值,然后立即更新矩阵的值。 I though about putting the new values in a copy of the first list 我将新值放在第一个列表的副本中

list2 = list1[:] #copy using slice method

but it seems like list2 is always the same as list1 and when the for loop reaches the second element, it has already replaced the first one by the new value 但似乎list2始终与list1相同,并且当for循环到达第二个元素时,它已经用新值替换了第一个元素

Thanks for any help! 谢谢你的帮助!

UPDATE: 更新:

Although the operation is a convolution, in this case it can be computed way faster with simple vectorized additions, as explained in my other answer . 尽管该操作卷积运算,但在这种情况下,可以通过简单的矢量化加法来更快地进行计算,如我的其他答案所述


What you are describing is a convolution operation in 2 dimensions, and is an operation that appears very frequently in signal processing. 您所描述的是二维的卷积运算,并且是在信号处理中非常频繁出现的运算。 A typical application is image filtering. 典型的应用是图像过滤。 Here is a good explanation, but it basically boils down to what you want to do. 是一个很好的解释,但基本上可以归结为您要执行的操作。

There is a NumPy implementation of the operation in SciPy, convolve2d . SciPy中有该操作的NumPy实现, convolve2d A smart implementation of convolution will be way, way faster than a straightforward loop-based approach, so it's usually worth using an existing one. 卷积的智能实现将比直接基于循环的方法快得多,因此通常值得使用现有的方法。 For your case, you could do something like: 对于您的情况,您可以执行以下操作:

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]])

I have realised that, for your case, which is rather simple (a small kernel with weights 1 or 0), you can also do the operation manually, only in a vectorized way: 我已经意识到,就您的情况而言,这很简单(权重为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]])

I think this should in theory be faster, because you are just doing additions, although it has more Python-C trips (maybe some could be saved), so it may depend on the size of the matrix in the end. 我认为从理论上讲这应该更快,因为尽管有更多的Python-C行程(也许可以节省一些),但是您只是在做加法操作,因此最终可能取决于矩阵的大小。

UPDATE: 更新:

After a couple of quick tests, this method is indeed faster with an input of size 30x30 or bigger in my machine, so unless your input is really small (in which case performance won't matter anyway) you should prefer this method. 经过几次快速测试,在我的机器中输入30x30或更大的尺寸时,此方法的确确实更快,因此,除非您的输入很小(无论如何,性能都无关紧要),否则您应该首选此方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM