In [1]:
from lets_plot import *
import pandas as pd

LetsPlot.setup_html()
In [2]:
# Shared dataset for all the plots

groups = ['A', 'B', 'C']
offsets = {'A': 0.0, 'B': 0.8, 'C': 1.6}

rows = []
for g in groups:
    off = offsets[g]
    for x in [1, 2, 3, 4, 5]:
        y = x + off
        rows.append({
            'group': g,
            'x': x,
            'y': y,
            'ymin': y - 0.6,
            'ymax': y + 0.6,
            'xmin': x - 0.35,
            'xmax': x + 0.35,
            'width': 0.7,
            'height': 0.7,
            'ridge': {'A': 1, 'B': 2, 'C': 3}[g],
            'value': x + (0 if g == 'A' else 5 if g == 'B' else 10)
        })

df = pd.DataFrame(rows)

box_rows = []
for g, base in [('A', 1.0), ('B', 2.0), ('C', 3.0)]:
    for v in [base - 0.35, base - 0.15, base, base + 0.2, base + 0.45, base + 0.7]:
        box_rows.append({'group': g, 'value': v})
df_dist = pd.DataFrame(box_rows)

poly_rows = []
poly_specs = {
    'A': [(1.0, 1.0), (2.2, 1.1), (2.0, 2.2), (1.1, 2.0), (1.0, 1.0)],
    'B': [(3.0, 1.2), (4.2, 1.0), (4.0, 2.1), (3.1, 2.3), (3.0, 1.2)],
    'C': [(5.0, 1.0), (6.3, 1.3), (6.0, 2.4), (5.2, 2.1), (5.0, 1.0)]
}
for g, pts in poly_specs.items():
    for x, y in pts:
        poly_rows.append({'group': g, 'x': x, 'y': y})
df_poly = pd.DataFrame(poly_rows)

hist_rows = []
for g, base in [('A', 1.0), ('B', 2.0), ('C', 3.0)]:
    for v in [base - 0.45, base - 0.2, base - 0.1, base, base + 0.15, base + 0.35, base + 0.55]:
        hist_rows.append({'group': g, 'value': v})
df_stat = pd.DataFrame(hist_rows)

df.head()
Out[2]:
group x y ymin ymax xmin xmax width height ridge value
0 A 1 1.0 0.4 1.6 0.65 1.35 0.7 0.7 1 1
1 A 2 2.0 1.4 2.6 1.65 2.35 0.7 0.7 1 2
2 A 3 3.0 2.4 3.6 2.65 3.35 0.7 0.7 1 3
3 A 4 4.0 3.4 4.6 3.65 4.35 0.7 0.7 1 4
4 A 5 5.0 4.4 5.6 4.65 5.35 0.7 0.7 1 5
In [3]:
def render_plots(common_settings=theme()):
    plots = [
        ggplot(df, aes('x', 'y', fill='group')) +
            geom_area(alpha=0.7) + ggtitle('geom_area') + common_settings,
    
        ggplot(df, aes('x', 'ridge', height='y', fill='group')) +
            geom_area_ridges(stat='identity', alpha=0.7) + ggtitle('geom_area_ridges') + common_settings,
    
        ggplot(df, aes('x', ymin='ymin', ymax='ymax', fill='group')) +
            geom_band(alpha=0.7) + ggtitle('geom_band') + common_settings,
    
        ggplot(df, aes('group', 'y', fill='group')) +
            geom_bar(stat='identity') + ggtitle('geom_bar') + common_settings,
    
        ggplot(df_stat, aes('value', fill='group')) +
            geom_density(alpha=0.5) + ggtitle('geom_density') + common_settings,
    
        ggplot(df_stat, aes('value', fill='group')) +
            geom_histogram(alpha=0.7, bins=7, position='identity') + ggtitle('geom_histogram') + common_settings,
    
        ggplot(df_poly, aes('x', 'y', group='group', fill='group')) +
            geom_polygon(alpha=0.7) + ggtitle('geom_polygon') + common_settings,
    
        ggplot(df, aes('x', ymin='ymin', ymax='ymax', fill='group')) +
            geom_ribbon(alpha=0.7) + ggtitle('geom_ribbon') + common_settings,
    
        ggplot(df, aes(xmin='xmin', xmax='xmax', ymin='ymin', ymax='ymax', fill='group')) +
            geom_rect(alpha=0.7) + ggtitle('geom_rect') + common_settings,
    
        ggplot(df, aes('group', 'y', fill='group')) +
            geom_violin() + ggtitle('geom_violin') + common_settings,
    
        ggplot(df, aes('x', 'ridge', fill='group')) +
            geom_tile(width=0.7, height=0.7) + ggtitle('geom_tile') + common_settings,
    
        ggplot(df_dist, aes('group', 'value', fill='group')) +
            geom_boxplot() + ggtitle('geom_boxplot') + common_settings,
    
        ggplot(df, aes('x', 'y')) +
            geom_hex(aes(fill='..count..')) + ggtitle('geom_hex') + common_settings,
    
        ggplot(df, aes('x', 'y', fill='group')) +
            geom_point(shape=22, size=6, stroke=1.2, color='black') + ggtitle('geom_point shape=22') + common_settings
    ]
    
    return gggrid(plots, ncol=4) + ggsize(1200, 1000)

Default

In [4]:
render_plots()
Out[4]:
In [5]:
render_plots(flavor_darcula())
Out[5]:

Default size but a yellow border

In [6]:
render_plots( guides(fill=guide_legend(override_aes={'color': 'yellow'})) )
Out[6]:

No border (size = 0)

In [7]:
render_plots( guides(fill=guide_legend(override_aes={'size': 0})) )
Out[7]:

Default color but size = 2

In [8]:
render_plots( guides(fill=guide_legend(override_aes={'size': 2})) )
Out[8]:

Yellow border, size = 2

In [9]:
render_plots( guides(fill=guide_legend(override_aes={'color': 'yellow', 'size': 2})) )
Out[9]:

There is a minimum interior size

In [10]:
render_plots( guides(fill=guide_legend(override_aes={'color': 'yellow', 'size': 4})) )
Out[10]:
In [11]:
render_plots( guides(fill=guide_legend(override_aes={'color': 'yellow', 'size': 10})) )
Out[11]:

Width/height are relative to the original size

width = 2

In [12]:
render_plots( guides(fill=guide_legend(override_aes={'width': 2})) )
Out[12]:

height = 2

In [13]:
render_plots( guides(fill=guide_legend(override_aes={'height': 2})) )
Out[13]:

width = 0.2

In [14]:
render_plots( guides(fill=guide_legend(override_aes={'width': 0.2})) )
Out[14]:

height = 0.5

In [15]:
render_plots( guides(fill=guide_legend(override_aes={'height': 0.5})) )
Out[15]:

Different combinations

In [16]:
render_plots( guides(fill=guide_legend(override_aes={'color': 'violet', 'size': 2, 'width': 2.4, 'height': 2.4})) )
Out[16]:
In [17]:
render_plots( guides(fill=guide_legend(override_aes={'color': 'dark_gray', 'size': 1, 'width': 3})) )
Out[17]:

Individual height/width values

In [18]:
render_plots(guides(
    fill=guide_legend(
        override_aes={'height': [0.6, 1, 1.4], 
                      'width': [0.6, 1, 1.4]}
    )
))
Out[18]:
In [19]:
render_plots( theme(legend_position='top')+ guides(fill=guide_legend(override_aes={'height': [0.6, 1, 1.4], 'width': [0.6, 1, 1.4]})) )
Out[19]:
In [20]:
render_plots(  theme(legend_position='bottom')+guides(fill=guide_legend(override_aes={'width': [0.6, 1, 1.4]})) )
Out[20]:
In [21]:
render_plots(  theme(legend_position='bottom')+guides(fill=guide_legend(override_aes={'size': [0.6, 1, 1.4]})) )
Out[21]:

geom_raster()

In [22]:
mpg = pd.read_csv('https://raw.githubusercontent.com/JetBrains/lets-plot-docs/refs/heads/master/data/mpg.csv')

raster_df = (
    mpg[mpg['cyl'].isin([4, 6, 8])]
    .groupby(['class', 'drv'], as_index=False)
    .agg(cyl=('cyl', lambda s: f'{int(s.mode().iloc[0])} cylinders'))
)
In [23]:
base = (
    ggplot(raster_df, aes('class', 'drv', fill='cyl')) +
    geom_raster() +
    scale_fill_brewer(palette="Set2") + 
    ggsize(720, 320) +
    theme(legend_position='bottom')
)

gggrid([base + ggtitle('default'), 
        base + \
    guides(fill=guide_legend(override_aes={'width': 2.6, 'height': 0.7})) + \
    ggtitle('wider and flatter legend keys')])
Out[23]:

geom_boxplot()

In [24]:
boxplot_df = mpg[mpg['class'].isin(['compact', 'subcompact', 'midsize', 'suv'])]
base = (
    ggplot(boxplot_df, aes('class', 'hwy', fill='drv')) +
    geom_boxplot(color='gray20', size=0.8, outlier_shape=21,
                 position=position_dodge(width=0.85)) +
    scale_fill_brewer(palette='Pastel1') +
    ggsize(620, 380) +
    labs(x='vehicle class', y='highway mpg', fill='drive')
)

base + ggtitle('geom_boxplot(): default legend keys') 
Out[24]:
In [25]:
base + guides(fill=guide_legend(override_aes={'width': 1.8}))
Out[25]:
In [26]:
base + guides(fill=guide_legend(override_aes={'height': 1.8}))
Out[26]:
In [27]:
base + guides(fill=guide_legend(override_aes={'height': 1.4, 'width': 1.7}))
Out[27]:
In [28]:
base + guides(fill=guide_legend(override_aes={'height': 0.7, 'width': 0.7}))
Out[28]:
In [31]:
(
    ggplot(boxplot_df, aes('class', 'hwy', fill='drv')) +
    geom_boxplot(color='gray20', size=2.0, outlier_shape=21,
                 position=position_dodge(width=0.85)) +
    scale_fill_brewer(palette='Pastel1') +
    ggsize(620, 380) +
    labs(x='vehicle class', y='highway mpg', fill='drive') +
    ggtitle('size=2')
)
Out[31]:
In [ ]: