This demo illustrates the overall plot structure and the effect of various layout-related theme parameters. Understanding how they interact can help fine-tune the appearance and readability of your plots.
plot_marginadds outer space around the entire plot, including titles, captions, legends, and the plotting panel.plot_title: margin,plot_subtitle: margin,plot_caption: margin,axis_title_x: margin,axis_title_y: margincontrol the spacing around the corresponding textual elements. These are passed via themarginargument toelement_text().axis_text_spacing_x,axis_text_spacing_ydefine the spacing between axis ticks and their associated labels.panel_insetadds internal padding between the plotting panel and the axes, shrinking the effective plotting area.plot_insetadds padding inside the plot area (including the plot panel, axes, and axis labels) and other textual elements.legend_box_spacingcontrols the spacing between the legend section and the plot area.
import numpy as np from lets_plot import *
np.random.seed(42) x = list(range(210, 1000, 97)) # Base rate increases with x (e.g., linear growth for lambda) lambdas = [5 + (xi - 210) / 100 for xi in x] y = [np.random.poisson(lam) * 30 + 90 for lam in lambdas] data = {'x': x, 'y': y}
SCALE_FACTOR = 2 PAD = 11
def labeled_rect(xmin, xmax, ymin, ymax, inner_text='', border_text='', pad=PAD, **kwargs): xmin_s = xmin * SCALE_FACTOR + pad xmax_s = xmax * SCALE_FACTOR - pad ymin_s = ymin * SCALE_FACTOR + pad ymax_s = ymax * SCALE_FACTOR - pad is_horizontal = (xmax - xmin > (ymax - ymin) / 2) rect_layer = geom_rect( xmin=xmin_s, xmax=xmax_s, ymin=ymin_s, ymax=ymax_s, size=pad - 3, **kwargs ) # Inner text: centered x_center = (xmin_s + xmax_s) / 2 y_center = (ymin_s + ymax_s) / 2 inner_layer = geom_text( x=x_center, y=y_center, label=inner_text, angle=0 if is_horizontal else 90, color='darkgray' ) # Border text: near top-right (horizontal) or top-left (vertical) if is_horizontal: x_border = xmax_s y_border = ymin_s + pad / 2 - 1 angle = 0 vjust = 0 else: # vertical x_border = xmin_s - pad / 2 - 5 y_border = ymin_s angle = 90 vjust = 1 border_layer = geom_text( x=x_border, y=y_border, label=border_text, angle=angle, hjust=1, vjust=vjust, family='Courier', color='black' ) return rect_layer + inner_layer + border_layer
def annotation_arrow(x, y, xend, yend, label, hjust): x_s = x * SCALE_FACTOR y_s = y * SCALE_FACTOR xend_s = xend * SCALE_FACTOR yend_s = yend * SCALE_FACTOR with_arrow = arrow(length=8, ends='last', type='open', angle=20) label_x = x_s - 16 label_y = y_s + 8 if hjust == 1: label_x = x_s + 24 label_y = y_s - 10 return geom_segment(x=x_s, y=y_s, xend=xend_s, yend=yend_s, arrow=with_arrow) + \ geom_text(x=label_x, y=label_y, label=label, hjust=hjust, family='Courier', color='black')
def x_ticks(data, y_base=608, tick_length=8): ticks = { 'x': data['x'], 'xend': data['x'], 'y': [y_base] * len(data['x']), 'yend': [y_base + tick_length] * len(data['x']), } return geom_segment(aes(x='x', y='y', xend='xend', yend='yend'), data=ticks, color='gray50', size=1) def y_ticks(ymin=208, ymax=574, n_ticks=6, x_base=168, tick_length=8): y_ticks = np.linspace(ymin, ymax, n_ticks) ticks = { 'y': y_ticks, 'yend': y_ticks, 'x': [x_base] * n_ticks, 'xend': [x_base + tick_length] * n_ticks, } return geom_segment(aes(x='x', y='y', xend='xend', yend='yend'), data=ticks, color='gray50', size=1)
COORDS = { 'PLOT_XMIN': 0, 'PLOT_XMAX': 620, 'PLOT_YMIN': 0, 'PLOT_YMAX': 420, 'PANEL_XMIN': 88, 'PANEL_XMAX': 506, 'PANEL_YMIN': 90, 'PANEL_YMAX': 304, 'TITLE_YMIN': 11, 'TITLE_YMAX': 44.5, 'SUBTITLE_YMIN': 44, 'SUBTITLE_YMAX': 78.5, 'X_TITLE_YMIN': 346.5, 'X_TITLE_YMAX': 378, 'Y_TITLE_XMIN': 11, 'Y_TITLE_XMAX': 44.5, 'X_TEXT_XMIN': 98, 'X_TEXT_XMAX': 498, 'X_TEXT_YMIN': 320, 'X_TEXT_YMAX': 334, 'Y_TEXT_XMIN': 56, 'Y_TEXT_XMAX': 72, 'Y_TEXT_YMIN': 98, 'Y_TEXT_YMAX': 294, 'PLOT_INSET_XMIN': 44.5, 'PLOT_INSET_XMAX': 517, 'PLOT_INSET_YMIN': 79, 'PLOT_INSET_YMAX': 346, 'CAPTION_YMIN': 378, 'CAPTION_YMAX': 410, 'LEGEND_XMIN': 532, 'LEGEND_XMAX': 610, 'LEGEND_YMIN': 137, 'LEGEND_YMAX': 254, 'LEGEND_SPACING_XMIN': 518, 'LEGEND_SPACING_XMAX': 532, 'FRAME_XMIN': 86.5, 'FRAME_XMAX': 509.5, 'FRAME_YMIN': 86, 'FRAME_YMAX': 305.5, } plotting_area = labeled_rect(xmin=COORDS['PLOT_XMIN'], xmax=COORDS['PLOT_XMAX'], ymin=COORDS['PLOT_YMIN'], ymax=COORDS['PLOT_YMAX'], inner_text='', border_text='', pad=1, fill='white', color='gold', alpha=0.0) plot_margin = labeled_rect(xmin=COORDS['PLOT_XMIN'], xmax=COORDS['PLOT_XMAX'], ymin=COORDS['PLOT_YMIN'], ymax=COORDS['PLOT_YMAX'], inner_text='', border_text='plot_margin', fill='white', color='lemon_chiffon', alpha=0.9) title_area = labeled_rect(xmin=COORDS['PANEL_XMIN'], xmax=COORDS['PANEL_XMAX'], ymin=COORDS['TITLE_YMIN'], ymax=COORDS['TITLE_YMAX'], inner_text='TITLE', border_text='plot_title: margin', fill='light_blue', color='light_blue', alpha=0.3) subtitle_area = labeled_rect(xmin=COORDS['PANEL_XMIN'], xmax=COORDS['PANEL_XMAX'], ymin=COORDS['SUBTITLE_YMIN'], ymax=COORDS['SUBTITLE_YMAX'], inner_text='SUBTITLE', border_text='plot_subtitle: margin', fill='light_green', color='light_green', alpha=0.3) y_title_area = labeled_rect(xmin=COORDS['Y_TITLE_XMIN'], xmax=COORDS['Y_TITLE_XMAX'], ymin=COORDS['PANEL_YMIN'], ymax=COORDS['PANEL_YMAX'], inner_text='Y-AXIS TITLE', border_text='axis_title_y: margin', fill='peach_puff', color='peach_puff', alpha=0.2) x_title_area = labeled_rect(xmin=COORDS['PANEL_XMIN'], xmax=COORDS['PANEL_XMAX'], ymin=COORDS['X_TITLE_YMIN'], ymax=COORDS['X_TITLE_YMAX'], inner_text='X-AXIS TITLE', border_text='axis_title_x: margin', fill='peach_puff', color='peach_puff', alpha=0.2) panel_area = labeled_rect(xmin=COORDS['PANEL_XMIN'], xmax=COORDS['PANEL_XMAX'], ymin=COORDS['PANEL_YMIN'], ymax=COORDS['PANEL_YMAX'], inner_text='PLOT\nPANEL', border_text='panel_inset', fill='gray', color='light_gray', alpha=0.5) y_text_area = labeled_rect(xmin=COORDS['Y_TEXT_XMIN'], xmax=COORDS['Y_TEXT_XMAX'], ymin=COORDS['Y_TEXT_YMIN'], ymax=COORDS['Y_TEXT_YMAX'], inner_text='y-axis labels', border_text='', pad=0, fill='pink', color='light_pink', alpha=0.3) y_text_area2 = labeled_rect(xmin=COORDS['Y_TEXT_XMAX'], xmax=COORDS['Y_TEXT_XMAX'] + PAD + 1, ymin=COORDS['Y_TEXT_YMIN'], ymax=COORDS['Y_TEXT_YMAX'], inner_text='', border_text='axis_text_spacing_y', fill='pink', color='light_pink', alpha=0.3) x_text_area = labeled_rect(xmin=COORDS['X_TEXT_XMIN'], xmax=COORDS['X_TEXT_XMAX'], ymin=COORDS['X_TEXT_YMIN'], ymax=COORDS['X_TEXT_YMAX'], inner_text='x-axis labels', border_text='', pad=0, fill='pink', color='light_pink', alpha=0.3) x_text_area2 = labeled_rect(xmin=COORDS['X_TEXT_XMIN'], xmax=COORDS['X_TEXT_XMAX'], ymin=COORDS['X_TEXT_YMIN'] - PAD - 1, ymax=COORDS['X_TEXT_YMAX'] - PAD - 4, inner_text='', border_text='axis_text_spacing_x', fill='pink', color='light_pink', alpha=0.3) caption_area = labeled_rect(xmin=COORDS['PANEL_XMIN'], xmax=COORDS['PANEL_XMAX'], ymin=COORDS['CAPTION_YMIN'], ymax=COORDS['CAPTION_YMAX'], inner_text='CAPTION', border_text='plot_caption: margin', fill='sky_blue', color='sky_blue', alpha=0.3) legend_area = labeled_rect(xmin=COORDS['LEGEND_XMIN'], xmax=COORDS['LEGEND_XMAX'], ymin=COORDS['LEGEND_YMIN'], ymax=COORDS['LEGEND_YMAX'], pad=1, inner_text='LEGEND', border_text='', fill='chocolate', color='chocolate', alpha=0.1) legend_spacing = labeled_rect(xmin=COORDS['LEGEND_SPACING_XMIN'], xmax=COORDS['LEGEND_SPACING_XMAX'], ymin=COORDS['LEGEND_YMIN'], ymax=COORDS['LEGEND_YMAX'], pad=11, inner_text='', border_text='legend_box_spacing', fill='gray93', color='gray93') plot_inset_area = labeled_rect(xmin=COORDS['PLOT_INSET_XMIN'], xmax=COORDS['PLOT_INSET_XMAX'], ymin=COORDS['PLOT_INSET_YMIN'], ymax=COORDS['PLOT_INSET_YMAX'], inner_text='', border_text='plot_inset', fill='white', color='plum', alpha=0.5)
ggplot(data, aes('x', 'y')) + \ plot_margin + \ plotting_area + \ plot_inset_area + \ title_area + \ subtitle_area + \ y_title_area + \ y_text_area + y_text_area2 + \ x_title_area + \ x_text_area + x_text_area2 + \ panel_area + \ caption_area + \ legend_spacing + \ legend_area + \ annotation_arrow(x=529, y=322, xend=500, yend=306, label='axis tick area', hjust=0) + \ annotation_arrow(x=75, y=74, xend=86, yend=97, label='axis tick area', hjust=1) + \ theme_void() + \ scale_y_reverse() + \ geom_point(color='dodgerblue', alpha=1) + geom_line(color='dodgerblue', alpha=1) + \ x_ticks(data) + \ y_ticks() + \ ggsize(COORDS['PLOT_XMAX'] * SCALE_FACTOR, COORDS['PLOT_YMAX'] * SCALE_FACTOR)