Coordinates of 2D points zoomed in/out
When working with NumPy, it's best to keep all our data in the form of NumPy arrays, instead of converting back and forth between NumPy and Python data structures.


So instead of creating a NumPy array for each point and then zipping them to extract tuples of \$x\$-coordinates and \$y\$-coordinates, create one array for all the points:

p = np.random.uniform(0., 1000., (N, 2))


We can extract the \$x\$-coordinates and \$y\$-coordinates, if we need them, by transposing the array:

x, y = p.T


but we won't need to do so until the very end when we pass the data to Matplotlib.
The coordinates of the origin can be computed like this:

o = (p.min(axis=0) + p.max(axis=0)) * .5

To scale the points about the origin, use:

q = o * (1 - scale) + p * scale


instead of (as in the code in the post):

delta = p - o
q = o + delta * scale


The former is slightly quicker, as it has only two arithmetic operations on arrays as long as p whereas the latter has three.


Putting this together:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches

N = 5
p = np.random.uniform(0., 1000., (N, 2))

# Center of points, defined as the center of the minimal rectangle
# that contains all points.
o = (p.min(axis=0) + p.max(axis=0)) * .5

# Scale factor (0. &lt; scale)
scale = 1.5

# Points scaled about center.
q = o * (1 - scale) + p * scale

ax = plt.subplot(111)
ax.scatter(*p.T, c='b')           # Original points.
ax.scatter(*o, marker='x', c='g') # Center.
ax.scatter(*q.T, c='r')           # Scaled points.
ax.add_patch(patches.Rectangle(p.min(axis=0), *p.ptp(axis=0), fill=False))
plt.show()


Here numpy.ptp stands for peak-to-peak and computes the range of values (maximum − minimum) along an axis in an array.