diff --git a/geopandas/geodataframe.py b/geopandas/geodataframe.py index 89671e1..2f3edae 100644 --- a/geopandas/geodataframe.py +++ b/geopandas/geodataframe.py @@ -203,7 +203,7 @@ class GeoDataFrame(GeoPandasBase, DataFrame): coerce_float, params) - def to_json(self, na='null', **kwargs): + def to_json(self, na='null', show_bbox=False, **kwargs): """Returns a GeoJSON string representation of the GeoDataFrame. Parameters @@ -215,10 +215,12 @@ class GeoDataFrame(GeoPandasBase, DataFrame): each feature individually so that features may have different properties * keep: output the missing entries as NaN + + show_bbox : include bbox (bounds) in the geojson The remaining *kwargs* are passed to json.dumps(). """ - return json.dumps(self._to_geo(na), **kwargs) + return json.dumps(self._to_geo(na, show_bbox), **kwargs) @property def __geo_interface__(self): @@ -226,11 +228,11 @@ class GeoDataFrame(GeoPandasBase, DataFrame): representation of the GeoDataFrame. This differs from `_to_geo()` only in that it is a property - with a default `na` arg instead of a method + with default args instead of a method """ - return self._to_geo(na='null') + return self._to_geo(na='null', show_bbox=True) - def _to_geo(self, na='null'): + def _to_geo(self, na='null', show_bbox=False): """Returns a python feature collection (i.e. the geointerface) representation of the GeoDataFrame. @@ -243,6 +245,8 @@ class GeoDataFrame(GeoPandasBase, DataFrame): each feature individually so that features may have different properties * keep: output the missing entries as NaN + + show_bbox : include bbox (bounds) in the geojson. default False """ def fill_none(row): @@ -267,16 +271,27 @@ class GeoDataFrame(GeoPandasBase, DataFrame): f = na_methods[na] def feature(i, row): + bbox = row[self._geometry_column_name].bounds row = f(row) - return { + feat = { 'id': str(i), 'type': 'Feature', 'properties': dict((k, v) for k, v in iteritems(row) if k != self._geometry_column_name), 'geometry': mapping(row[self._geometry_column_name]) } - return {'type': 'FeatureCollection', - 'features': [feature(i, row) for i, row in self.iterrows()]} + if show_bbox: + feat['bbox'] = bbox + + return feat + + geo = {'type': 'FeatureCollection', + 'features': [feature(i, row) for i, row in self.iterrows()]} + + if show_bbox: + geo['bbox'] = self.total_bounds + + return geo def to_file(self, filename, driver="ESRI Shapefile", **kwargs): """ diff --git a/tests/test_geodataframe.py b/tests/test_geodataframe.py index 7a4536d..48f67e4 100644 --- a/tests/test_geodataframe.py +++ b/tests/test_geodataframe.py @@ -433,3 +433,16 @@ class TestDataFrame(unittest.TestCase): self.assertEqual(len(self.df.__geo_interface__['features']), self.df.shape[0]) + def test_geodataframe_geojson_no_bbox(self): + geo = self.df._to_geo(na="null", show_bbox=False) + self.assertFalse('bbox' in geo.keys()) + for feature in geo['features']: + self.assertFalse('bbox' in feature.keys()) + + def test_geodataframe_geojson_bbox(self): + geo = self.df._to_geo(na="null", show_bbox=True) + self.assertTrue('bbox' in geo.keys()) + self.assertEqual(len(geo['bbox']), 4) + self.assertTrue(isinstance(geo['bbox'], tuple)) + for feature in geo['features']: + self.assertTrue('bbox' in feature.keys())