Merge pull request #311 from nickeubank/add_dissolve

Add dissolve method to GeoDataFrame
This commit is contained in:
Kelsey Jordahl
2016-05-16 22:48:49 -07:00
2 changed files with 112 additions and 1 deletions
+48 -1
View File
@@ -8,7 +8,7 @@ import os
import sys
import numpy as np
from pandas import DataFrame, Series
from pandas import DataFrame, Series, Index
from shapely.geometry import mapping, shape
from shapely.geometry.base import BaseGeometry
from six import string_types
@@ -441,6 +441,53 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
plot.__doc__ = plot_dataframe.__doc__
def dissolve(self, by=None, aggfunc='first'):
"""
Dissolve geometries within `groupby` into single observation.
Parameters
----------
by : string, default None
Column whose values define groups to be dissolved
aggfunc : function or string, default "first"
Aggregation function for manipulation of data associated
with each group. Passed to pandas `groupby.agg` method.
Returns
-------
GeoDataFrame
"""
# Process non-spatial component
data = self.drop(labels=self.geometry.name, axis=1).copy()
aggregated_data = data.groupby(by=by).agg(aggfunc)
# Process spatial component
groupby_plus_geometry_cols = [self.geometry.name]
groupby_plus_geometry_cols.append(by)
geometry = self[groupby_plus_geometry_cols].copy()
def merge_geometries(block):
merged_geom = block.unary_union
new_index = block.drop(self.geometry.name, axis=1).iloc[0][by]
merged_w_index = GeoSeries(merged_geom, index=Index(Series(new_index),name=by),
name=self.geometry.name)
return merged_w_index
g = geometry.groupby(by=by, group_keys=False).apply(merge_geometries)
aggregated_geometry = GeoDataFrame(g,
index=g.index,
geometry=self.geometry.name)
# Recombine
aggregated = aggregated_geometry.join(aggregated_data)
aggregated = aggregated.set_geometry(self.geometry.name)
return aggregated
def _dataframe_set_geometry(self, col, drop=False, inplace=False, crs=None):
if inplace:
raise ValueError("Can't do inplace setting when converting from"
+64
View File
@@ -0,0 +1,64 @@
from __future__ import absolute_import
import tempfile
import shutil
import numpy as np
from shapely.geometry import Point
from geopandas import GeoDataFrame, read_file
from geopandas.tools import overlay
from .util import unittest, download_nybb
from pandas.util.testing import assert_frame_equal
from pandas import Index
class TestDataFrame(unittest.TestCase):
def setUp(self):
nybb_filename, nybb_zip_path = download_nybb()
self.polydf = read_file(nybb_zip_path, vfs='zip://' + nybb_filename)
self.polydf = self.polydf[['geometry', 'BoroName', 'BoroCode']]
self.polydf = self.polydf.rename(columns={'geometry':'myshapes'})
self.polydf = self.polydf.set_geometry('myshapes')
self.polydf['manhattan_bronx'] = 5
self.polydf.loc[3:4,'manhattan_bronx']=6
# Merged geometry
manhattan_bronx = self.polydf.loc[3:4,]
others = self.polydf.loc[0:2,]
collapsed = [others.geometry.unary_union, manhattan_bronx.geometry.unary_union]
merged_shapes = GeoDataFrame({'myshapes': collapsed}, geometry='myshapes',
index=Index([5,6], name='manhattan_bronx'))
# Different expected results
self.first = merged_shapes.copy()
self.first['BoroName'] = ['Staten Island', 'Manhattan']
self.first['BoroCode'] = [5, 1]
self.mean = merged_shapes.copy()
self.mean['BoroCode'] = [4,1.5]
def test_geom_dissolve(self):
test = self.polydf.dissolve('manhattan_bronx')
self.assertTrue(test.geometry.name == 'myshapes')
self.assertTrue(test.geom_almost_equals(self.first).all())
def test_first_dissolve(self):
test = self.polydf.dissolve('manhattan_bronx')
test = test.drop('myshapes', axis=1)
first = self.first.drop('myshapes', axis=1)
assert_frame_equal(first, test)
def test_mean_dissolve(self):
test = self.polydf.dissolve('manhattan_bronx', aggfunc='mean')
test = test.drop('myshapes', axis=1)
mean = self.mean.drop('myshapes', axis=1)
assert_frame_equal(mean, test)
test = self.polydf.dissolve('manhattan_bronx', aggfunc=np.mean)
test = test.drop('myshapes', axis=1)
assert_frame_equal(mean, test)