0

Attempting to make an array of 2d points.

import random
import numpy as np

world_x=500
world_y=500

num_points = 7
points_list = []

def fill_points():
    for i in range(num_points):
        points_list.append(random.randrange(-1*world_x,world_x+1))
        points_list.append(random.randrange(-1*world_y,world_y+1))
    points_array = np.array(points_list)
    points_array.reshape((num_points,2))
    print(points_array)
    print (points_array[0,])
    print (points_array[2,])
    print (points_array[4,])

fill_points()

Returns

[ -70 -491 -326  -35 -408  407   94 -330 -493  499  -61  -12   62 -357]
-70
-326
-408

I was expecting [-70,-491],[-408,-407], and [-493,499]. I've also tried to do this just using shape instead of reshape, and got similar results. Am I converting the list incorrectly, or using reshape incorrectly?

3
  • 2
    .reshape returns a new object Commented May 12, 2018 at 18:34
  • I see, if anyone else is wondering, you can just reassign the new object to the variable name points_array=points_array.reshape((num_points,2)) though @ktzr's solution below saves a line. Commented May 12, 2018 at 18:43
  • 1
    Well, you assign to variables, not objects. It doesn't make sense to say "reassign to itself*. You could assign it to a new variable or to the same variable, and use that variable to access the object, it is up to you. See my answer for an option that works in-place as well. Commented May 12, 2018 at 18:47

2 Answers 2

2

The .reshape method returns a new array object, that is, it doesn't work in-place. You can either reassign the results of reshape back to the same variable, or modify the .shape attribute directly, which does work in-place:

In [1]: import numpy as np

In [2]: arr = np.arange(10)

In [3]: arr
Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [4]: arr.reshape(2, 5)
Out[4]:
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

In [5]: arr
Out[5]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

On the other hand:

In [6]: arr.shape = 2, 5

In [7]: arr
Out[7]:
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

Or use the .resize method for in-place modifications:

In [8]: arr = np.arange(4)

In [9]: arr
Out[9]: array([0, 1, 2, 3])

In [10]: arr.resize(2, 2)

In [11]: arr
Out[11]:
array([[0, 1],
       [2, 3]])

Note: the different array objects can share the same underlying buffer, so be aware that this happens:

In [12]: arr = np.arange(10)

In [13]: arr
Out[13]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [14]: arr2 = arr.reshape(2, 5)

In [15]: arr
Out[15]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [16]: arr2
Out[16]:
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

In [17]: arr[0] = 99

In [18]: arr
Out[18]: array([99,  1,  2,  3,  4,  5,  6,  7,  8,  9])

In [19]: arr2
Out[19]:
array([[99,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9]])

So, this makes the re-assigning approach relatively cheap:

In [20]: arr = arr.reshape(2, 5)

In [21]: arr
Out[21]:
array([[99,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9]])

Note, I tend to avoid .resize, because you can accidentally do:

In [33]: arr = np.arange(4)

In [34]: arr.resize(4,4)

In [35]: arr
Out[35]:
array([[0, 1, 2, 3],
       [0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])

But it will at least warn you... if other arrays are referenced:

In [36]: arr = np.arange(4)

In [37]: arr2 = arr.reshape(2,2)

In [38]: arr
Out[38]: array([0, 1, 2, 3])

In [39]: arr2
Out[39]:
array([[0, 1],
       [2, 3]])

In [40]: arr.resize(4,4)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-40-c4464d98ed0e> in <module>()
----> 1 arr.resize(4,4)

ValueError: cannot resize an array that references or is referenced
by another array in this way.  Use the resize function

However, you can override that behavior at your own peril:

In [41]: arr.resize(4,4, refcheck=False)

In [42]: arr
Out[42]:
array([[0, 1, 2, 3],
       [0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])

In [43]: arr2
Out[43]:
array([[4611686018427387904, 4611686018427387904],
       [                  6,                   0]])
Sign up to request clarification or add additional context in comments.

Comments

1

It looks like you want to keep the x and y cords together, try adding them as a list. E.g.:

import random
import numpy as np

world_x=500
world_y=500

num_points = 7
points_list = []

def fill_points():
    for i in range(num_points):
        points_list.append([random.randrange(-1*world_x,world_x+1),
                            random.randrange(-1*world_y,world_y+1)])
    points_array = np.array(points_list)
    print(points_array)
    print (points_array[0,0])
    print (points_array[2,0])
    print (points_array[4,0])

fill_points()

Outputs:

[[ 354 -147]
 [ 193  288]
 [ 157 -319]
 [ 133  426]
 [-109  -54]
 [ -61  224]
 [-251 -411]]
354
157
-109

Or if you want to use reshape. Remember reshape returns a new list, it doesnt change the list you input:

def fill_points():
    for i in range(num_points):
        points_list.append(random.randrange(-1*world_x,world_x+1))
        points_list.append(random.randrange(-1*world_y,world_y+1))
    points_array = np.array(points_list).reshape((num_points,2))
    print(points_array)
    print (points_array[0,0])
    print (points_array[2,0])
    print (points_array[4,0])

fill_points()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.