2

My array is from a image whick like below:

[[[ 66.17041352  32.64576397  20.96214396]                                                                                                                               
  [ 66.17041352  32.64576397  20.96214396]
  [ 65.96318838  32.36065031  16.13857633]
  ...,
  [ 69.04849876  28.06324166  26.57747623]
  [ 63.7269604   32.96378326  25.94336956]
  [ 53.96807994  39.33219382  23.9025511 ]]

 ...,
 [[ 18.55833403  34.4104455   -9.75497344]
  [ 18.55833403  34.4104455   -9.75497344]
  [ 21.45103128  32.77919479  -3.84284208]
  ...,
  [ 44.64859327  41.89617915  14.25196745]
  [ 43.40291913  43.25109885  17.43372679]
  [ 43.30009306  47.94315449  15.59464532]]

 [[ 18.64249436  31.63054472  -7.56023249]
  [ 18.64249436  31.63054472  -7.56023249]
  [ 23.23099091  32.284216    -3.86411699]
  ...,
  [ 44.98536772  45.0246078   17.92556564]
  [ 45.53417128  45.42120428  17.50264622]
  [ 46.7226915   45.42428651  19.21054283]]]

I want to change the array to zero like this:

[[[ 0.  0.  0.]
  [ 0.  0.  0.]
  [ 0.  0.  0.]
  ...,
  [ 0.  0.  0.]
  [ 0.  0.  0.]
  [ 0.  0.  0.]]

 ...,

 [[ 0.  0.  0.]
  [ 0.  0.  0.]
  [ 0.  0.  0.]
  ...,

 [[ 0.  0.  0.]
  [ 0.  0.  0.]
  [ 0.  0.  0.]
  ...,
  [ 0.  0.  0.]
  [ 0.  0.  0.]
  [ 0.  0.  0.]]]

I know how to make it happen, but I just wonder why my origin code doesn't work.The print shows that nothing changed.

for row in image_arr:
    for col in row:
        col = [0,0,0]

print image_arr
scriptboy
  • 777
  • 8
  • 25

6 Answers6

4

In your loop, you are just reassigning the name col to the list [0,0,0], over and over and over again. Not at all what you want! To change your 3d array to all zeros, you simply do this.:

arr[:, :, :,] = 0

Bing bang boom, you're done.

Cody Piersall
  • 8,312
  • 2
  • 43
  • 57
  • 5
    This is the first answer to make it clear that `col = [0,0,0]` is just a _name rebinding_-- that's the critical problem. The fact that numpy doesn't return copies here but views of the original object which can be mutated (like `col[:] = 0`) is just a fact about _numpy_; the fact that `col = [0, 0, 0]` was never going to work is a fundamental fact about _Python_. – DSM Mar 12 '17 at 02:37
  • 2
    Or in fewer characters, `arr[...] = 0` or even `arr[()] = 0` – Eric Mar 12 '17 at 13:05
0

Is because col is a value not a reference , see Python objects confusion: a=b, modify b and a changes!

try instead :

a=0
b=0

for row in image_arr:

    for col in row:
        image_arr[a][b] = [0,0,0]
        a=a+1
    b=b+1

print image_arr
Community
  • 1
  • 1
Lullu
  • 1
  • 3
0

This is because col is a copy not a reference. This is true for all of python:

CODE Example:

simple = [1,2,3,4,5,6]
print simple
for elem in simple:
    elem = 0
print simple

OUTPUT:

[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]

Try this instead:

rows,cols,lens = arr.shape
for r in range(rows):
    for c in range(cols):
        arr[r][c] = [0,0,0]
mitoRibo
  • 4,468
  • 1
  • 13
  • 22
  • 1
    `col` isn't a copy of anything. And if it were, then `arr[r]` would also be a copy, and so `arr[r][c] = something` would also fail to modify `arr`. – DSM Mar 12 '17 at 02:29
0

You change the value col in the loop but it's not related to the original variable image_arr. You can use enumerate to access the index and modify image_arr variable directly. As in the following example:

import numpy as np
image_arr = np.arange(30).reshape(3, 5, 2)
print(image_arr)

for i,row in enumerate(image_arr):
    for j,col in enumerate(row):
        image_arr[i][j]=0

print(image_arr)
Xu Han
  • 89
  • 1
  • 4
0

You are changing col to a new list, but col is not a reference to a sublist of row. Instead, if you change the elements of col, then you will get the result you want:

for row in image_arr:
    for col in row:
        for i in range(len(col))
            col[i] = 0
Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
0

col is a 1d array, a view of arr. To change its values you need to use slicing notation. col=[0,0,0] reassigns the variable without mutating the iteration variable. Mutability is a key concept here (and applicable to lists and dictionaries as well).

In [254]: arr = np.ones((2,3,4))
In [255]: for row in arr:
     ...:     for col in row:
     ...:         col[:] = 0   # or = [1,2,3,5]
     ...:         
In [256]: arr
Out[256]: 
array([[[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]],

       [[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]]])

And since you want to change all the values, col[:]=0 works just as well as col[:]=[0,0,0,0] (in my shape).

But while we are at it, any of these also work

In [257]: for row in arr:
     ...:     row[:,:] = 1
     ...:     
In [258]: arr
Out[258]: 
array([[[ 1.,  1.,  1.,  1.],
        [ 1.,  1.,  1.,  1.],
 ...]]])
In [259]: arr[:,:,:]=2     # one : per dimension
In [260]: arr[...] = 3     # ... shorthand for multiple :

But why reset arr? Why not make a new array with the same shape (and throw away the 'original')?

arr1 = np.zeros_like(arr)
hpaulj
  • 221,503
  • 14
  • 230
  • 353