MasovyKnedlicek
MasovyKnedlicek

Reputation: 96

Python numpy array - fill fast with values of coordinates

I have a huge number of points that represent centers of gravity of rectangles. My task is to create a 3D numpy array of a shape (len(x_values) * len(y_values), 4, 2) that would contain [x,y] coordinates of all 4 tops of those rectangles.

Example:

[[[3.  3.5]     # 4.0 - 2.0/2, 5.0 - 3.0/2 ... first top
  [3.  6.5]     # 4.0 - 2.0/2, 5.0 + 3.0/2 ... second top
  [5.  6.5]     # 4.0 + 2.0/2, 5.0 + 3.0/2 ... third top
  [5.  3.5]]    # 4.0 + 2.0/2, 5.0 - 3.0/2 ... fourth top
  
  ...           # other points
]  

I wrote this code:

import numpy as np
import random


# Just an example of points that represent centers of gravity of rectangles; 500 000 in total
x_values = [random.uniform(0, 10) for _ in range(1000)]
y_values = [random.uniform(0, 10) for _ in range(500)]

WIDTH = 2.0
HEIGHT = 3.0

my_points = np.zeros(shape=(len(x_values) * len(y_values), 4, 2), dtype=np.float64)

ii = 0
for y in y_values:
    for x in x_values:
        # [x, y] ... center of gravity of a rectangle
        my_points[ii][0][0] = x - WIDTH*0.5
        my_points[ii][0][1] = y - HEIGHT*0.5
        my_points[ii][1][0] = x - WIDTH*0.5
        my_points[ii][1][1] = y + HEIGHT*0.5
        my_points[ii][2][0] = x + WIDTH*0.5
        my_points[ii][2][1] = y + HEIGHT*0.5
        my_points[ii][3][0] = x + WIDTH*0.5
        my_points[ii][3][1] = y - HEIGHT*0.5
        ii += 1

However, this approach is really slow for huge number of points. Is there a better and faster way how to fill the array?

Upvotes: 1

Views: 862

Answers (1)

Stef
Stef

Reputation: 30579

The speedup comes from vectorizing the assignment and eliminating the python loop.

my_points = np.empty(shape=(len(x_values) * len(y_values), 4, 2), dtype=np.float64)

x = np.tile(x_values, len(y_values))
y = np.repeat(y_values, len(x_values))

my_points[:,1,0] = my_points[:,0,0] = x - WIDTH*0.5
my_points[:,3,1] = my_points[:,0,1] = y - HEIGHT*0.5
my_points[:,2,1] = my_points[:,1,1] = y + HEIGHT*0.5
my_points[:,3,0] = my_points[:,2,0] = x + WIDTH*0.5

Upvotes: 2

Related Questions