1

I have to select values from a scatter plot between two regions. These are defined as the black and the red line. So basically I need all the values of the points between the red and black line.

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, 0.8], [1.1, 1.1], 'k-', lw = 2, c = 'r')
plt.plot([0, 0.8], [1.5, 1.5], 'k-', lw =2)

plt.plot([1.8, 1.8], [2.0, 2.5], 'k-', lw = 2, c = 'r')
plt.plot([1.4, 1.4], [2.05, 2.5], 'k-', lw =2)

plt.plot([0.8, 1.8], [1.1, 2.0], 'k-', lw = 2, c = 'r')
plt.plot([0.8, 1.4], [1.5, 2.05], 'k-', lw = 2)

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

enter image description here

This is just an example for general terms. My points aren't random but come from a dictionary. I do not know how to select the values within that region. Let me know if you have any questions or concerns.

C Golledge
  • 79
  • 5
  • 1
    You could create a polygon from your 6 points and then use [this solution](https://stackoverflow.com/questions/36399381/whats-the-fastest-way-of-checking-if-a-point-is-inside-a-polygon-in-python) – JohanC Jul 02 '20 at 19:47

1 Answers1

2

We can create a filter (as a boolean expression) for the convex region delimited by the 3 red lines:

(y >= 1.1) & (x <= 1.8) & (ar * x + br * y + cr >= 0)

The equation of the diagonal line can be found by solving a general equation ax+by+c=0 to go through 2 specific points. The equation will be zero on the line, negative on the 'left' side and positive on the 'right' side.

A similar filter defines the region delimited by the black lines. And the expression in_red & ~in_black defines the region of interest. Such a filter can be used to select the points to be drawn, but could also be used to select the points for other calculations.

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.uniform(0, 2, N)
y = np.random.uniform(0, 2.5, N)

ar, br, cr = get_line_eq(0.8, 1.8, 1.1, 2.0)
in_red = (y >= 1.1) & (x <= 1.8) & (ar * x + br * y + cr >= 0)
ak, bk, ck = get_line_eq(0.8, 1.4, 1.5, 2.05)
in_black = (y >= 1.5) & (x <= 1.4) & (ak * x + bk * y + ck >= 0)

plt.scatter(x[in_black], y[in_black], s=5, c='k') # inside the black region
plt.scatter(x[~in_red], y[~in_red], s=5, c='b') # outside the red region
plt.scatter(x[in_red & ~in_black], y[in_red & ~in_black], s=5, c='r') # inside red but outside black

plt.xlim(0.0, 2.0)
plt.ylim(0.0, 2.5)
plt.plot([0, 0.8], [1.1, 1.1], 'k-', lw=2, c='r')
plt.plot([0, 0.8], [1.5, 1.5], 'k-', lw=2)

plt.plot([1.8, 1.8], [2.0, 2.5], 'k-', lw=2, c='r')
plt.plot([1.4, 1.4], [2.05, 2.5], 'k-', lw=2)

plt.plot([0.8, 1.8], [1.1, 2.0], 'k-', lw=2, c='r')
plt.plot([0.8, 1.4], [1.5, 2.05], 'k-', lw=2)

plt.tight_layout()
plt.show()

example plot

JohanC
  • 71,591
  • 8
  • 33
  • 66