1

I have to select values from a scatter plot within a box. So basically I need all the values of the points within the box

N = 500
x = np.random.rand(N) * 2
y = np.random.rand(N) * 2.5
area = np.pi*3
colors = (0,0,0)

fig = plt.figure()
ax1 = fig.add_subplot(111)

plt.scatter(x, y, s=area, alpha=0.5)
plt.xlim(0.0, 2.0)
plt.ylim(0.0, 2.5)
plt.plot([0.7,1.0], [1.15,1.45], 'k--', lw=2)
plt.plot([0.3,0.6], [1.65,1.95], 'k--', lw=2)
    
plt.plot([0.7,0.3], [1.15, 1.65], 'k--', lw=2)
plt.plot([1.0, 0.6], [1.45, 1.95], 'k--', lw=2)

plt.title('Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')

enter image description here

This is similar to one of my previous questions Selecting points within a region of a scatter plot

But I am having trouble thinking of how to do it for the box instead of a polygon. I tried doing my steps before but when I try to color them different to show that I am properly selecting the points within the region, the coloration is not correct. Any help would be awesome!

C Golledge
  • 79
  • 5

1 Answers1

3

You can create line equations for each of the sides of the convex polygon. Then you can use these as a filter (you need to change the > to < if the points go the opposite way around):

from matplotlib import pyplot as plt
import numpy as np

# line equation of the form ax+by+c = 0 through (x0,y0) and (x1,y1);
# ax+by+c < 0 for points left of the line
def get_line_eq(x0, x1, y0, y1):
    return y0 - y1, x1 - x0, x0 * y1 - x1 * y0

N = 500
x = np.random.rand(N) * 2
y = np.random.rand(N) * 2.5
area = 10

fig = plt.figure()
ax1 = fig.add_subplot(111)

plt.scatter(x, y, s=area, alpha=0.5)
plt.xlim(0.0, 2.0)
plt.ylim(0.0, 2.5)

pnts = [[0.7, 1.15], [1.0, 1.45], [0.6, 1.95], [0.3, 1.65]]
pnts = pnts + [pnts[0]] # repeat first point to create a closed polygon
pnts = np.array(pnts) # numpy arrays are easier to separate x and y coordinates
plt.plot(pnts[:, 0], pnts[:, 1], 'k--', lw=2)

equations = [get_line_eq(x0, x1, y0, y1) for (x0, y0), (x1, y1) in zip(pnts[:-1], pnts[1:])]
filter = np.all([a*x + b*y + c > 0 for a, b, c in equations], axis=0)

plt.scatter(x[filter], y[filter], s=20, color='red', alpha=0.5)

plt.title('Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
# plt.gca().set_aspect('equal', 'box')  # show right angles
plt.show()

filter points inside a parallelogram

PS: plt.fill() creates a filled polygon:

plt.fill(pnts[:, 0], pnts[:, 1], fc='yellow', alpha=0.5, ec='k', ls='--', lw=2, zorder=0)
JohanC
  • 71,591
  • 8
  • 33
  • 66