Skip to content

Commit

Permalink
Geopandas conversion (#186)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr authored Jun 6, 2018
1 parent 2d9a666 commit a7c7977
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 21 deletions.
40 changes: 20 additions & 20 deletions geoviews/data/geopandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import numpy as np
from geopandas import GeoDataFrame

from holoviews.core.data import Interface, MultiInterface
from holoviews.core.data import Interface, MultiInterface, PandasInterface
from holoviews.core.data.interface import DataError
from holoviews.core.util import max_range
from holoviews.element import Path
from holoviews.element import Path, Points

from ..util import geom_to_array

Expand All @@ -33,6 +33,10 @@ def init(cls, eltype, data, kdims, vdims):
else:
kdims = eltype.kdims

if len(set([gt[5:] if 'Multi' in gt else gt for gt in data.geom_type])) != 1:
raise ValueError('The GeopandasInterface can only read dataframes which '
'share a common geometry type')

if vdims is None:
vdims = eltype.vdims
return data, {'kdims': kdims, 'vdims': vdims}, {}
Expand Down Expand Up @@ -91,39 +95,29 @@ def sample(cls, columns, samples=[]):

@classmethod
def shape(cls, dataset):
rows, cols = 0, 0
rows, cols = 0, len(dataset.dimensions())
if len(dataset.data) == 0: return rows, cols
arr = geom_to_array(dataset.data.geometry.iloc[0])
ds = dataset.clone(arr, datatype=cls.subtypes, vdims=[])
for d in dataset.data.geometry:
ds.data = geom_to_array(d)
r, cols = ds.interface.shape(ds)
rows += r
return rows+len(dataset.data)-1, cols
geom_type = dataset.data.geom_type.iloc[0]
offset = 0 if geom_type == 'Point' else len(dataset.data)-1
return rows+offset, cols

@classmethod
def length(cls, dataset):
length = 0
if len(dataset.data) == 0: return 0
arr = geom_to_array(dataset.data.geometry.iloc[0])
ds = dataset.clone(arr, datatype=cls.subtypes, vdims=[])
for d in dataset.data.geometry:
ds.data = geom_to_array(d)
length += ds.interface.length(ds)
return length+len(dataset.data)-1
return cls.shape(dataset)[0]

@classmethod
def nonzero(cls, dataset):
return bool(cls.length(dataset))

@classmethod
def redim(cls, dataset, dimensions):
new_data = []
arr = geom_to_array(dataset.data.geometry.iloc[0])
ds = dataset.clone(arr, datatype=cls.subtypes, vdims=[])
for d in dataset.data.geometry:
ds.data = geom_to_array(d)
new_data.append(ds.interface.redim(ds, dimensions))
return new_data
return PandasInterface.redim(dataset, dimensions)

@classmethod
def values(cls, dataset, dimension, expanded, flat):
Expand All @@ -132,6 +126,10 @@ def values(cls, dataset, dimension, expanded, flat):
data = dataset.data
if idx not in [0, 1] and not expanded:
return data[dimension.name].values
elif not len(data):
return np.array([])

geom_type = dataset.data.geom_type.iloc[0]
values = []
columns = list(data.columns)
arr = geom_to_array(data.geometry.iloc[0])
Expand All @@ -144,7 +142,8 @@ def values(cls, dataset, dimension, expanded, flat):
else:
arr = np.full(len(arr), data.iloc[i, columns.index(dimension.name)])
values.append(arr)
values.append([np.NaN])
if geom_type != 'Point':
values.append([np.NaN])
return np.concatenate(values[:-1]) if values else np.array([])

@classmethod
Expand Down Expand Up @@ -182,3 +181,4 @@ def split(cls, dataset, start, end, datatype, **kwargs):

Interface.register(GeoPandasInterface)
Path.datatype += ['geodataframe']
Points.datatype += ['geodataframe']
14 changes: 13 additions & 1 deletion geoviews/element/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,19 @@ def __call__(self, *args, **kwargs):
group_type = args[0]
if 'crs' not in kwargs and issubclass(group_type, _Element):
kwargs['crs'] = self._element.crs
return super(GeoConversion, self).__call__(*args, **kwargs)
is_gpd = self._element.interface.datatype == 'geopandas'
if is_gpd:
kdims = args[1] if len(args) > 1 else kwargs.get('kdims', None)
if len(args) > 1:
args = (Dataset, [])+args[2:]
else:
args = (Dataset,)
kwargs['kdims'] = []
converted = super(GeoConversion, self).__call__(*args, **kwargs)
if is_gpd:
if kdims is None: kdims = group_type.kdims
converted = converted.map(lambda x: x.clone(kdims=kdims, new_type=group_type), Dataset)
return converted

def linecontours(self, kdims=None, vdims=None, mdims=None, **kwargs):
return self(LineContours, kdims, vdims, mdims, **kwargs)
Expand Down
2 changes: 2 additions & 0 deletions geoviews/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ def geom_to_arr(geom):


def geom_to_array(geom):
if geom.geom_type == 'Point':
return np.array([[geom.x, geom.y]])
if hasattr(geom, 'exterior'):
xs = np.array(geom.exterior.coords.xy[0])
ys = np.array(geom.exterior.coords.xy[1])
Expand Down

0 comments on commit a7c7977

Please sign in to comment.