Search code examples
pythonpandasgeopandashvplot

Geopandas has no attribute hvplot


I am running this code to generate a choropleth map of landprices in Germany. I have installed the pyviz, panel and geoviews packages. Even yesterday this was generating the plots with the hovering annotations. But today the code is generating an error:

AttributeError                            Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_7148\2718829362.py in <module>
      3 years = pn.widgets.IntSlider(name="Jahre",value=2005,start=1995,end=2021,step=1)
      4 #interact = pn.bind(map_landvalue,zeit=years,pval=value_type)
----> 5 de_map_plot = pn.Column(pn.Column(value_type,years),
      6                     pn.bind(map_landvalue,zeit=years,pval=value_type))
      7 de_map_plot.show()

~\anaconda3\lib\site-packages\panel\layout\base.py in __init__(self, *objects, **params)
    628                                  "as positional arguments or as a keyword, "
    629                                  "not both." % type(self).__name__)
--> 630             params['objects'] = [panel(pane) for pane in objects]
    631         elif 'objects' in params:
    632             params['objects'] = [panel(pane) for pane in params['objects']]

~\anaconda3\lib\site-packages\panel\layout\base.py in <listcomp>(.0)
    628                                  "as positional arguments or as a keyword, "
    629                                  "not both." % type(self).__name__)
--> 630             params['objects'] = [panel(pane) for pane in objects]
    631         elif 'objects' in params:
    632             params['objects'] = [panel(pane) for pane in params['objects']]

~\anaconda3\lib\site-packages\panel\pane\base.py in panel(obj, **kwargs)
     78     if kwargs.get('name', False) is None:
     79         kwargs.pop('name')
---> 80     pane = PaneBase.get_pane_type(obj, **kwargs)(obj, **kwargs)
     81     if len(pane.layout) == 1 and pane._unpack:
     82         return pane.layout[0]

~\anaconda3\lib\site-packages\panel\param.py in __init__(self, object, **params)
    743         if object is not None:
    744             self._validate_object()
--> 745             self._replace_pane(not self.lazy)
    746 
    747     @param.depends('object', watch=True)

~\anaconda3\lib\site-packages\panel\param.py in _replace_pane(self, force, *args)
    792                     new_object = Spacer()
    793                 else:
--> 794                     new_object = self.eval(self.object)
    795                 if inspect.isawaitable(new_object):
    796                     param.parameterized.async_executor(partial(self._eval_async, new_object))

~\anaconda3\lib\site-packages\panel\param.py in eval(self, function)
    775                 args = (getattr(dep.owner, dep.name) for dep in arg_deps)
    776                 kwargs = {n: getattr(dep.owner, dep.name) for n, dep in kw_deps.items()}
--> 777         return function(*args, **kwargs)
    778 
    779     async def _eval_async(self, awaitable):

~\anaconda3\lib\site-packages\param\parameterized.py in _depends(*args, **kw)
    385     @wraps(func)
    386     def _depends(*args, **kw):
--> 387         return func(*args, **kw)
    388 
    389     deps = list(dependencies)+list(kw.values())

~\anaconda3\lib\site-packages\panel\depends.py in wrapped(*wargs, **wkwargs)
    207         def wrapped(*wargs, **wkwargs):
    208             combined_args, combined_kwargs = combine_arguments(wargs, wkwargs)
--> 209             return function(*combined_args, **combined_kwargs)
    210     wrapped.__bound_function__ = function
    211     return wrapped

~\AppData\Local\Temp\ipykernel_7148\3612203928.py in map_landvalue(zeit, pval)
      7     test=df_kreise[df_kreise['Zeit']==zeit][['Kreise_Code',pval]]
      8     test=pd.merge(kreise_map,test,on='Kreise_Code',how='outer')
----> 9     fig=test.dropna().hvplot(frame_height=550,frame_width=450,
     10                      hover_cols=['Kreise','Kreise_Code','pval_baureifsLand','pval_insgesamt'],
     11                      legend=False,c=pval,title=title_str,cmap='OrRd')

~\anaconda3\lib\site-packages\pandas\core\generic.py in __getattr__(self, name)
   5573         ):
   5574             return self[name]
-> 5575         return object.__getattribute__(self, name)
   5576 
   5577     def __setattr__(self, name: str, value) -> None:

AttributeError: 'GeoDataFrame' object has no attribute 'hvplot'

Code:

import pandas as pd
import geopandas as gpd
import panel as pn

df_kreise=pd.read_csv('LandpriceFF_df.csv')
kreise_map=gpd.read_file('vg2500_geo84//vg2500_krs.dbf') #not in df_kreise [15001, 3152, 3156]
kreise_map['RS']=kreise_map['RS'].astype(int)
kreise_map=kreise_map.rename(columns={'RS':'Kreise_Code','GEN':'Kreise'})
de_map=gpd.read_file('vg2500_geo84//vg2500_sta.shp')

def map_landvalue(zeit,
                  pval):
    title_str=' Germany '+pval+' Year '+str(zeit)
    if pval == 'Baureifsland Purchase Value': pval='pval_baureifsLand'
    elif pval=='Insgesamt Purchase Value': pval='pval_insgesamt'
    test=df_kreise[df_kreise['Zeit']==zeit][['Kreise_Code',pval]]
    test=pd.merge(kreise_map,test,on='Kreise_Code',how='outer')
    fig=test.dropna().hvplot(frame_height=550,frame_width=450,
                     hover_cols=['Kreise','Kreise_Code','pval_baureifsLand','pval_insgesamt'],
                     legend=False,c=pval,title=title_str,cmap='OrRd')
    return fig

pn.extension()
value_type=pn.widgets.Select(options=['Baureifsland Purchase Value','Insgesamt Purchase Value'])
years = pn.widgets.IntSlider(name="Jahre",value=2005,start=1995,end=2021,step=1)
de_map_plot = pn.Column(pn.Column(value_type,years),
                                pn.bind(map_landvalue,zeit=years,pval=value_type))
de_map_plot.show()

The datasets I am using are here: https://raw.githubusercontent.com/VolkaneicFox/IWH-Research/main/LandpriceFF_df.csv

https://raw.githubusercontent.com/VolkaneicFox/IWH-Research/main/vg2500_krs.shp


Solution

  • In order to use the holoviews pandas extension with df.hviews methods, you must import hvplot.pandasbefore the dataframe is created, even if you are never going to use the hvplot.pandas module directly.

    hvplot.pandas is a critical import as it loads a holoviews pandas extension and registers holoviews with the pandas library so that dataframes created using pandas will have access to the DataFrame.hviews attribute. Without this import, your regular pandas dataframes will not have the extension loaded and attempting to use the extension will simply raise an AttributeError.

    Note that geopandas.GeoDataFrame is a subclass of pandas.DataFrame and the above applies directly to geopandas as well. As with pandas, when reading a GeoDataFrame in from disk, the extension must be loaded before the read is called (before the geopandas object is created - but not necessarily before the file was written).

    See the hvplot extension user guide for more info.