has2k1 / plotnine

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

Is it possible to control the output figure size including legends and axes? #481

Closed haggaie closed 3 years ago

haggaie commented 3 years ago

When I set figure_size through theme or the options it seems like this setting only controls the figure itself, but does not take into account legends, axis, titles, etc.

Is there another setting that could set the size of the overall resulting figure?

has2k1 commented 3 years ago

It is not possible. The backend (Matplotlib) cannot guarantee that.

On Tue., Jan. 26, 2021, 3:14 p.m. Haggai Eran, notifications@github.com wrote:

When I set figure_size through theme or the options it seems like this setting only controls the figure itself, but does not take into account legends, axis, titles, etc.

Is there another setting that could set the size of the overall resulting figure?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/has2k1/plotnine/issues/481, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAF6QNPL4YFTQAN33OPQMF3S32W3PANCNFSM4WTLJBYA .

haggaie commented 3 years ago

Too bad. Thanks for the quick answer.

himalayajung commented 3 years ago

@haggaie Maybe you can use base_size. e.g. theme_grey(base_size=20)

haggaie commented 3 years ago

Thanks @himalayajung, though I don't think that would help. What I want to accomplish it to set the size of the pdf plotnine would generate in advance, and have all the components fit that space. That makes it easier to them include the figure in a paper and keeping font and figure sizes uniform. I believe this is similar to the matplotlib tight layout feature, though I haven't used it in a while, so I might be mistaken.

benjaminleroy commented 2 years ago

Hi there, I know this issue is a year old, but @wangmallory and I have been working on an extension to plotnine (cowpatch), and in this package we use an idea suggested in a blog post by Kavi Gupta (@kavigupta) in a backend to create correctly sized plotnine objects / matplotlib figures. 

The problem (love plotnine b.t.w.) is that plotnine's underlying code leverages bbox_inches=“tight” from matplotlib. I do see that @has2k1 is looking into converting to plt.tight_layout() (issue #390).

A solution using our package would be something like the following:

import plotnine as p9
import cowpatch as cow 

# for reproducible example:
import plotnine.data as p9_data
g0 = p9.ggplot(p9_data.mpg) +\
    p9.geom_bar(p9.aes(x="hwy")) +\
    p9.labs(title = 'Plot 0')

out_info = cow.svg_utils._select_correcting_size_svg(g0, height = 4, width = 5, dpi = 96) #height and width in inches (in this example keep dpi = 96 )

# feed out_info[0], out_info[1] into p9.save’s height and width parameter
g0.save(filename = “local_image.pdf”, width = out_info[0], height = out_info[1])

The resulting file local_image.pdf (in whatever format you'd like) should be the desired size (up to some eps). For the above example, here is a screengrab of the size information from adobe acrobat:

Screen Shot 2022-04-10 at 10 10 31 AM

Note that this “solution” is an interative one, and sometimes (especially with large legends) this can still fail since the legend may constraint the minimum size your image can actually take.