from pyprojroot import here
import mpl_fontkit as fk
from brand_yml import Brand
Things that didn’t work
This section is a non-exhaustive list problems I wasn’t able to solve with plotnine
.
Note that this tutorial was made with plotnine
version 0.15.0
. I fully expect that this appendix will likely very quickly become irrelevant with the many anticipated improvements that are coming to plotnine
in the near future.
Horizontal legend with horizontal legend text
Initially I wanted a horizontal legend for the colors. But in order to remove the whitespace between keys, I discovered that the text needs to be smaller than the legend keys, otherwise they “push” the legend keys apart in uneven manner. I attempted to (unsuccesfully) address this by making the legend text small, eliminating as much text as possible (e.g. removing the “%” characters for -0.50
and 0.50
), and lastly increasing the legend key size.
But it still didn’t really work out the way I hoped, so I stuck with a vertical legend instead.
Composing in plotnine is not like R’s patchwork
I wanted to add a line plot of employment numbers to the heatmap. Given the similar syntax in plotnine’s compose to R’s patchwork, I thought the behaviour would be similar.
One discrepancy is that there is no way to specify the relative size of component plots. But this might be addressed very soon #980
It is possible to (rather labourously) pad plots by using plot_spacer
s, which I attemp unsuccessfully below:
= "Total employed, all industries"
INDUSTRY = labour_processed_cutted.filter(pl.col("Industry") == INDUSTRY)
plot_data_subsetted
= (
plot_highlight_industry
plot+ geom_point(data=plot_data_subsetted, color="black", fill="black")
+ labs(title=INDUSTRY, subtitle="")
)
plot_highlight_industry
= (
line_plot
ggplot(filter(
labour_processed_cutted."YEAR") >= FILTER_YEAR[0],
pl.col("YEAR") <= FILTER_YEAR[1],
pl.col("Industry").is_in([INDUSTRY]),
pl.col(
),="DATE_YMD", y="VALUE"),
aes(x
)+ geom_line(color="black")
+ theme_tufte()
+ theme(
="none",
legend_position=element_text(size=10, ha="left"),
plot_title=3,
axis_ticks_length=element_line(),
axis_ticks_major_y=element_text(size=8, margin={"r": 2, "l": 2, "units": "pt"}),
axis_text_y=element_rect(fill=COLOR_BACKGROUND, color=COLOR_BACKGROUND),
plot_background
)+ scale_y_continuous(
=mb.breaks_extended(3),
breaks=lambda x: ["{:.0f}K".format(xi / 1000) for xi in x],
labels
)+ labs(title="Employment Rate")
)
from plotnine.composition import Stack, plot_spacer
= Stack(
p1
[+ scale_x_datetime(expand=(0, 0)),
line_plot
plot_spacer(),
plot_spacer(),
plot_spacer(),
]
)
= (
p2
plot_highlight_industry+ theme(plot_title=element_blank(), plot_subtitle=element_blank())
+ scale_x_datetime(expand=(0, 0))
)
& scale_x_datetime(expand=(0, 0)) & theme_bw() & theme(
Stack([p1, p2]) =element_rect(fill=COLOR_BACKGROUND, color=COLOR_BACKGROUND)
plot_background )
/home/runner/work/labourcan/labourcan/.venv/lib/python3.13/site-packages/plotnine/scales/scales.py:48: PlotnineWarning: Scale for 'x' is already present.
Adding another scale for 'x',
which will replace the existing scale.
The x axes don’t automatically line up
This can be fixed by ensuring expand
and the limits
is the same:
& scale_x_datetime(
Stack([plot_highlight_industry, line_plot]) =(0, 0)
expand& theme_bw() & theme(
) =element_rect(fill=COLOR_BACKGROUND, color=COLOR_BACKGROUND)
plot_background )
But if we add plot_spacer()
s then it won’t line up because it seems that the space that the legend occupies is now ignored:
& scale_x_datetime(
Stack([plot_highlight_industry, p1]) =(0, 0)
expand& theme_bw() & theme(
) =element_rect(fill=COLOR_BACKGROUND, color=COLOR_BACKGROUND)
plot_background )
/home/runner/work/labourcan/labourcan/.venv/lib/python3.13/site-packages/plotnine/scales/scales.py:48: PlotnineWarning: Scale for 'x' is already present.
Adding another scale for 'x',
which will replace the existing scale.
Possibly there are some complexities that I don’t fully understand #959, but at this point I decided to throw in the towel.