3

I am trying to plot the Zillow dataset with Bokeh using Geoviews and Datashader but I am having the damnedest time getting it to work. I am able to plot the data on a Cartesian plane fine but when I attempt to overlay the data with a map I run into errors.

I have used code adapted from the census-hv example on the datashader github. I believe my problem is that it is looking for the coordinates to be in UTM not Lat/Long. Because the code works when I have my coordinates multiplied by a few thousand. The points are then put above the map in white space. If i attempt to plot the proper lat/long coordinates I get the following errors.

Can someone please point me in the direction of a map that uses Lat/Long

>>>props.head()
longitude   latitude
0 -118.654084  34.144442
1 -118.625364  34.140430
2 -118.394633  33.989359
3 -118.437206  34.148863
4 -118.385816  34.194168

import pandas as pd
import holoviews as hv
import geoviews as gv
import datashader as ds

from bokeh.models import WMTSTileSource
from holoviews.operation.datashader import datashade, dynspread
hv.notebook_ex

tension('bokeh')

%%opts Overlay [width=900 height=525 xaxis=None yaxis=None]

geomap = gv.WMTS(WMTSTileSource(url=\
   'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.jpg'))

points = hv.Points(gv.Dataset(props, kdims=['longitude', 'latitude']))
# color_key = {'w':'aqua', 'b':'lime',  'a':'red', 'h':'fuchsia', 'o':'yellow' }
race = datashade(points, x_sampling=50, y_sampling=50,
                 element_type=gv.Image)
geomap * race

RETURNS ERROR:
WARNING:root:dynamic_operation: Exception raised in callable 

'dynamic_operation' of type 'function'.
Invoked as dynamic_operation(height=400, scale=1.0, width=400, x_range=None, y_range=None)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/IPython/core/formatters.py in __call__(self, obj)
    305                 pass
    306             else:
--> 307                 return printer(obj)
    308             # Finally look for special method names
    309             method = get_real_method(obj, self.print_method)

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/ipython/display_hooks.py in pprint_display(obj)
    255     if not ip.display_formatter.formatters['text/plain'].pprint:
    256         return None
--> 257     return display(obj, raw=True)
    258 
    259 

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/ipython/display_hooks.py in display(obj, raw, **kwargs)
    241     elif isinstance(obj, (HoloMap, DynamicMap)):
    242         with option_state(obj):
--> 243             html = map_display(obj)
    244     else:
    245         return repr(obj) if raw else IPython.display.display(obj, **kwargs)

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/ipython/display_hooks.py in wrapped(element)
    127         try:
    128             html = fn(element,
--> 129                       max_frames=OutputMagic.options['max_frames'])
    130 
    131             # Only want to add to the archive for one display hook...

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/ipython/display_hooks.py in map_display(vmap, max_frames)
    196         return None
    197 
--> 198     return render(vmap)
    199 
    200 

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/ipython/display_hooks.py in render(obj, **kwargs)
     57     if renderer.fig == 'pdf':
     58         renderer = renderer.instance(fig='png')
---> 59     return renderer.html(obj, **kwargs)
     60 
     61 

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/plotting/renderer.py in html(self, obj, fmt, css, comm, **kwargs)
    253         code to initialize a Comm, if the plot supplies one.
    254         """
--> 255         plot, fmt =  self._validate(obj, fmt)
    256         figdata, _ = self(plot, fmt, **kwargs)
    257         if css is None: css = self.css

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/plotting/renderer.py in _validate(self, obj, fmt)
    189         if isinstance(obj, tuple(self.widgets.values())):
    190             return obj, 'html'
--> 191         plot = self.get_plot(obj, renderer=self)
    192 
    193         fig_formats = self.mode_formats['fig'][self.mode]

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/plotting/renderer.py in get_plot(self_or_cls, obj, renderer)
    164         """
    165         # Initialize DynamicMaps with first data item
--> 166         initialize_dynamic(obj)
    167 
    168         if not isinstance(obj, Plot) and not displayable(obj):

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/plotting/util.py in initialize_dynamic(obj)
    173             continue
    174         if not len(dmap):
--> 175             dmap[dmap._initial_key()]
    176 
    177 

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/core/spaces.py in __getitem__(self, key)
    942         # Not a cross product and nothing cached so compute element.
    943         if cache is not None: return cache
--> 944         val = self._execute_callback(*tuple_key)
    945         if data_slice:
    946             val = self._dataslice(val, data_slice)

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/core/spaces.py in _execute_callback(self, *args)
    791 
    792         with dynamicmap_memoization(self.callback, self.streams):
--> 793             retval = self.callback(*args, **kwargs)
    794         return self._style(retval)
    795 

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/core/spaces.py in __call__(self, *args, **kwargs)
    489         # Nothing to do for callbacks that accept no arguments
    490         (inargs, inkwargs) = (args, kwargs)
--> 491         if not args and not kwargs: return self.callable()
    492         inputs = [i for i in self.inputs if isinstance(i, DynamicMap)]
    493         streams = []

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/core/overlay.py in dynamic_mul(*args, **kwargs)
     27             from .spaces import Callable
     28             def dynamic_mul(*args, **kwargs):
---> 29                 element = other[args]
     30                 return self * element
     31             callback = Callable(dynamic_mul, inputs=[self, other])

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/core/spaces.py in __getitem__(self, key)
    942         # Not a cross product and nothing cached so compute element.
    943         if cache is not None: return cache
--> 944         val = self._execute_callback(*tuple_key)
    945         if data_slice:
    946             val = self._dataslice(val, data_slice)

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/core/spaces.py in _execute_callback(self, *args)
    791 
    792         with dynamicmap_memoization(self.callback, self.streams):
--> 793             retval = self.callback(*args, **kwargs)
    794         return self._style(retval)
    795 

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/core/spaces.py in __call__(self, *args, **kwargs)
    519 
    520         try:
--> 521             ret = self.callable(*args, **kwargs)
    522         except:
    523             posstr = ', '.join(['%r' % el for el in inargs]) if inargs else ''

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/util.py in dynamic_operation(*key, **kwargs)
    101                 self.p.kwargs.update(kwargs)
    102                 obj = map_obj[key] if isinstance(map_obj, HoloMap) else map_obj
--> 103                 return self._process(obj, key)
    104         else:
    105             def dynamic_operation(*key, **kwargs):

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/util.py in _process(self, element, key)
     87             kwargs = {k: v for k, v in self.p.kwargs.items()
     88                       if k in self.p.operation.params()}
---> 89             return self.p.operation.process_element(element, key, **kwargs)
     90         else:
     91             return self.p.operation(element, **self.p.kwargs)

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/core/operation.py in process_element(self, element, key, **params)
    133         """
    134         self.p = param.ParamOverrides(self, params)
--> 135         return self._process(element, key)
    136 
    137 

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/operation/datashader.py in _process(self, element, key)
    357 
    358     def _process(self, element, key=None):
--> 359         agg = aggregate._process(self, element, key)
    360         shaded = shade._process(self, agg, key)
    361         return shaded

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/operation/datashader.py in _process(self, element, key)
    226         agg = getattr(cvs, glyph)(data, x, y, self.p.aggregator)
    227         if agg.ndim == 2:
--> 228             return self.p.element_type(agg, **params)
    229         else:
    230             return NdOverlay({c: self.p.element_type(agg.sel(**{column: c}),

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/geoviews/element/geo.py in __init__(self, data, **kwargs)
     81         elif crs:
     82             kwargs['crs'] = crs
---> 83         super(_Element, self).__init__(data, **kwargs)
     84 
     85 

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/element/raster.py in __init__(self, data, bounds, extents, xdensity, ydensity, **params)
    242         if bounds is None:
    243             xvals = self.dimension_values(0, False)
--> 244             l, r, xdensity, _ = util.bound_range(xvals, xdensity)
    245             yvals = self.dimension_values(1, False)
    246             b, t, ydensity, _ = util.bound_range(yvals, ydensity)

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/holoviews/core/util.py in bound_range(vals, density)
   1373     using significant digits reported by sys.float_info.dig.
   1374     """
-> 1375     low, high = vals.min(), vals.max()
   1376     invert = False
   1377     if vals[0] > vals[1]:

/home/mcamp/anaconda3/envs/py3.6/lib/python3.6/site-packages/numpy/core/_methods.py in _amin(a, axis, out, keepdims)
     27 
     28 def _amin(a, axis=None, out=None, keepdims=False):
---> 29     return umr_minimum(a, axis, None, out, keepdims)
     30 
     31 def _sum(a, axis=None, dtype=None, out=None, keepdims=False):

ValueError: zero-size array to reduction operation minimum which has no identity

Out[54]:
b':DynamicMap   []'
Matt Camp
  • 1,448
  • 3
  • 17
  • 38

1 Answers1

3

I think the problem here is two-fold, first of all since the coordinates are latitudes and longitudes and you specify xsampling/ysampling values of 50 the datashaded image ends up with a tiny or zero shape, which causes this error. My suggestion would be to cast the coordinates to Google Mercator first. In future this PR will let you do so very simply by calling this:

import cartopy.crs as ccrs
projected = gv.operation.project(points, projection=ccrs.GOOGLE_MERCATOR)
...

To do this manually for now you can use the cartopy projection directly:

coords = ccrs.GOOGLE_MERCATOR.transform_points(ccrs.PlateCarree(), lons, lats)
projected = gv.Points(coords, crs=ccrs.GOOGLE_MERCATOR)
...
philippjfr
  • 3,997
  • 14
  • 15
  • 2
    You can also use the datashader function `datashader.utils.lnglat_to_meters()` to project the original source data into Web Mercator, which because it's used by most map tile providers is a convenient coordinate system to work with if all you want to do is visualize it (and don't need to access anything by the original lat/lng coordinates anymore). – James A. Bednar Jun 12 '17 at 19:10