How to delete a set of meshgrid points inside a circle?

前端 未结 3 653
[愿得一人]
[愿得一人] 2021-01-13 22:10

I am trying to create a meshgrid without some of the points that falls within the circle having specified coordinates and a radius. I am not able to subtract the grid points

3条回答
  •  青春惊慌失措
    2021-01-13 22:59

    If you'd like a scatter plot with just the points outside the circle, use boolean indexing to select only those points from your 2D "meshgridded" array:

    import numpy as np
    import matplotlib.pyplot as plt
    
    N = 50
    x_start, x_end = -2.0, 2.0
    y_start, y_end = -1.0, 1.0
    
    x = np.linspace(x_start, x_end, N)
    y = np.linspace(y_start, y_end, N)
    
    x0, y0, radius = 0.0, 0.0, 0.4
    
    x, y = np.meshgrid(x, y)
    r = np.sqrt((x - x0)**2 + (y - y0)**2)
    
    outside = r > radius
    
    fig, ax = plt.subplots()
    ax.set(xlabel='X', ylabel='Y', aspect=1.0)
    
    ax.scatter(x[outside], y[outside])
    
    plt.show()
    

    enter image description here


    On the other hand, if you were using something like imshow that requires 2D input, you'd need to either mask the values inside (as @JulienSpronck mentions, though it would be better to set them to np.nan or use a masked array than to set them to 0) or set a clip path on the image.

    For scatter, however, you don't need 2D input.


    Boolean indexing on a nD array will return a 1d result. For example:

    In [9]: x = np.arange(100).reshape(10, 10)
    
    In [10]: x
    Out[10]: 
    array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
           [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
           [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
           [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
           [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
           [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
           [70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
           [80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
           [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
    
    In [11]: x[x > 75]
    Out[11]: 
    array([76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
           93, 94, 95, 96, 97, 98, 99])
    

    Because scatter is only plotting points, it doesn't care how they're connected, and we can easily use the 1D result of boolean indexing.

    On the other hand, if you wanted to plot an image, you'd need a 2D grid. In that case, you'd want to mask the values instead:

    In [12]: np.ma.masked_where(x <= 75, x)
    Out[12]: 
    masked_array(data =
     [[-- -- -- -- -- -- -- -- -- --]
     [-- -- -- -- -- -- -- -- -- --]
     [-- -- -- -- -- -- -- -- -- --]
     [-- -- -- -- -- -- -- -- -- --]
     [-- -- -- -- -- -- -- -- -- --]
     [-- -- -- -- -- -- -- -- -- --]
     [-- -- -- -- -- -- -- -- -- --]
     [-- -- -- -- -- -- 76 77 78 79]
     [80 81 82 83 84 85 86 87 88 89]
     [90 91 92 93 94 95 96 97 98 99]])
    

    Notice how this maintains the 2D structure of the input.

    On a side note, if this were a floating point array, you could just as easily set the values to np.nan instead of masking them. When plotted with imshow, the two will behave identically. I used a masked array in this case because x was an integer array and can't contain NaN's.

提交回复
热议问题