plotly.py
plotly.py copied to clipboard
Add continuous color scale to strip, box, and violin plots
Currently, strip/box/violin plots only work with categorical/discrete colormaps. This is sufficient for the violins and boxes but for the points that can be included in all three plots, it would be useful to color by a continuous feature and to add a colorbar to the plot. I looked around a bit and it seems like the go.Box constructor needs to have the coloraxis attrbute added to it (and I suspect something would need to be added to avoid coloring the boxes/violins in the same colors as the points, since they are colored the same for categorical variables).
The example below illustrates the issue by trying to color by the sepal_width variable:
import plotly.express as px
iris = px.data.iris()
px.strip(iris, 'species', 'sepal_length', 'sepal_width', stripmode='overlay')
The resulting plot is not meaningful since it colors a continuous variable with a discrete colormap.
So far, I have not found a prettier workaround that this (which is imperfect since it uses the legend instead of a colorbar):
import matplotlib as mpl
sw = iris['sepal_width'].sort_values()
sw_01 = (sw - sw.min()) / (sw.max() - sw.min())
sw_colors = {n: mpl.colors.rgb2hex(c) for n, c in zip(sw, mpl.cm.viridis(sw_01))}
px.strip(iris, 'species', 'sepal_length', 'sepal_width',
stripmode='overlay', category_orders={'sepal_width': sw.to_list()[::-1]},
color_discrete_map=sw_colors)
Hi Joel!
What you're trying to do makes sense in principle, although unfortunately the changes required to implement it all sit at the Javascript level, in plotly.js. strip
is built on top of box
at the moment, so basically we would need to add the ability for the points in box
/violin
traces to be coloured differently from the boxes/violins themselves. If that were done, then we would get the coloraxis
attribute in the graph_objects
automatically (via code-generation) and we could then figure out how to bolt this onto PX.
Another approach would be to add jitter
options to scatter
traces, and we could then build something like strip
on top of scatter
instead of on top of box
. Either way that would require changes in the JS layer again.
PS: your workaround is pretty good actually! If you bin the continuous variable in Python and then color by that you can get pretty close!
Thanks for the reply @nicolaskruchten ! I suspected that this would have to be added in the js layer, but I wasn't sure how to provide example code in js so I decided to open an issue here to start. I think this would be great functionality to add to plotly, should I open a separate issue in plotly.js and reference this one?
To me, the first solution you suggested above would be preferable since it is then possible to also color the points when used together with violin or box.
Any follow-ups about this issue? It seems like this continuous color scale issue for box plot is not resolved.
Correct, we have not implemented this feature and no one is working on it at the moment.
+1 on adding this functionality.
Curious if anyone has new/different work around to accomplish dots with a continuous color scale.
+1
Yep this would be extremely useful!
- 3!
This feature would be helpful; I'm trying to replicate a summary plot for SHAP values, and I have not been able to do it.
This feature would be helpful; I'm trying to replicate a summary plot for SHAP values, and I have not been able to do it.
Same! It's a shame.
Hello! The same is for me. I'm trying to create a new feature importance visualization and I will need this. Hoper there will be a fix soon. Thanks
+1
This feature would be helpful; I'm trying to replicate a summary plot for SHAP values, and I have not been able to do it.
Same! It's a shame.
What I did was generate an Explanation object and then use the shap library's plots functionalities. Hope this helps!
Has another workaround been found? I need the points to be colored differently than the violin part. Is there any way to iterate through fig.data to modify values one by one? Either with the marker size or the marker color?
Check out this post to complement this workaround.
+1