proplot-dev / proplot

🎨 A succinct matplotlib wrapper for making beautiful, publication-quality graphics
https://proplot.readthedocs.io
MIT License
1.07k stars 96 forks source link

Set markercolor for scatter plots with a substring from another columns using .map() and colordict #448

Open PaleoLipidRR opened 5 months ago

PaleoLipidRR commented 5 months ago

Description

I have my pandas DataFrame with 3 columns: 2 are numerical and 1 is categorical (string); below is a subset of the data.

Site2 MOB insituOxy '1244' 0.792353 14.757724 '1244' 0.724254 14.757724 '1244' 0.753294 14.757724 'BAR94-24' 0.106508 77.748306 'BAR94-24' 0.153819 77.748306

I would like to color a scatter plot using the following syntax:

fig, ax = plot.subplots() ax.scatter(plot_data.insituOxy,plot_data.MOB, marker='o', c=plot_data.Site2.map(color_site_dict).fillna('gray6'), )

Doing so, I got the error below:

TypeError Traceback (most recent call last) Cell In[252], line 9 4 color_site_dict = { 5 '1244':'blue6', 6 '850':'red6', 7 } 8 fig, ax = plot.subplots() ----> 9 ax.scatter(plot_data.insituOxy,plot_data.MOB, 10 marker='o', 11 c=plot_data.Site2.map(color_site_dict).fillna('gray6'), 12 )

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\proplot\internals\process.py:284, in _preprocess_args..decorator.._redirect_or_standardize(self, *args, *kwargs) 281 ureg.setup_matplotlib(True) 283 # Call main function --> 284 return func(self, args, **kwargs)

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\proplot\axes\plot.py:3259, in PlotAxes.scatter(self, args, kwargs) 3255 """ 3256 %(plot.scatter)s 3257 """ 3258 kwargs = _parse_vert(default_vert=True, kwargs) -> 3259 return self._apply_scatter(args, **kwargs)

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\proplot\axes\plot.py:3220, in PlotAxes._apply_scatter(self, xs, ys, ss, cc, vert, kwargs) 3215 if ( 3216 any(.ndim == 2 and .shape[1] in (3, 4) for _ in (xs, ys)) 3217 and test.ndim == 2 and test.shape[1] in (3, 4) 3218 ): 3219 infer_rgb = False -> 3220 cc, kw = self._parse_color( 3221 xs, ys, cc, inbounds=inbounds, apply_cycle=False, infer_rgb=infer_rgb, kw 3222 ) 3223 guide_kw = _pop_params(kw, self._update_guide) 3224 objs = []

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\proplot\axes\plot.py:2082, in PlotAxes._parse_color(self, x, y, c, apply_cycle, infer_rgb, kwargs) 2080 c = list(map(pcolors.to_hex, c)) # avoid iterating over columns 2081 else: -> 2082 kwargs = self._parse_cmap( 2083 x, y, c, plot_lines=True, default_discrete=False, kwargs 2084 ) 2085 methods = (self._parse_cycle,) 2086 pop = _pop_params(kwargs, *methods, ignore_internal=True)

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\proplot\internals\warnings.py:96, in _rename_kwargs..decorator.._deprecate_kwargs(*args, *kwargs) 91 key_new = key_new.format(value) 92 _warn_proplot( 93 f'Keyword {key_old!r} was deprecated in version {version} and will ' 94 f'be removed in a future release. Please use {key_new!r} instead.' 95 ) ---> 96 return func_orig(args, **kwargs)

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\proplot\axes\plot.py:2645, in PlotAxes._parse_cmap(self, cmap, cmap_kw, c, color, colors, default_cmap, norm, norm_kw, extend, vmin, vmax, discrete, default_discrete, skip_autolev, plot_lines, plot_contours, min_levels, *args, *kwargs) 2643 isdiverging = False 2644 if not discrete and not skip_autolev: -> 2645 vmin, vmax, kwargs = self._parse_vlim( 2646 args, vmin=vmin, vmax=vmax, **kwargs 2647 ) 2648 if autodiverging and vmin is not None and vmax is not None: 2649 if abs(np.sign(vmax) - np.sign(vmin)) == 2:

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\proplot\axes\plot.py:2158, in PlotAxes._parse_vlim(self, vmin, vmax, robust, inbounds, negative, positive, symmetric, to_centers, *args, **kwargs) 2156 if inbounds and x is not None and y is not None: # ignore if None coords 2157 z = self._inbounds_vlim(x, y, z, to_centers=to_centers) -> 2158 imin, imax = process._safe_range(z, pmin, pmax) 2159 if automin and imin is not None: 2160 vmins.append(imin)

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\proplot\internals\process.py:490, in _safe_range(data, lo, hi) 484 """ 485 Safely return the minimum and maximum (default) or percentile range accounting 486 for masked values. Use min and max functions when possible for speed. Return 487 None if we fail to get a valid range. 488 """ 489 _load_objects() --> 490 data, units = _to_masked_array(data) 491 data = data.compressed() # remove all invalid values 492 min = max = None

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\proplot\internals\process.py:143, in _to_masked_array(data, copy) 141 if ndarray is not Quantity and isinstance(data, Quantity): 142 data, units = data.magnitude, data.units --> 143 data = ma.masked_invalid(data, copy=copy) 144 if np.issubdtype(data.dtype, int): 145 data = data.astype(float)

File c:\Users\ratta\miniconda3\envs\python310_pymc_env\lib\site-packages\numpy\ma\core.py:2360, in masked_invalid(a, copy) 2333 """ 2334 Mask an array where invalid values occur (NaNs or infs). 2335 (...) 2357 2358 """ 2359 a = np.array(a, copy=False, subok=True) -> 2360 res = masked_where(~(np.isfinite(a)), a, copy=copy) 2361 # masked_invalid previously never returned nomask as a mask and doing so 2362 # threw off matplotlib (gh-22842). So use shrink=False: 2363 if res._mask is nomask:

TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

Equivalent steps in matplotlib

However, the same syntax can be implemented by matplotlib (pyplot).

# your code here, if applicable
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.scatter(plot_data.insituOxy,plot_data.MOB,
            marker='o',
            c=plot_data.Site2.map(color_site_dict).fillna('gray6'),
            )

Here is the expected output: image

Proplot version

Paste the results of import matplotlib; print(matplotlib.__version__); import proplot; print(proplot.version) here.

matplotlib version: 3.4.3 proplot version: 0.9.7

Mickychen00 commented 5 months ago

Have a try with python 3.9?