has2k1 / plotnine

A Grammar of Graphics for Python
https://plotnine.org
MIT License
4.07k stars 225 forks source link

Non-aes geom_rect ignores alpha #572

Closed TyberiusPrime closed 2 years ago

TyberiusPrime commented 2 years ago
import plotnine, plotnine.data
p = plotnine.ggplot(plotnine.data.mtcars)
p += plotnine.theme_bw()
p += plotnine.geom_point(plotnine.aes('hp','cyl'))
p += plotnine.geom_rect(xmin=0, xmax=100, ymin=0, ymax=7, alpha=.1, fill="blue") # fails
p += plotnine.geom_rect(plotnine.aes(xmin='xmin', xmax='xmax', ymin='ymin', ymax='ymax'), data  = pd.DataFrame({'xmin':100, 'xmax':200, 'ymin':0, 'ymax':7}, index=[0]), alpha=.1, fill="blue") # ok
p

image

Note that in the failing case, I'm not setting an aes at all, just straight values, and it does draw the rect - just not with the alpha I specified.

This is using the current release - master shows it as well though.

Thanks for having a look!

has2k1 commented 2 years ago

Your code, this line

p += plotnine.geom_rect(xmin=0, xmax=100, ymin=0, ymax=7, alpha=.1, fill="blue") # fails

is failing in a subtle way. When you manually set aesthetics, each row of the dataframe gets a value. So you are creating as many rectangles as there are rows in mtcars and the alphas build up! To confirm that the alpha is not ignored, try changing to alpha=.01 or smaller. This is not a bug, it happens all the time e.g. if you do geom_point(x=1, alpha=0.1) all the points get those values.

The solution is to use another dataframe with only one rectangle just like the second rectangle, or use annotate.

annotate(geom_rect, xmin=0, xmax=100, ymin=0, ymax=7, alpha=.1, fill="red")
TyberiusPrime commented 2 years ago

Thanks Hassan.

I now remember having fallen into this trap before.