holoviz / holoviews

With Holoviews, your data visualizes itself.
https://holoviews.org
BSD 3-Clause "New" or "Revised" License
2.7k stars 404 forks source link

Nondescriptive error message #4511

Closed brendankristiansen closed 4 years ago

brendankristiansen commented 4 years ago

ALL software version info

Description of expected behavior and the observed behavior

I am trying to map weed presence as a heat map using a quadmesh similar to the Xarray quadmesh example on the geoviews website. When loading my data into a geoviews dataset and calling the to(gv.QuadMesh) function, I receive the error holoviews.core.data.interface.DataError: None of the available storage backends were able to support the supplied data format.

I have also tried loading my data into an Xarray dataset instead of using Pandas, but it produces the same error.

The error message being given does not give any insight as to what the problem is, and according to what I've read in the docs, I am using the library correctly.

Complete, minimal, self-contained example code that reproduces the issue

lats = [45, 46, 47]
lons = [-111, -112, -113]
weed_broadleaf = [300, 500, 700]

pd_dict = {
    'Latitude': lats,
    'Longitude': lons,
    'Broadleaf': weed_broadleaf
}

df = pd.DataFrame(pd_dict, columns=pd_dict.keys())
my_ds = gv.Dataset(df, kdims=['Latitude', 'Longitude'], vdims=['Broadleaf'])
my_qmesh = my_ds.to(gv.QuadMesh)

Stack traceback and/or browser JavaScript console output

Traceback (most recent call last):
  File "~/repos/ag-image-import/heatmap_demo.py", line 87, in <module>
    my_qmesh = my_ds.to(gv.QuadMesh)
  File "~/anaconda3/envs/pygroundskeeper/lib/python3.7/site-packages/geoviews/element/__init__.py", line 39, in __call__
    converted = super(GeoConversion, self).__call__(*args, **kwargs)
  File "~/anaconda3/envs/pygroundskeeper/lib/python3.7/site-packages/holoviews/core/data/__init__.py", line 178, in __call__
    element = new_type(selected, **params)
  File "~/anaconda3/envs/pygroundskeeper/lib/python3.7/site-packages/geoviews/element/geo.py", line 110, in __init__
    super(_Element, self).__init__(data, kdims=kdims, vdims=vdims, **kwargs)
  File "~/anaconda3/envs/pygroundskeeper/lib/python3.7/site-packages/holoviews/element/raster.py", line 784, in __init__
    super(QuadMesh, self).__init__(data, kdims, vdims, **params)
  File "~/anaconda3/envs/pygroundskeeper/lib/python3.7/site-packages/holoviews/core/data/__init__.py", line 351, in __init__
    datatype=kwargs.get('datatype'))
  File "~/anaconda3/envs/pygroundskeeper/lib/python3.7/site-packages/holoviews/core/data/interface.py", line 292, in initialize
    raise DataError(error)
holoviews.core.data.interface.DataError: None of the available storage backends were able to support the supplied data format.
jbednar commented 4 years ago

That's one of the most confusing error messages we have, and it would be great to figure out how to make it more informative. Unfortunately, I don't know how to do that, because what it's saying is that none of our code can figure out what to do with what you supplied, which isn't an error with any particular bit of code but just that across all the code we have available, there's no code that is equipped to do what you're asking. We could put in something to catch this particular case, but to avoid this vague message in general we'd have to have a model for all the data that someone could supply and give appropriate advice for each such case, which as you might imagine would be quite a difficult task!

In any case, here you are calling an element that is set up to plot two-dimensional gridded data (an Xarray quadmesh), but you are passing columnar data. The hv.QuadMesh element plots already-gridded data, which is stored in a two-dimensional format that's like an image (with values at each lat,lon location on a grid), while here you have a table with individual observations at arbitrary lat,lon locations not on a grid. Going from a table of scattered observations to a grid requires some explicit operation like calculating a two-dimensional histogram, binning the arbitrary lat,lon locations into pre-established grid bins, which .to won't automatically perform for you. You'll need to aggregate the data yourself into such a format, which you can do by calling hv.HeatMap(df,...).aggregate() or hv.operations.datashader.rasterize(hv.Scatter(df,...), though those return hv.HeatMap or hv.Image objects rather than hv.QuadMesh; I don't know of anything we offer for aggregating into a QuadMesh.

philippjfr commented 4 years ago

Recent versions will report this:

DataError: QuadMesh type expects gridded data, PandasInterface is columnar.To display columnar data as gridded use the HeatMap element or aggregate the data.

jbednar commented 4 years ago

That's a much better message, though I'm still not sure how one aggregates into a QuadMesh.

philippjfr commented 4 years ago

Datashader or np.histogram2d both work.

github-actions[bot] commented 2 weeks ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.