The package d3po
integrates well with
dplyr
. All the examples here use the pipe,
%>%
, both to filter/summarise data and create the
charts.
Let’s start by loading packages.
library(dplyr)
library(igraph)
library(d3po)
The included dataset pokemon
has the present
structure:
glimpse(pokemon)
#> Rows: 151
#> Columns: 15
#> $ id <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,…
#> $ name <chr> "Bulbasaur", "Ivysaur", "Venusaur", "Charmander", "Cha…
#> $ height <dbl> 0.7, 1.0, 2.0, 0.6, 1.1, 1.7, 0.5, 1.0, 1.6, 0.3, 0.7,…
#> $ weight <dbl> 6.9, 13.0, 100.0, 8.5, 19.0, 90.5, 9.0, 22.5, 85.5, 2.…
#> $ base_experience <int> 64, 142, 236, 62, 142, 240, 63, 142, 239, 39, 72, 178,…
#> $ type_1 <chr> "grass", "grass", "grass", "fire", "fire", "fire", "wa…
#> $ type_2 <chr> "poison", "poison", "poison", NA, NA, "flying", NA, NA…
#> $ attack <int> 49, 62, 82, 52, 64, 84, 48, 63, 83, 30, 20, 45, 35, 25…
#> $ defense <int> 49, 63, 83, 43, 58, 78, 65, 80, 100, 35, 55, 50, 30, 5…
#> $ hp <int> 45, 60, 80, 39, 58, 78, 44, 59, 79, 45, 50, 60, 40, 45…
#> $ special_attack <int> 65, 80, 100, 60, 80, 109, 50, 65, 85, 20, 25, 90, 20, …
#> $ special_defense <int> 65, 80, 100, 50, 65, 85, 64, 80, 105, 20, 25, 80, 20, …
#> $ speed <int> 45, 60, 80, 65, 80, 100, 43, 58, 78, 45, 30, 70, 50, 3…
#> $ color_1 <chr> "#78C850", "#78C850", "#78C850", "#F08030", "#F08030",…
#> $ color_2 <chr> "#A040A0", "#A040A0", "#A040A0", NA, NA, "#A890F0", NA…
To compare the distribution of weight
by
type_1
, the pokemon
dataset doesn’t need
additional aggregation or transformation, just to use the Pokemon
name
as the grouping variable and (optionally) the
color
variable:
d3po(pokemon) %>%
po_box(daes(x = type_1, y = speed, group = name, color = color_1)) %>%
po_title("Distribution of Pokemon Speed by Type")
Let’s start by counting Pokemon by type:
<- pokemon %>%
pokemon_count group_by(type_1, color_1) %>%
count()
Now we can create a bar chart by using type_1
both for
the x
axis and the group_by
variable provided
this data has no year
column or similar:
d3po(pokemon_count) %>%
po_bar(
daes(x = type_1, y = n, group = type_1, color = color_1)
%>%
) po_title("Count of Pokemon by Type")
By using the pokemon_count
table created for the bar
chart, the logic is exactly the same and we only need to change the
function and specify the size
instead of x
and
y
:
d3po(pokemon_count) %>%
po_treemap(
daes(size = n, group = type_1, color = color_1)
%>%
) po_title("Share of Pokemon by Type")
Use these plots with caution because polar coordinates has major perceptual problems. Use with EXTREME caution.
This method is exactly the same as treemap
but changing
the function.
d3po(pokemon_count) %>%
po_pie(
daes(size = n, group = type_1, color = color_1)
%>%
) po_title("Share of Pokemon by Type")
Let’s start by obtaining the decile for the Pokemon
weight
just for the grass, fire and water type:
<- pokemon %>%
pokemon_decile filter(type_1 %in% c("grass", "fire", "water")) %>%
group_by(type_1 ,color_1) %>%
summarise(
decile = 0:10,
weight = quantile(weight, probs = seq(0, 1, by = .1))
)#> Warning: Returning more (or less) than 1 row per `summarise()` group was deprecated in
#> dplyr 1.1.0.
#> ℹ Please use `reframe()` instead.
#> ℹ When switching from `summarise()` to `reframe()`, remember that `reframe()`
#> always returns an ungrouped data frame and adjust accordingly.
#> `summarise()` has grouped output by 'type_1', 'color_1'. You can override using
#> the `.groups` argument.
Now we can create an area chart by using the variable
and color
columns created above:
d3po(pokemon_decile) %>%
po_line(
daes(x = decile, y = weight, group = type_1, color = color_1)
%>%
) po_title("Decile of Pokemon Weight by Type")
Let’s start by obtaining the density for the Pokemon
weight
:
<- density(pokemon$weight, n = 30)
pokemon_density
<- tibble(
pokemon_density x = pokemon_density$x,
y = pokemon_density$y,
variable = "weight",
color = "#5377e3"
)
Now we can create an area chart by using the variable
and color
columns created above:
d3po(pokemon_density) %>%
po_area(
daes(x = x, y = y, group = variable, color = color)
%>%
) po_title("Approximated Density of Pokemon Weight")
Let’s explore the balance between defense and attack by Pokemon type:
<- pokemon %>%
pokemon_def_vs_att group_by(type_1, color_1) %>%
summarise(
mean_def = mean(defense),
mean_att = mean(attack),
n_pkmn = n()
)#> `summarise()` has grouped output by 'type_1'. You can override using the
#> `.groups` argument.
d3po(pokemon_def_vs_att) %>%
po_scatter(
daes(x = mean_att, y = mean_def, size = n_pkmn, group = type_1, color = color_1)
%>%
) po_title("Average Attack vs Average Defense by Type")
This visualization method is different to the rest, as it can work
with a single data
object or data
,
nodes
and edges
objects by separate.
Let’s create an igraph object:
<- make_tree(40, children = 3, mode = "undirected") tr
To visualize is as simple as:
d3po(tr) %>%
po_layout() # optional
Another option is to work with a data.frame
or
tibble
:
<- igraph::as_data_frame(tr, "edges") edges
Which is also visualized in a straightforward manner:
d3po() %>%
po_edges(data = edges)
Going back to the treemap example, it is possible to move the labels and also use any font that you like:
d3po(pokemon_count) %>%
po_treemap(
daes(size = n, group = type_1, color = color_1, align = "left")
%>%
) po_title("Share of Pokemon by Type") %>%
po_font("Fira Sans", 12, "uppercase") %>%
po_labels("left", "top", F, "Times", 30, "uppercase")