我想浏览一个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循环到达第二个元素时,它已经用新值替换了第一个元素
感谢您的帮助!
答案 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或更大的情况下,这种方法确实更快,所以除非您的输入非常小(在这种情况下性能无关紧要),您应该更喜欢这种方法