【问题标题】:Solved: Calculating the average around numpy array element error: TypeError: 'numpy.float64' object does not support item assignment已解决:计算 numpy 数组元素周围的平均值错误:TypeError: 'numpy.float64' object does not support item assignment
【发布时间】:2020-04-16 21:34:55
【问题描述】:

编辑:感谢@hpaulj

,我已经更改了下面呈现工作版本的代码

我正在尝试使用 Gauss-Seidel 迭代求解 2D 拉普拉斯方程:矩阵中的每个非边界元素都被周围矩阵元素的平均值替换。我首先创建了基本矩阵。

# creation of matrix using random values and boundary conditions.
matrix = np.random.random((4,4))
for n in range(4): matrix.itemset((4-1, n), 10)
for n in range(4): matrix.itemset((n, 4-1), 0)
for n in range(4): matrix.itemset((0, n), 0)
for n in range(4): matrix.itemset((n, 0), 0)

输出:

[[ 0.          0.          0.          0.        ]
 [ 0.          0.33285936  0.59830215  0.        ]
 [ 0.          0.07021714  0.45341002  0.        ]
 [ 0.         10.         10.          0.        ]]

使用以下代码 sn-p,我尝试在数组中的每个非边界元素周围找到左、右、上和下元素。

# opening the matrix and preparing it to be read and rewritten.
#with np.nditer(matrix, op_flags=['readwrite']) as it:
with np.nditer(matrix, op_flags=['readwrite'], flags=['multi_index']) as it:

    # loop to find each element in our matrix
    #for index, x in np.ndenumerate(matrix):
    for x in it:
        #row, colum = index

        # only non-border values may be adjusted
        if x != 0 and x != 10:
            row, colum = it.multi_index

            # finding each element around x
            left = matrix[row][colum-1]
            right = matrix[row][colum+1]
            up = matrix[row-1][colum]
            down = matrix[row+1][colum]

            # finding average of elements around x
            newvalue = 1/4*(left+right+up+down)
            x[...] = newvalue

python 没有替换值,而是打印出以下错误:

x[...] = newvalue
TypeError: 'numpy.float64' object does not support item assignment

如果我只是使用,我不会收到错误

for x in it:

但是我无法跟踪数组中的 x、y 值。有人知道如何跟踪元素的位置或解决错误吗?

【问题讨论】:

  • x 在迭代中是matrix 中槽的值,但它不是对该槽的引用。正如错误所说,它是一个数字。 matrix[row, col] = newvalue 应该可以工作。
  • nditer 的迭代变量是对插槽的引用,一个 0d 数组。 x[...]=newvalue 确实可以做到这一点。在两个循环中执行 print(type(x)) 以查看差异。在nditer 上下文中嵌套ndenumerate(matrix) 循环是没有意义的。
  • 如果要跟踪row/colnditer中有multi-index选项,numpy.org/devdocs/reference/…
  • 我怀疑如果您使用嵌套列表而不是数组,这段代码会运行得更快。您没有太多(如果有的话)使用numpy 数组方法。列表迭代更快(nditer 没有帮助!)。
  • @hpaulj 我认为 numpy 数组会更快。这个数组目前非常小,但对于最终的程序,它将是 100×100 大。嵌套循环还会更快吗?

标签: python numpy


【解决方案1】:

更好地使用numpy索引来设置矩阵:

In [358]: arr = np.random.random((4,4))                                                                
In [359]: arr[[0,3],:] = 0                                                                             
In [360]: arr[:,[0,3]] = 0                                                                             
In [361]: arr[3,1:-1] = 10                                                                             
In [362]: arr                                                                                          
Out[362]: 
array([[ 0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.8869947 ,  0.61765067,  0.        ],
       [ 0.        ,  0.92640868,  0.83014953,  0.        ],
       [ 0.        , 10.        , 10.        ,  0.        ]])

甚至:

In [363]: arr = np.zeros((4,4))                                                                        
In [364]: arr[1:-1,1:-1] = np.random.random((4-2,4-2))                                                 
In [365]: arr                                                                                          
Out[365]: 
array([[0.        , 0.        , 0.        , 0.        ],
       [0.        , 0.50803298, 0.78055366, 0.        ],
       [0.        , 0.98941105, 0.61842531, 0.        ],
       [0.        , 0.        , 0.        , 0.        ]])

我怀疑您的其他迭代可以重写以充分利用数组方法,但我现在不会解决这个问题。

这是我在 cmets 中提到的区别:

In [367]: with np.nditer(arr, op_flags=['readwrite']) as it: 
     ...:    for x in it: 
     ...:        print(type(x), x) 
     ...:                                                                                              
<class 'numpy.ndarray'> 0.0
<class 'numpy.ndarray'> 0.0
<class 'numpy.ndarray'> 0.0
...
In [368]: for index,x in np.ndenumerate(arr): 
     ...:     print(type(x),x) 
     ...:                                                                                              
<class 'numpy.float64'> 0.0
<class 'numpy.float64'> 0.0
<class 'numpy.float64'> 0.0
....

以及multi_Index的使用:

In [369]: with np.nditer(arr, op_flags=['readwrite'],flags=['multi_index']) as it: 
     ...:    for x in it: 
     ...:        print(type(x), x, it.multi_index) 
     ...:                                                                                              
<class 'numpy.ndarray'> 0.0 (0, 0)
...
<class 'numpy.ndarray'> 0.5080329836279988 (1, 1)
<class 'numpy.ndarray'> 0.7805536642151875 (1, 2)

【讨论】:

  • 感谢您的建议。
  • 我不太关心速度。由于您的建议,该代码正在运行。谢谢!
猜你喜欢
  • 2022-01-26
  • 1970-01-01
  • 2022-01-23
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多