Parameters width_unit/height_unit

In [1]:
from math import sqrt

import pandas as pd

from lets_plot import *
In [2]:
LetsPlot.setup_html()

geom_errorbar()

Issue #1288 - Allow absolute width for geom_errorbar (and possibly others)

In [3]:
def get_diff_data():
    n = 16
    dy = 100
    xs = [2 * i for i in range(n)]
    return pd.DataFrame({
        'x': xs,
        'ymin': [dy + i % 4 for i in range(n)],
        'lower': [dy + i % 4 + .25 for i in range(n)],
        'upper': [dy + i % 4 + 2.25 for i in range(n)],
        'ymax': [dy + i % 4 + 2.5 for i in range(n)],
        'width_px': [10 * (i % 4 + 1) for i in range(n)]
    })

diff16_df = get_diff_data()
diff4_df = diff16_df.iloc[:4]
In [4]:
def get_errorbar_plot(df, width=None, width_unit=None):
    cat_size = len(df['x'].unique())
    return ggplot(df) + \
        geom_errorbar(aes(x='x', ymin='ymin', ymax='ymax'),
                      width=width, width_unit=width_unit) + \
        ggtitle("categories count: {0}\nwidth={1}, width_unit={2}".format(
            cat_size, width, width_unit
        ))
In [5]:
gggrid([
    get_errorbar_plot(diff16_df, width=.5),
    get_errorbar_plot(diff4_df, width=.5),
    get_errorbar_plot(diff16_df, width=5, width_unit='size'),
    get_errorbar_plot(diff4_df, width=5, width_unit='size'),
], ncol=2)
Out[5]:

Additional tests

In [6]:
gggrid([
    ggplot(diff4_df) + \
        geom_errorbar(aes(x='x', ymin='ymin', ymax='ymax', width='width_px'), width_unit='px') + \
        ggtitle("Mapped width (px)"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(x='x', ymin='ymin', ymax='ymax'), width_unit='px', width=30) + \
        ggtitle("Constant width (30 px)"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(y='x', xmin='ymin', xmax='ymax'), width_unit='px', width=30) + \
        ggtitle("Constant width (30 px)", "orientation='y'"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(x='x', ymin='ymin', ymax='ymax'), width_unit='res', width=1) + \
        ggtitle("Constant width (1 res)"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(x='x', ymin='ymin', ymax='ymax'), width_unit='identity', width=2) + \
        ggtitle("Constant width (2 identity = 2 axis units)"),
    ggplot(diff4_df) + \
        geom_point(aes(x='x', y='ymax'), size=12, color="lightgray") + \
        geom_errorbar(aes(x='x', ymin='ymin', ymax='ymax'), width_unit='size', width=12) + \
        ggtitle("Constant width (12 sizes = point of size 12)"),
], ncol=2)
Out[6]:
In [7]:
def get_diff_test_plot(width, width_unit, coord, geom):
    p = ggplot(diff4_df) + \
        geom(aes(x='x', ymin='ymin', ymax='ymax', lower='lower', upper='upper'),
             stat='identity', width_unit=width_unit, width=width) + \
        coord + \
        ggtitle("width={w}, width_unit={wu}\n\ncoord={c}".format(
            w=width,
            wu=width_unit,
            c=coord.as_dict()
        ))
    if width_unit == 'size':
        p += geom_point(aes(x='x', y='ymax'), size=12, color="gray", alpha=.25)
    return p

plots = []
for width, width_unit in [(1, 'res'), (2, 'identity'), (50, 'px'), (12, 'size')]:
    for coord in [
        coord_cartesian(),
        coord_fixed(ratio=.5),
        coord_flip(),
    ]:
        plots.append(get_diff_test_plot(width, width_unit, coord, geom_errorbar))

gggrid(plots, ncol=2) + ggsize(800, 2400)
Out[7]:

Deprecated aesthetics and parameters

In [8]:
gggrid([
    ggplot(diff4_df) + \
        geom_errorbar(aes(y='x', xmin='ymin', xmax='ymax', height='width_px'), width_unit='px') + \
        ggtitle("aes(height='width_px')"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(y='x', xmin='ymin', xmax='ymax', width='width_px', height='width_px'), width_unit='px') + \
        ggtitle("aes(width='width_px', height='width_px')"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(y='x', xmin='ymin', xmax='ymax', width='width_px'), height_unit='px') + \
        ggtitle("aes(width='width_px'), height_unit='px'"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(y='x', xmin='ymin', xmax='ymax'), width=30, height_unit='px') + \
        ggtitle("width=30, height_unit='px'"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(y='x', xmin='ymin', xmax='ymax'), width=30, height_unit='px', width_unit='px') + \
        ggtitle("width=30, height_unit='px', width_unit='px'"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(y='x', xmin='ymin', xmax='ymax'), height=30, width_unit='px') + \
        ggtitle("height=30"),
    ggplot(diff4_df) + \
        geom_errorbar(aes(y='x', xmin='ymin', xmax='ymax'), width=50, height=10, width_unit='px') + \
        ggtitle("width=50 and height=10"),
], ncol=2)
WARN: using 'height' aesthetic parameter for errorbar was deprecated.
      Please, use 'width' aesthetic instead.
WARN: using 'height' aesthetic parameter for errorbar was deprecated.
      Please, use 'width' aesthetic instead.
WARN: using 'height_unit' parameter for errorbar was deprecated.
      Please, use 'width_unit' parameter instead.
WARN: using 'height_unit' parameter for errorbar was deprecated.
      Please, use 'width_unit' parameter instead.
WARN: using 'height_unit' parameter for errorbar was deprecated.
      Please, use 'width_unit' parameter instead.
WARN: using 'height' parameter for errorbar was deprecated.
      Please, use 'width' parameter instead.
WARN: using 'height' parameter for errorbar was deprecated.
      Please, use 'width' parameter instead.
Out[8]:

geom_boxplot()/geom_crossbar()

In [9]:
gggrid([
    ggplot(diff4_df) + \
        geom_boxplot(aes(x='x', ymin='ymin', ymax='ymax', lower='lower', upper='upper', width='width_px'),
                     stat='identity', width_unit='px') + \
        ggtitle("Mapped width (px)"),
    ggplot(diff4_df) + \
        geom_boxplot(aes(x='x', ymin='ymin', ymax='ymax', lower='lower', upper='upper'),
                     stat='identity', width_unit='px', width=30) + \
        ggtitle("Constant width (30 px)"),
    ggplot(diff4_df) + \
        geom_boxplot(aes(x='x', ymin='ymin', ymax='ymax', lower='lower', upper='upper'),
                     stat='identity', width_unit='res', width=1) + \
        ggtitle("Constant width (1 res)"),
    ggplot(diff4_df) + \
        geom_boxplot(aes(x='x', ymin='ymin', ymax='ymax', lower='lower', upper='upper'),
                     stat='identity', width_unit='identity', width=2) + \
        ggtitle("Constant width (2 identity = 2 axis units)"),
    ggplot(diff4_df) + \
        geom_point(aes(x='x', y='upper'), size=12, color="lightgray") + \
        geom_boxplot(aes(x='x', ymin='ymin', ymax='ymax', lower='lower', upper='upper'),
                     stat='identity', width_unit='size', width=12) + \
        ggtitle("Constant width (12 sizes = point of size 12)"),
], ncol=2)
Out[9]:
In [10]:
plots = []
for width, width_unit in [(1, 'res'), (2, 'identity'), (50, 'px'), (12, 'size')]:
    for coord in [
        coord_cartesian(),
        coord_fixed(ratio=.5),
        coord_flip(),
    ]:
        plots.append(get_diff_test_plot(width, width_unit, coord, geom_boxplot))

gggrid(plots, ncol=2) + ggsize(800, 2400)
Out[10]:
In [11]:
gggrid([
    ggplot(diff4_df) + \
        geom_crossbar(aes(x='x', ymin='ymin', ymax='ymax', width='width_px'), width_unit='px') + \
        ggtitle("Mapped width (px)"),
    ggplot(diff4_df) + \
        geom_crossbar(aes(x='x', ymin='ymin', ymax='ymax'), width_unit='px', width=30) + \
        ggtitle("Constant width (30 px)"),
    ggplot(diff4_df) + \
        geom_crossbar(aes(y='x', xmin='ymin', xmax='ymax'), width_unit='px', width=30) + \
        ggtitle("Constant width (30 px)", "orientation='y'"),
    ggplot(diff4_df) + \
        geom_crossbar(aes(x='x', ymin='ymin', ymax='ymax'), width_unit='res', width=1) + \
        ggtitle("Constant width (1 res)"),
    ggplot(diff4_df) + \
        geom_crossbar(aes(x='x', ymin='ymin', ymax='ymax'), width_unit='identity', width=2) + \
        ggtitle("Constant width (2 identity = 2 axis units)"),
    ggplot(diff4_df) + \
        geom_point(aes(x='x', y='ymax'), size=12, color="lightgray") + \
        geom_crossbar(aes(x='x', ymin='ymin', ymax='ymax'), width_unit='size', width=12) + \
        ggtitle("Constant width (12 sizes = point of size 12)"),
], ncol=2)
Out[11]:
In [12]:
plots = []
for width, width_unit in [(1, 'res'), (2, 'identity'), (50, 'px'), (12, 'size')]:
    for coord in [
        coord_cartesian(),
        coord_fixed(ratio=.5),
        coord_flip(),
    ]:
        plots.append(get_diff_test_plot(width, width_unit, coord, geom_crossbar))

gggrid(plots, ncol=2) + ggsize(800, 2400)
Out[12]:

geom_tile()

Custom width with 'identity' stat

Suppose we have the following hand-calculated statistics for binwidth=[4, 4]:

In [13]:
tile_stat_data = {
    'x': [2,  2, 6, 10, 10],
    'y': [2, 10, 2,  2, 10],
    'mean': [1.2, 1.8, 0.8, 1.2, 0.6],
    'width_px': [10, 20, 30, 40, 50],
    'height_px': [10, 20, 30, 40, 50],
}

And we want to plot this data using geom_tile() (or geom_bin2d(stat='identity')):

In [14]:
def get_tile_plot(width=None, height=None, width_unit=None, height_unit=None):
    return ggplot(tile_stat_data, aes('x', 'y')) + \
        geom_tile(aes(fill='mean'), width=width, height=height,
                  width_unit=width_unit, height_unit=height_unit) + \
        ggtitle("Supposed binwidth: [4, 4]\nwidth={w}, width_unit={wu}\nheight={h}, height_unit={hu}".format(
            w=width, wu=width_unit,
            h=height, hu=height_unit,
        ))
In [15]:
gggrid([
    get_tile_plot(),
    get_tile_plot(width=1, height=.5),
    get_tile_plot(width=4, height=4, width_unit='identity', height_unit='identity'),
], ncol=3)
Out[15]:

Additional tests

In [16]:
gggrid([
    ggplot(tile_stat_data, aes('x', 'y')) + \
        geom_tile(aes(fill='mean', width='width_px', height='height_px'),
                  width_unit='px', height_unit='px') + \
        ggtitle("Mapped width and height (px)"),
    ggplot(tile_stat_data, aes('x', 'y')) + \
        geom_tile(aes(fill='mean'),
                  width=40, height=40,
                  width_unit='px', height_unit='px') + \
        ggtitle("Constant width and height (40 px)"),
    ggplot(tile_stat_data, aes('x', 'y')) + \
        geom_tile(aes(fill='mean'),
                  width=1, height=1,
                  width_unit='res', height_unit='res') + \
        ggtitle("Constant width and height (1 res)"),
    ggplot(tile_stat_data, aes('x', 'y')) + \
        geom_tile(aes(fill='mean'),
                  width=3, height=3,
                  width_unit='identity', height_unit='identity') + \
        ggtitle("Constant width and height (3 identity = 3 axis units)"),
    ggplot(tile_stat_data, aes('x', 'y')) + \
        geom_tile(aes(fill='mean'),
                  width=20, height=20,
                  width_unit='size', height_unit='size') + \
        geom_point(color='gray', size=20) + \
        ggtitle("Constant width and height (20 sizes = point of size 20)"),
], ncol=2)
Out[16]:
In [17]:
def get_tile_test_plot(width, height, width_unit, height_unit, coord):
    return ggplot(tile_stat_data, aes('x', 'y')) + \
        geom_tile(aes(fill='mean'),
                  width_unit=width_unit, height_unit=height_unit,
                  width=width, height=height) + \
        geom_point(size=12, color="lightgray") + \
        coord + \
        ggtitle("width={w}, width_unit={wu}\nheight={h}, height_unit={hu}\n\ncoord={c}".format(
            w=width,
            wu=width_unit,
            h=height,
            hu=height_unit,
            c=coord.as_dict()
        ))

plots = []
for dim, dim_unit in [(1, 'res'), (3, 'identity'), (50, 'px'), (12, 'size')]:
    for coord in [
        coord_cartesian(),
        coord_fixed(ratio=.5),
        coord_flip(),
    ]:
        plots.append(get_tile_test_plot(dim, dim, dim_unit, dim_unit, coord))

gggrid(plots, ncol=2) + ggsize(800, 2400)
Out[17]:

geom_hex()

In [18]:
hex_stat_data = {
    'x': [2,  2, 6, 10, 10],
    'y': [v * sqrt(3.0) / 2.0 for v in [2, 10, 2,  2, 10]],
    'v': [1.2, 1.8, 0.8, 1.2, 0.6],
    'width_px': [10, 20, 30, 40, 50],
    'height_px': [10, 20, 30, 40, 50],
}
In [19]:
gggrid([
    ggplot(hex_stat_data, aes('x', 'y')) + \
        geom_hex(aes(fill='v', width='width_px', height='height_px'),
                 stat='identity',
                 width_unit='px', height_unit='px') + \
        ggtitle("Mapped width and height (px)"),
    ggplot(hex_stat_data, aes('x', 'y')) + \
        geom_hex(aes(fill='v'),
                 stat='identity',
                 width=40, height=40,
                 width_unit='px', height_unit='px') + \
        ggtitle("Constant width and height (40 px)"),
    ggplot(hex_stat_data, aes('x', 'y')) + \
        geom_hex(aes(fill='v'),
                 stat='identity',
                 width=0.5, height=0.5,
                 width_unit='res', height_unit='res') + \
        ggtitle("Constant width and height (0.5 res)"),
    ggplot(hex_stat_data, aes('x', 'y')) + \
        geom_hex(aes(fill='v'),
                 stat='identity',
                 width=4, height=4,
                 width_unit='identity', height_unit='identity') + \
        ggtitle("Constant width and height (4 identity = 4 axis units)"),
    ggplot(hex_stat_data, aes('x', 'y')) + \
        geom_hex(aes(fill='v'),
                 stat='identity',
                 width=20, height=20,
                 width_unit='size', height_unit='size') + \
        geom_point(color='gray', size=20) + \
        ggtitle("Constant width and height (20 sizes = point of size 20)"),
], ncol=2)
Out[19]:
In [20]:
def get_hex_test_plot(width, height, width_unit, height_unit, coord):
    return ggplot(hex_stat_data, aes('x', 'y')) + \
        geom_hex(aes(fill='v'),
                 stat='identity',
                 width_unit=width_unit, height_unit=height_unit,
                 width=width, height=height) + \
        geom_point(size=12, color="lightgray") + \
        coord + \
        ggtitle("width={w}, width_unit={wu}\nheight={h}, height_unit={hu}\n\ncoord={c}".format(
            w=width,
            wu=width_unit,
            h=height,
            hu=height_unit,
            c=coord.as_dict()
        ))

plots = []
for dim, dim_unit in [(0.5, 'res'), (4, 'identity'), (50, 'px'), (12, 'size')]:
    for coord in [
        coord_cartesian(),
        coord_fixed(ratio=.5),
        coord_flip(),
    ]:
        plots.append(get_hex_test_plot(dim, dim, dim_unit, dim_unit, coord))

gggrid(plots, ncol=2) + ggsize(800, 2400)
Out[20]: