mirror of
https://github.com/wassname/geopandas.git
synced 2026-09-09 11:22:50 +08:00
Added support for null geometries for to_file and from_file functions
- Closes-Bug: #138
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
|
||||
|
||||
"features": [
|
||||
{ "type": "Feature", "properties": { "Name": "Null Geometry" }, "geometry": null },
|
||||
{ "type": "Feature", "properties": { "Name": "SF to NY" }, "geometry": { "type": "LineString", "coordinates": [ [ -122.4051293283311, 37.786780113640894 ], [ -73.859832357849271, 40.487594916296196 ] ] } }
|
||||
]
|
||||
}
|
||||
@@ -68,7 +68,6 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
|
||||
if not isinstance(col, (list, np.ndarray, Series)):
|
||||
raise ValueError("Must use a list-like to set the geometry"
|
||||
" property")
|
||||
|
||||
self.set_geometry(col, inplace=True)
|
||||
|
||||
geometry = property(fget=_get_geometry, fset=_set_geometry,
|
||||
@@ -177,7 +176,7 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
|
||||
else:
|
||||
f = f
|
||||
|
||||
d = {'geometry': shape(f['geometry'])}
|
||||
d = {'geometry': shape(f['geometry']) if f['geometry'] else None}
|
||||
d.update(f['properties'])
|
||||
rows.append(d)
|
||||
df = GeoDataFrame.from_dict(rows)
|
||||
@@ -326,8 +325,8 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
|
||||
'type': 'Feature',
|
||||
'properties':
|
||||
dict((k, v) for k, v in iteritems(row) if k != 'geometry'),
|
||||
'geometry': mapping(row['geometry'])}
|
||||
|
||||
'geometry': mapping(row['geometry']) if row['geometry']
|
||||
else None}
|
||||
properties = OrderedDict([(col, convert_type(_type)) for col, _type
|
||||
in zip(self.columns, self.dtypes) if col != 'geometry'])
|
||||
# Need to check geom_types before we write to file...
|
||||
@@ -335,7 +334,7 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
|
||||
# Point, LineString, or Polygon
|
||||
geom_types = self['geometry'].geom_type.unique()
|
||||
from os.path import commonprefix # To find longest common prefix
|
||||
geom_type = commonprefix([g[::-1] for g in geom_types])[::-1] # Reverse
|
||||
geom_type = commonprefix([g[::-1] for g in geom_types if g])[::-1]
|
||||
if geom_type == '': # No common suffix = mixed geometry types
|
||||
raise ValueError("Geometry column cannot contains mutiple "
|
||||
"geometry types when writing to file.")
|
||||
|
||||
@@ -30,6 +30,8 @@ class TestDataFrame(unittest.TestCase):
|
||||
self.df2 = GeoDataFrame([
|
||||
{'geometry': Point(x, y), 'value1': x + y, 'value2': x * y}
|
||||
for x, y in zip(range(N), range(N))], crs=self.crs)
|
||||
self.df3 = read_file('examples/null_geom.geojson')
|
||||
self.line_paths = self.df3['Name']
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tempdir)
|
||||
@@ -290,12 +292,21 @@ class TestDataFrame(unittest.TestCase):
|
||||
""" Test to_file and from_file """
|
||||
tempfilename = os.path.join(self.tempdir, 'boros.shp')
|
||||
self.df.to_file(tempfilename)
|
||||
# Read layer back in?
|
||||
# Read layer back in
|
||||
df = GeoDataFrame.from_file(tempfilename)
|
||||
self.assertTrue('geometry' in df)
|
||||
self.assertTrue(len(df) == 5)
|
||||
self.assertTrue(np.alltrue(df['BoroName'].values == self.boros))
|
||||
|
||||
# Write layer with null geometry out to file
|
||||
tempfilename = os.path.join(self.tempdir, 'null_geom.shp')
|
||||
self.df3.to_file(tempfilename)
|
||||
# Read layer back in
|
||||
df3 = GeoDataFrame.from_file(tempfilename)
|
||||
self.assertTrue('geometry' in df3)
|
||||
self.assertTrue(len(df3) == 2)
|
||||
self.assertTrue(np.alltrue(df3['Name'].values == self.line_paths))
|
||||
|
||||
def test_to_file_types(self):
|
||||
""" Test various integer type columns (GH#93) """
|
||||
tempfilename = os.path.join(self.tempdir, 'int.shp')
|
||||
|
||||
Reference in New Issue
Block a user