title: How to optimize repeated checking if a point is in a polygon
body: <p><strong>I have a <code>MultiPolygon</code> that represents a road and would like to find whether some GPS points fall within x distance from the road. My <code>geo_buf</code> below is <code>road.buffer(x)</code>. Using repeated <code>geo_buf.contains(Point)</code> is very slow, as shown in the profiling below (most of the time is spent running line 297).</strong></p>
  
  <p>How can i optimize the speed?</p>
  
  <pre><code>from line_profiler import LineProfiler
  from shapely.geometry import Point as shapely_Point
  
  Line #      Hits         Time  Per Hit   % Time  Line Contents
  ==============================================================
     151                                           def filter_gps(gps_row, geo_buf):
     152    606446   62042960.0    102.3     83.3      pot = shapely_Point(gps_row['longitude'], gps_row['latitude'])
     153    606446   12433530.0     20.5     16.7      return geo_buf.contains(pot)
  
  
  
  Line #      Hits         Time  Per Hit   % Time  Line Contents
  ==============================================================
  
    294      1232      11850.0      9.6       0.0   if len(df_gps.index) &gt; 1:
    295                                               geo_buf = shape(json.loads(srg_row['srg_buf']))
    296                                               # filter the GPS points
    297      1232   98465688.0  79923.4     68.4      df_filter = df_gps[df_gps.apply(lambda row: filter_gps(row, geo_buf), axis=1)]
  </code></pre>