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()