dataset i am working on: https://www.kaggle.com/code/gauravsahani/housing-in-london-for-beginners/data
i am using bokeh and have produced the following scatter plot
source=ColumnDataSource(data=dict(df,av=df.average_price,cr=df.no_of_crimes,ar=df.area))
p=figure(sizing_mode='stretch_width',toolbar_location=None,height=500,
x_axis_label='Average Salary',y_axis_label='crime rate')
p.xaxis.formatter = BasicTickFormatter(use_scientific=False)
p.add_layout(Legend(), 'right')
p.scatter(x='av',y='cr',source=source,size=9,alpha=0.4,legend_field='area',fill_color=factor_cmap('area',palette=magma(34),factors=df.area.unique()))
p.xgrid.grid_line_color=None
p.legend.label_text_font_size='12px'
p.legend.padding=4
p.legend.orientation='vertical'
p.legend.spacing=-7
p.add_tools(HoverTool(tooltips=[('Area','@ar')]))
show(p)
I am trying to produce a custom function for reusability which is the following:
source=ColumnDataSource(data=dict(df,av=df.average_price,
cr=df.no_of_crimes,
ar=df.area))
tooltips=[('Area','@ar')]
def scatter(source,x,y,xlabel=None,ylabel=None,size=None,alpha=None,legend_field=None,fill_color=None):
p=figure(sizing_mode='stretch_width',
toolbar_location=None,
height=500,
x_axis_label=xlabel,
y_axis_label=ylabel)
p.xgrid.grid_line_color=None
p.xaxis.formatter = BasicTickFormatter(use_scientific=False)
p.legend.label_text_font_size='12px'
p.legend.padding=4
p.legend.orientation='vertical'
p.legend.spacing=-7
p.scatter(source=source,x=x,y=y,size=size,alpha=alpha,legend_field=legend_field,fill_color=fill_color)
return p
p=scatter(source,x='av',y='cr')
show(p)
however I keep getting an error and I cant seem to figure out why since both my x and y columns are numerical values and already run successfuly when not working with a function. the error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [234], in <cell line: 24>()
20 p.scatter(source=source,x=x,y=y,size=size,alpha=alpha,legend_field=legend_field,fill_color=fill_color)
22 return p
---> 24 p=scatter(source,x='av',y='cr')
26 show(p)
Input In [234], in scatter(source, x, y, xlabel, ylabel, size, alpha, legend_field, fill_color)
17 p.legend.orientation='vertical'
18 p.legend.spacing=-7
---> 20 p.scatter(source=source,x=x,y=y,size=size,alpha=alpha,legend_field=legend_field,fill_color=fill_color)
22 return p
File ~\Anaconda3\lib\site-packages\bokeh\plotting\glyph_api.py:962, in GlyphAPI.scatter(self, *args, **kwargs)
960 return self.circle(*args, **kwargs)
961 else:
--> 962 return self._scatter(*args, marker=marker_type, **kwargs)
File ~\Anaconda3\lib\site-packages\bokeh\plotting\_decorators.py:86, in glyph_method.<locals>.decorator.<locals>.wrapped(self, *args, **kwargs)
84 if self.coordinates is not None:
85 kwargs.setdefault("coordinates", self.coordinates)
---> 86 return create_renderer(glyphclass, self.plot, **kwargs)
File ~\Anaconda3\lib\site-packages\bokeh\plotting\_renderer.py:116, in create_renderer(glyphclass, plot, **kwargs)
113 # handle the mute glyph, we always set one
114 muted_visuals = pop_visuals(glyphclass, kwargs, prefix='muted_', defaults=glyph_visuals, override_defaults={'alpha':0.2})
--> 116 glyph = make_glyph(glyphclass, kwargs, glyph_visuals)
117 nonselection_glyph = make_glyph(glyphclass, kwargs, nonselection_visuals)
118 selection_glyph = make_glyph(glyphclass, kwargs, selection_visuals)
File ~\Anaconda3\lib\site-packages\bokeh\plotting\_renderer.py:145, in make_glyph(glyphclass, kws, extra)
143 kws = kws.copy()
144 kws.update(extra)
--> 145 return glyphclass(**kws)
File ~\Anaconda3\lib\site-packages\bokeh\model\model.py:128, in Model.__init__(self, **kwargs)
121 def __init__(self, **kwargs: Any) -> None:
122
123 # "id" is popped from **kw in __new__, so in an ideal world I don't
124 # think it should be here too. But Python has subtle behavior here, so
125 # it is necessary
126 kwargs.pop("id", None)
--> 128 super().__init__(**kwargs)
129 default_theme.apply_to_model(self)
File ~\Anaconda3\lib\site-packages\bokeh\core\has_props.py:206, in HasProps.__init__(self, **properties)
203 self._unstable_themed_values = {}
205 for name, value in properties.items():
--> 206 setattr(self, name, value)
208 self._initialized = True
File ~\Anaconda3\lib\site-packages\bokeh\core\has_props.py:230, in HasProps.__setattr__(self, name, value)
228 properties = self.properties(_with_props=True)
229 if name in properties:
--> 230 return super().__setattr__(name, value)
232 descriptor = getattr(self.__class__, name, None)
233 if isinstance(descriptor, property): # Python property
File ~\Anaconda3\lib\site-packages\bokeh\core\property\descriptors.py:283, in PropertyDescriptor.__set__(self, obj, value, setter)
280 class_name = obj.__class__.__name__
281 raise RuntimeError(f"{class_name}.{self.name} is a readonly property")
--> 283 value = self.property.prepare_value(obj, self.name, value)
284 old = self._get(obj)
285 self._set(obj, old, value, setter=setter)
File ~\Anaconda3\lib\site-packages\bokeh\core\property\dataspec.py:515, in SizeSpec.prepare_value(self, cls, name, value)
513 except TypeError:
514 pass
--> 515 return super().prepare_value(cls, name, value)
File ~\Anaconda3\lib\site-packages\bokeh\core\property\bases.py:365, in Property.prepare_value(self, owner, name, value, hint)
363 else:
364 obj_repr = owner if isinstance(owner, HasProps) else owner.__name__
--> 365 raise ValueError(f"failed to validate {obj_repr}.{name}: {error}")
367 if isinstance(owner, HasProps):
368 obj = owner
ValueError: failed to validate Scatter(id='40569', ...).size: expected an element of either String, Dict(Enum('expr', 'field', 'value', 'transform'), Either(String, Instance(Transform), Instance(Expression), Float)) or Float, got None
any help would be great
def scatter(source,x,y,xlabel=None,ylabel=None,size=5,alpha=1,legend_field=str(None),fill_color=None):
p=figure(sizing_mode='stretch_width',
toolbar_location=None,
height=500,
x_axis_label=xlabel,
y_axis_label=ylabel)
p.xgrid.grid_line_color=None
p.xaxis.formatter = BasicTickFormatter(use_scientific=False)
p.legend.label_text_font_size='12px'
p.legend.padding=4
p.legend.orientation='vertical'
p.legend.spacing=-7
if legend_field == str(None):
p.scatter(source=source,x=x,y=y,size=size,alpha=alpha,fill_color=fill_color)
else:
p.scatter(source=source,x=x,y=y,size=size,alpha=alpha,legend_field=legend_field,fill_color=fill_color)
return p