BUG: preserve metadata on merge/concat (#247, #320) (#322)

This commit is contained in:
Joris Van den Bossche
2016-05-26 23:28:07 +02:00
parent 320b75d185
commit 0f82cedf55
2 changed files with 77 additions and 7 deletions
+15 -7
View File
@@ -409,10 +409,18 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
return GeoDataFrame
def __finalize__(self, other, method=None, **kwargs):
""" propagate metadata from other to self """
# NOTE: backported from pandas master (upcoming v0.13)
for name in self._metadata:
object.__setattr__(self, name, getattr(other, name, None))
"""propagate metadata from other to self """
# merge operation: using metadata of the left object
if method == 'merge':
for name in self._metadata:
object.__setattr__(self, name, getattr(other.left, name, None))
# concat operation: using metadata of the first object
elif method == 'concat':
for name in self._metadata:
object.__setattr__(self, name, getattr(other.objs[0], name, None))
else:
for name in self._metadata:
object.__setattr__(self, name, getattr(other, name, None))
return self
def copy(self, deep=True):
@@ -443,7 +451,7 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
def dissolve(self, by=None, aggfunc='first'):
"""
Dissolve geometries within `groupby` into single observation.
Dissolve geometries within `groupby` into single observation.
Parameters
----------
@@ -473,14 +481,14 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
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),
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,
aggregated_geometry = GeoDataFrame(g,
index=g.index,
geometry=self.geometry.name)
# Recombine
+62
View File
@@ -0,0 +1,62 @@
from __future__ import absolute_import
import pandas as pd
from shapely.geometry import Point
from geopandas import GeoDataFrame, GeoSeries
from geopandas.tests.util import unittest
class TestMerging(unittest.TestCase):
def setUp(self):
self.gseries = GeoSeries([Point(i, i) for i in range(3)])
self.series = pd.Series([1, 2, 3])
self.gdf = GeoDataFrame({'geometry': self.gseries, 'values': range(3)})
self.df = pd.DataFrame({'col1': [1, 2, 3], 'col2': [0.1, 0.2, 0.3]})
def _check_metadata(self, gdf, geometry_column_name='geometry', crs=None):
self.assertEqual(gdf._geometry_column_name, geometry_column_name)
self.assertEqual(gdf.crs, crs)
def test_merge(self):
res = self.gdf.merge(self.df, left_on='values', right_on='col1')
# check result is a GeoDataFrame
self.assert_(isinstance(res, GeoDataFrame))
# check geometry property gives GeoSeries
self.assert_(isinstance(res.geometry, GeoSeries))
# check metadata
self._check_metadata(res)
## test that crs and other geometry name are preserved
self.gdf.crs = {'init' :'epsg:4326'}
self.gdf = (self.gdf.rename(columns={'geometry': 'points'})
.set_geometry('points'))
res = self.gdf.merge(self.df, left_on='values', right_on='col1')
self.assert_(isinstance(res, GeoDataFrame))
self.assert_(isinstance(res.geometry, GeoSeries))
self._check_metadata(res, 'points', self.gdf.crs)
def test_concat_axis0(self):
res = pd.concat([self.gdf, self.gdf])
self.assertEqual(res.shape, (6, 2))
self.assert_(isinstance(res, GeoDataFrame))
self.assert_(isinstance(res.geometry, GeoSeries))
self._check_metadata(res)
def test_concat_axis1(self):
res = pd.concat([self.gdf, self.df], axis=1)
self.assertEqual(res.shape, (3, 4))
self.assert_(isinstance(res, GeoDataFrame))
self.assert_(isinstance(res.geometry, GeoSeries))
self._check_metadata(res)