Package: geopip
GEOPIP: Geojson Point in Polygon (PIP)Reverse geocode a lng/lat coordinate within a geojsonFeatureCollectionand return information about the containing country (polygon).Basically, you can use anygeojsonfile (top level is aFeatureCollection) for reverse coding - set the environment variableREVERSE_GEOCODE_DATAto the geojson file. OnlyPolygonandMultiPolygonfeatures will be used! If a point is found to be in a feature, thepropertiesof that feature will be returned.In other words, provide a geojson with postcode boundaries, and you can query for the postcode in which a coordinate is. Provide timezone boundaries and you can find the timezone for a coordinate. Be creative :).The default shape data (contained within the package) is fromthematicmapping(the simple shapes). It contains polygons representing one country with the following meta-data (properties):FIPS      String(2)         FIPS 10-4 Country Code
ISO2      String(2)         ISO 3166-1 Alpha-2 Country Code
ISO3      String(3)         ISO 3166-1 Alpha-3 Country Code
UN        Short Integer(3)  ISO 3166-1 Numeric-3 Country Code
NAME      String(50)        Name of country/area
AREA      Long Integer(7)   Land area, FAO Statistics (2002)
POP2005   Double(10,0)      Population, World Population Prospects (2005)
REGION    Short Integer(3)  Macro geographical (continental region), UN Statistics
SUBREGION Short Integer(3)  Geographical sub-region, UN Statistics
LON       FLOAT (7,3)       Longitude
LAT       FLOAT (6,3)       LatitudeHence, you can use this package as anoffline reverse geocoder on the country level(by default):In[1]:importgeopipIn[2]:geopip.search(lng=4.910248,lat=50.850981)Out[2]:{'AREA':0,'FIPS':'BE','ISO2':'BE','ISO3':'BEL','LAT':50.643,'LON':4.664,'NAME':'Belgium','POP2005':10398049,'REGION':150,'SUBREGION':155,'UN':56}NOTE: Since the polygons for each country are quite simple, reverse geocoding at the borders of two countrys isnotexact. Use polygons with higher resolution for these use cases (seeData).Theshapelypackage will be used, if installed. Otherwise, a pure python implementation will be used (on the basis ofwinding numbers). Seehere,hereandherefor more informations and example implementations. Espacially for larger features, the shapely implementation might give performance improvements (default shape data and 2.6 GHz Intel Core i7, python3.6.2, cythonized version ofgeohash-hilbert):Pure:In[1]:importgeopipIn[2]:geopip._geopip.p_in_polygon?Signature:geopip._geopip.p_in_polygon(p,shp)Docstring:Test,whetherpoint`p`isinshape`shp`.Usethepurepythonimplementationforthis.Parameters:p:Tuple[float,float]Point(lng,lat)inWGS84.shp:Dict[str,Any]Preparedshapedictionaryfrom`geopip._pure.prepare()`.Returns:boolean:True,ifpinshp,FalseotherwiseFile:~/repositories/geopip/geopip/_pure.pyType:functionIn[3]:%timeitgeopip.search(4.910248,50.850981)25.6µs±390nsperloop(mean±std.dev.of7runs,10000loopseach)Shapely:In[1]:importgeopipIn[2]:geopip_geopip.p_in_polygon?Signature:geopip._geopip.p_in_polygon(p,shp)Docstring:Test,whetherpoint`p`isinshape`shp`.Usetheshapelyimplementationforthis.Parameters:p:Tuple[float,float]Point(lng,lat)inWGS84.shp:Dict[str,Any]Preparedshapedictionaryfrom`geopip._shapely.prepare()`.Returns:boolean:True,ifpinshp,FalseotherwiseFile:~/repositories/geopip/geopip/_shapely.pyType:functionIn[3]:%timeitgeopip.search(4.910248,50.850981)50µs±601nsperloop(mean±std.dev.of7runs,10000loopseach)For simple geojsons, the pure python implementation is faster, but on more complex polygons, the shapely implementation will win.InstallpipinstallgeopipIf you require the extra speed, because you have many polygons and / or very detailed polygons, try installing geohash-hilbert with Cython extensions and / or have (vectorized) shapely installed.# make sure to have GEOS library installed (including dev extensions)pipinstallnumpy'shapely[vectorized]>=1.6'pipinstallcython# for building geohash-hilbert's cython extensionpipinstall--upgradegeohash-hilbertDataOther interesting shape data can be found at:http://www.naturalearthdata.com/downloads/: Different thematic shape files at 10m, 50m and 110m resolution.http://www.gadm.org/version2: Administrative area 0 or 1 contain contries or states, respectively. Attention to the license!https://www2.census.gov/geo/tiger/: Various shape/gdb files and information for USA.http://guides.library.upenn.edu/c.php?g=475518&p=3254770: Links to various geoinformation data.http://thematicmapping.org/downloads/world_borders.php: Country borders and some interesting information. The default file is from here. There is also a higher resolution version.https://github.com/evansiroky/timezone-boundary-builder: Time zone boundaries. See releases for downloads.https://www.suche-postleitzahl.org/plz-karte-erstellen: DE postalcodes + size + population (Census / OSM).https://www2.census.gov/geo/tiger/TIGER2010DP1/ZCTA_2010Census_DP1.zip: US postalcodes + size + population (Census; field definition seeDP_TableDescriptions.xlsin the zip).https://github.com/berlinermorgenpost/Berlin-Geodaten: Geo shapes of Berlin, DE.https://github.com/gregoiredavid/france-geojson: Geojson of regions, arrondissements, ... France.https://data.opendatasoft.com/explore/dataset/arrondissements@parisdata/: Geojson of arrondissements of Paris, FR.https://data.opendatasoft.com/pages/home/: Lots of different data, some have geojson, see above.NOTE: shapefiles / gdb databases have to be transformed into geojson. One way is to usefiona. Assuming the gdb files are in the directory/data/gdb:fioinsp/data/gdb# a python shell opens>>>importjson>>>features=[]>>>forfeatinsrc:...features+=[feat]...>>>f=open('/data/gdb.geo.json','w')>>>json.dump(dict(type='FeatureCollection',features=features),f)>>>f.close()Then thegdbwill be transformed into a geojson filegdb.geo.json.Documentation(TODOmore)
Basically, there are the two functionsgeopip.searchandgeopip.search_allthat perform the search in the providedFeatureCollection. Then there is the classgeopip.GeoPIPthat accepts aFeatureCollectioneither as a file or a dictionary and provides the same search functionality:searchIn[1]:importgeopipIn[2]:geopip.search?Signature:geopip.search(lng,lat)Docstring:Reversegeocodelng/latcoordinatewithinthefeaturesfrom`instance().shapes`.Lookwithinthefeaturesfromthe`instance().shapes`functionforapolygonthatcontainsthepoint(lng,lat).Fromthefirstfoundfeaturethe`porperties`willbereturned.`None`,ifnofeaturecontainesthepoint.Parameters:lng:floatLongitude(-180,180)ofpoint.(WGS84)lat:floatLatitude(-90,90)ofpoint.(WGS84)Returns:Dict[Any,Any]`Properties`offoundfeature.`None`ifnothingisfound.File:~/repositories/geopip/geopip/__init__.pyType:functionsearch_allIn[1]:importgeopipIn[2]:geopip.search_all?Signature:geopip.search_all(lng,lat)Docstring:Reversegeocodelng/latcoordinatewithinthefeaturesfrom`instance().shapes`.Lookwithinthefeaturesfromthe`instance().shapes`functionforallpolygonthatcontainsthepoint(lng,lat).Fromallfoundfeaturethe`porperties`willbereturned(moreorlesssortedfromsmallesttolargestfeature).`None`,ifnofeaturecontainesthepoint.Parameters:lng:floatLongitude(-180,180)ofpoint.(WGS84)lat:floatLatitude(-90,90)ofpoint.(WGS84)Returns:Iterator[Dict[Any,Any]]Iteratorfor`properties`offoundfeatures.File:~/repositories/geopip/geopip/__init__.pyType:functionGeoPIPIn[1]:importgeopipIn[2]:geopip.GeoPIP?Initsignature:geopip.GeoPIP(self,*args,**kwargs)Docstring:GeoPIP:GeojsonPointinPolygon(PIP)Reversegeocodealng/latcoordinatewithinageojson`FeatureCollection`andreturninformationaboutthecontainingpolygon.Initdocstring:Providethegeojsoneitherasafile(`filename`)orasageojsondict(`geojson_dict`).Ifnoneofbothisgiven,ittriestoloadthefilepointedtointheenvironmentvariable`REVERSE_GEOCODE_DATA`.Ifthevariableisnotset,adefaultgeojsonwillbeloaded(packaged):http://thematicmapping.org/downloads/world_borders.phpDuringinit,thegeojsonwillbeprepared(seepure/shapelyimplementation)andindexedwithgeohashes.Providetheparametersaskwargs!Allowedparameters:filename:strPathtoageojsonfile.geojson_dict:Dict[str,Any]Geojsondictionary.`FeatureCollection`required!File:~/repositories/geopip/geopip/_geopip.pyType:typeAGeoPIPobject provides the samesearchandsearch_allfunctions.