Bokeh Geoviews使用Lat / Long还是UTM?

时间:2017-06-11 03:45:25

标签: python bokeh holoviews datashader geoviews

我正在尝试使用Geoviews和Datashader绘制带有Bokeh的Zillow数据集,但我有最大的时间让它工作。我能够在笛卡尔平面上绘制数据,但是当我尝试用地图覆盖数据时,我遇到了错误。

我使用了数据分析器github上的census-hv示例改编的代码。我相信我的问题是它正在寻找UTM而不是Lat / Long的坐标。因为当我的坐标乘以几千时,代码就可以工作。然后将这些点放在白色空间中的地图上方。如果我试图绘制正确的纬度/经度坐标,我会得到以下错误。

有人可以指点我使用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   []'

1 个答案:

答案 0 :(得分:3)

我认为这里的问题是双重的,首先,因为坐标是纬度和经度,并且您指定xsampling / ysampling值为50,数据阴影图像最终会形成微小或零形状,从而导致此错误。我的建议是首先将坐标转换为Google Mercator。在将来this PR中,您可以通过调用此代码来简单地执行此操作:

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

要手动执行此操作,您现在可以直接使用折扣投影:

coords = ccrs.GOOGLE_MERCATOR.transform_points(ccrs.PlateCarree(), lons, lats)
projected = gv.Points(coords, crs=ccrs.GOOGLE_MERCATOR)
...