1

I have a grid point shapefile. I want to select N number of samples from those set of grid points. I tried pd.DataFrame.sample() but as we know it selects samples randomly. Is there any way I can select samples across those grid points uniformly?

I am using geopandas to read the shapefile. Below is pictorial representation of the task.(Not necessarily 1 step skip, it can be any but it should be uniform)

Edit: I need to select points such that deviation of distance between selected points is minimum to get a proper representation of whole area.

Below is a example I want to sample ~40 points.

Total Grid points:

Grid points

Bad Sampling:

enter image description here

Good Sampling:

Sampled points

6
  • Uniform how, can you circle some of the points as an example?
    – Bera
    Commented Jul 27, 2022 at 8:28
  • @BERA if you see both images every other point is selected in second image (1 point skipped). But when I use df.sample(N) it selects N number of samples randomly no specific skip/distance between two points. I need to select points such that deviation of distance between two selected points is minimum.
    – TK7372
    Commented Jul 27, 2022 at 8:35
  • couldn't you sort your dataframe by (y axis, x axis) and then itererate over your sorted dataframe and extract every other feature with a counter for example and if counter % 2 == 0: ?? edit: I guess it wouldn't work really well if you have an odd number of columns or rows because there would be a shift every other row / column
    – Kalak
    Commented Jul 27, 2022 at 9:15
  • Yes that would not work well. Also it is not necessary that it should select every other point, I have given just representation. I just want to select points such that deviation of distance between selected points is minimum.
    – TK7372
    Commented Jul 27, 2022 at 9:21
  • Then you should try something along these lines : 1. create a list with the first point of the data frame, 2. than while iterating over the rest of the dataframe only add the current point to the list if it is not within x meters from any of the points in the list with something like scipy.spatial.distance.cityblock() or scipy.spatial.distance.euclidean()
    – Kalak
    Commented Jul 27, 2022 at 9:51

1 Answer 1

1

This works nicely for what you want with two variants either with Euclidean distances or cityblock/Manhattan distances (check this explanation between the two distance calculation methods slide 3->5)

You can modify the DISTANCE_MIN constant to change the minimum distance between two points

import pandas as pd
from scipy.spatial.distance import euclidean, cityblock


DISTANCE_MIN = 80

df # pd.DataFrame
#              0          1
#0      156.4545  2204.0766
#1      156.4545  2154.0766
#2      156.4545  2104.0766
#3      156.4545  2054.0766
#4      156.4545  2004.0766
#               ...
#1171  2906.4545  1404.0766
#1172  2906.4545  1354.0766
#1173  2906.4545  1304.0766
#1174  2906.4545  1254.0766
#1175  2906.4545  1204.0766

first = True
list_ok = []

for index, row in df.iterrows():
    if first:
        list_ok.append([row[0], row[1]])
        first = False
        continue
    
    point = [row[0], row[1]]
    if any((euclidean(point, point_ok) < DISTANCE_MIN for point_ok in list_ok)):
        continue
    
    list_ok.append(point)

df_out = pd.DataFrame(list_ok)
print(df_out)
#             0          1
#0     156.4545  2204.0766
#1     156.4545  2104.0766
#2     156.4545  2004.0766
#3     156.4545  1904.0766
#4     156.4545  1804.0766
#..                ...
#303  2856.4545  1604.0766
#304  2856.4545  1504.0766
#305  2856.4545  1404.0766
#306  2856.4545  1304.0766
#307  2856.4545  1204.0766

enter image description here

5
  • Thanks! I have a further question. What if I want select a specific number of samples. e.g only 100.
    – TK7372
    Commented Jul 27, 2022 at 10:53
  • You don't mean just the first 100 I imagine but have 100 uniformly placed over your population (points) right ?
    – Kalak
    Commented Jul 27, 2022 at 11:28
  • Yes that's right.
    – TK7372
    Commented Jul 27, 2022 at 11:29
  • You have two options in my opinion, either change the DISTANCE_MIN until you have around 100 points in output (aproximation) or in my opinion what would be better would be to just use pd.DataFrame.sample in this situation you could even try multiple random samples of 100 and test the average deviation in distances in the different samples to choose the most uniform one (this way you are sure to have 100 points and "some" uniformity
    – Kalak
    Commented Jul 27, 2022 at 11:35
  • Lets say Instead selecting from the existing points, can we plot new points on polygon/shapefile uniformly instead? gis.stackexchange.com/questions/436919/…
    – TK7372
    Commented Jul 27, 2022 at 11:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.