Home > other >  pandas scatter plot log colorbar
pandas scatter plot log colorbar

Time:05-22

I am plotting a dataframe in pandas that uses another column for color and I would like to use a log normalized colormap.

enter image description here

Adding the norm argument yields the error above.

example_data.plot.scatter('sample_no', 'data1', c='data2', cmap='viridis',
                          norm=matplotlib.colors.LogNorm())

Full slack trace

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/Users/rwegener/repos/sarp_lessons/snippets/More mapping/flight_track.ipynb Cell 45' in <cell line: 1>()
----> 1 example_data.plot.scatter('sample_no', 'data1', c='data2', cmap='viridis',
      2                           norm=matplotlib.colors.LogNorm())

File ~/.pyenv/versions/miniconda3-4.7.12/envs/sarp/lib/python3.10/site-packages/pandas/plotting/_core.py:1669, in PlotAccessor.scatter(self, x, y, s, c, **kwargs)
   1586 def scatter(self, x, y, s=None, c=None, **kwargs):
   1587     """
   1588     Create a scatter plot with varying marker point size and color.
   1589 
   (...)
   1667         ...                       colormap='viridis')
   1668     """
-> 1669     return self(kind="scatter", x=x, y=y, s=s, c=c, **kwargs)

File ~/.pyenv/versions/miniconda3-4.7.12/envs/sarp/lib/python3.10/site-packages/pandas/plotting/_core.py:917, in PlotAccessor.__call__(self, *args, **kwargs)
    915 if kind in self._dataframe_kinds:
    916     if isinstance(data, ABCDataFrame):
--> 917         return plot_backend.plot(data, x=x, y=y, kind=kind, **kwargs)
    918     else:
    919         raise ValueError(f"plot kind {kind} can only be used for data frames")

File ~/.pyenv/versions/miniconda3-4.7.12/envs/sarp/lib/python3.10/site-packages/pandas/plotting/_matplotlib/__init__.py:71, in plot(data, kind, **kwargs)
     69         kwargs["ax"] = getattr(ax, "left_ax", ax)
     70 plot_obj = PLOT_CLASSES[kind](data, **kwargs)
---> 71 plot_obj.generate()
     72 plot_obj.draw()
     73 return plot_obj.result

File ~/.pyenv/versions/miniconda3-4.7.12/envs/sarp/lib/python3.10/site-packages/pandas/plotting/_matplotlib/core.py:329, in MPLPlot.generate(self)
    327 self._compute_plot_data()
    328 self._setup_subplots()
--> 329 self._make_plot()
    330 self._add_table()
    331 self._make_legend()

File ~/.pyenv/versions/miniconda3-4.7.12/envs/sarp/lib/python3.10/site-packages/pandas/plotting/_matplotlib/core.py:1114, in ScatterPlot._make_plot(self)
   1112 else:
   1113     label = None
-> 1114 scatter = ax.scatter(
   1115     data[x].values,
   1116     data[y].values,
   1117     c=c_values,
   1118     label=label,
   1119     cmap=cmap,
   1120     norm=norm,
   1121     **self.kwds,
   1122 )
   1123 if cb:
   1124     cbar_label = c if c_is_column else ""

TypeError: matplotlib.axes._axes.Axes.scatter() got multiple values for keyword argument 'norm'

CodePudding user response:

You could apply log norm to data1 and data2 and then create the scatter plot. It would produce the intended effect.

CodePudding user response:

It looks like a bug in class ScatterPlot in _matplotlib/core.py

if color_by_categorical:
    from matplotlib import colors

    n_cats = len(self.data[c].cat.categories)
    cmap = colors.ListedColormap([cmap(i) for i in range(cmap.N)])
    bounds = np.linspace(0, n_cats, n_cats   1)
    norm = colors.BoundaryNorm(bounds, cmap.N)
else:
    norm = self.kwds.pop("norm", None)

Sets norm local variable and later uses it in

scatter = ax.scatter(
    data[x].values,
    data[y].values,
    c=c_values,
    label=label,
    cmap=cmap,
    norm=norm,
    **self.kwds,
)

However, the last parameter self.kwds already contains norm named parameter, which you sent, so you end up with two norm, and Python can't handle this.

It seems like there was an attempt to fix it at commit 1cad74e1ee3b5144f6ef774aeed6ae3152d28d6a, but the commit wasn't successful.

  • Related