Download notebook (.ipynb)

Palmer Penguins#

This notebook is inspired by an example Radar chart with ggradar.

import numpy as np
import pandas as pd

from lets_plot import *
LetsPlot.setup_html()
def rescale_in_group_df(df, value_col, group_col, rescaled_col=None):
    if rescaled_col is None:
        rescaled_col = "rescaled_{0}".format(value_col)
    def rescale_subdf(subdf):
        rescaler = lambda s: (s - s.min()) / (s.max() - s.min())
        return subdf.assign(**{rescaled_col: rescaler(subdf[value_col])})
    return pd.concat([rescale_subdf(df[df[group_col] == g]) for g in df[group_col].unique()])

def get_data():
    df = pd.read_csv("https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/data/penguins.csv")

    grouped_df = df.dropna().groupby("species")[["bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g"]].mean().reset_index()
    grouped_df.columns = ["species", "avg. bill length", "avg. bill depth", "avg. flipper length", "avg. body mass"]

    melted_df = pd.melt(grouped_df, id_vars="species")
    avg_body_mass_filter = melted_df["variable"] == "avg. body mass"
    melted_df.loc[avg_body_mass_filter, "value"] /= 1000
    melted_df = melted_df.assign(units=np.where(avg_body_mass_filter, "kg", "mm"))

    rescaled_df = rescale_in_group_df(melted_df, "value", "variable")
    rescaled_df.loc[:, "rescaled_value_pct"] = (100 * rescaled_df["rescaled_value"]).astype(int)
    return rescaled_df.sort_values(by="species").reset_index(drop=True)
penguins_df = get_data()
penguins_df.head(4)
species variable value units rescaled_value rescaled_value_pct
0 Adelie avg. bill length 38.823973 mm 0.000000 0
1 Adelie avg. bill depth 18.347260 mm 0.978584 97
2 Adelie avg. flipper length 190.102740 mm 0.000000 0
3 Adelie avg. body mass 3.706164 kg 0.000000 0
font_family = "roboto"
axis_color = "lightgray"
axis_text_data = {"x": ["avg. bill length"]*3, \
                  "y": [0, 50, 100], \
                  "text": ["0%", "50%", "100%"]}

penguins_colors = {"Adelie": "#ff5a5f", "Chinstrap": "#ffb400", "Gentoo": "#007a87"}
penguins_tooltips = layer_tooltips().title("@species")\
                                    .line("@variable (@units): @value").format("@value", ".2~f")
penguins_theme = theme(
    text=element_text(family=font_family, size=18),
    plot_title=element_text(size=28, hjust=.5, face='bold'),
    axis_title='blank', axis_text_y='blank', axis_line_x='blank', \
    axis_ticks=element_line(color=axis_color), \
    panel_grid=element_line(color=axis_color), \
    panel_inset=[0, 80], \
    legend_position=[1, 0], legend_justification=[1, 0],
    tooltip=element_rect(),
    axis_tooltip='blank',
)
ggplot(penguins_df) + \
    geom_area(aes("variable", "rescaled_value_pct", paint_a="species"), position='identity', flat=True, \
              size=2.5, color_by='paint_a', fill_by='paint_a', alpha=.2) + \
    geom_point(aes("variable", "rescaled_value_pct", paint_a="species"), size=6, color_by='paint_a', tooltips=penguins_tooltips) + \
    geom_text(aes("x", "y", label="text"), data=axis_text_data, hjust=1, fontface='bold', family=font_family, size=10) + \
    scale_x_discrete() + \
    scale_manual('paint_a', name='', values=penguins_colors) + \
    coord_polar(ylim=[-15, 100]) + \
    ggsize(800, 600) + \
    ggtitle("Penguins species") + \
    penguins_theme + flavor_solarized_light()