0

I am trying to filter my file on geo coordinates to keep only coordinates located in Manhattan using Python and Folium. I've tried setting my own limits:

top_left = [40.806470, -73.973205]
bottom_left = [40.709729, -74.035690]
bottom_right = [40.696715, -73.992431]
top_right = [40.781518, -73.934066]

low_lat = bottom_right[0]
high_lat = top_left[0]       
low_lon = top_right[1]
high_lon = bottom_left[1]

df_bad = df.loc[
    (df["Point_latitude"] < high_lat) & 
    (df["Point_latitude"] > low_lat) &
    (df["Point_longitude"] > high_lon) &
    (df["Point_longitude"] < low_lon)
]

My problem with this method is that it includes parts of NYC I don't want to include. It is a straight box like this:

Before

I would like to filter my map like this: enter image description here

Is there a way to do that? Or maybe a new library that would allow me to do that?

Thank you

Community
  • 1
  • 1
nickfrenchy
  • 293
  • 4
  • 16
  • Pretty sure folium supports polylines: https://github.com/python-visualization/folium/blob/master/examples/line_example.py – Benjamin Jul 09 '16 at 13:18

1 Answers1

0

Use can use shapely for that. https://pypi.python.org/pypi/Shapely . In fact, you can create polygons and other geospatial features with it. Potentially, you do not need any df. Here is a complete example using your polygon and random points. You do not need all of these modules, but I show you that you can solve your problem in many ways:

import json
import geojson
from shapely.geometry import mapping, shape, Polygon, MultiPoint
import shapely.wkt as wkt
import folium

top_left = [-73.973205, 40.806470]
bottom_left = [-74.035690, 40.709729]
bottom_right = [-73.992431, 40.696715]
top_right = [-73.934066, 40.781518]

coordinates =[(-74, 40.74),(-74, 40.76),(-74, 40.78),(-74, 40.81)]
coordinates_shapely = MultiPoint(coordinates)

# 1. create a polygon:
polyNY_shapely = Polygon([(top_left), (bottom_left), (bottom_right), (top_right)])
# OR 
polyNY_json = {
"coordinates": [[top_left, bottom_left, bottom_right, top_right, top_left]], 
"type": "Polygon"
}


# 2. create the geojson of the polygon
g1 = wkt.loads(polyNY_shapely.wkt)
g2a = geojson.Feature(geometry=g1)
# OR
g2b = json.dumps(mapping(shape(polyNY_json)))

# 3. create map with polygon and all coordinates
map_osm = folium.Map(location=[40.7, -74.0],zoom_start=12)
folium.GeoJson(
g2a,
style_function=lambda feature: {
    'fillColor': '#ffff00',
    'color' : 'blue',
    'weight' : 2
    }).add_to(map_osm)
for cc in coordinates:
    folium.Marker(cc[::-1], popup='point '+str(cc)).add_to(map_osm)
map_osm.save('shapelyfolium.html')

# add points to map after filtering
for pp in range(len(list(coordinates_shapely))):
    print polyNY_shapely.contains(coordinates_shapely[pp])
    if polyNY_shapely.contains(coordinates_shapely[pp]):
        folium.Marker(coordinates[pp][::-1], popup='point '+str(pp),icon = folium.Icon(color='red')).add_to(map_osm)
# OR
# if pp.within(polyNY_shapely):
#     folium.Marker(row, popup='point '+str(index),icon = folium.Icon(color='red')).add_to(map_osm)
map_osm.save('shapelyfoliumAfterfiltering.html')

map before filtering map after filtering

giosans
  • 1,136
  • 1
  • 12
  • 30
  • 2
    Hello, Could you elaborate a bit more on how to use it for this use case? It looks like this could be useful but I'm not sure I understand how to apply it in this case. – nickfrenchy Jul 09 '16 at 13:15
  • 1
    creating a polygon is done using http://toblerity.org/shapely/manual.html#polygons . When you say "filter my file" I assume you only want to have points within that area. In that case follow this tutorial http://streamhacker.com/2010/03/23/python-point-in-polygon-shapely/ . If that's not what you mean with "filter my file", I'll have to ask you to elaborate better your question. – giosans Jul 09 '16 at 13:29
  • Yes I want to keep points in the area. Shapely looks like the right tool however I'm not sure how to use it. When I use the Polygon function with my area limit coordinates, I get TypeError: __init__() takes from 1 to 3 positional arguments but 9 were given... – nickfrenchy Jul 09 '16 at 18:23
  • 1
    Cannot say what gave you the error though, because you did not type your code. What Polygon function takes is explained here http://stackoverflow.com/questions/30457089/python-shapely-how-to-create-a-polygon-given-its-point-vertices or in the manual. – giosans Jul 10 '16 at 00:17
  • Ok yes I was doing it wrong I guess. I now have my polygon using coordinates as points. Now I guess I should convert the coordinates in my files to Points and use the point.within(polygon) from the link you posted above right? – nickfrenchy Jul 10 '16 at 15:38
  • 1
    You could use polygon.contains(point) after creating point object using shapely Point class. – giosans Jul 11 '16 at 06:56
  • I have my latitude and my longitude in 2 columns. I concatenated them into one 'point' column. I am trying to convert it to a Point format but I don't think I'm doing it properly as it asks for a float... Concat: df_co['point'] = df_co["Pickup_latitude"].map(str) + ','+df_co["Pickup_longitude"].map(str) Point and map: for index, row in df_co.iterrows(): point = Point(df_co['point']) loc = [df['Pickup_latitude'], df['Pickup_longitude']] if poly.contains(point): map_osm.polygon_marker(location= loc ,fill_color='#FFFFFF', num_sides=5, radius=5) – nickfrenchy Jul 11 '16 at 12:12
  • 1
    Sorry I didn't have much time lately. I update the complete solution to your question. Hope you are satisfied with it. – giosans Jul 15 '16 at 14:52