Reputation: 11754
Long-time reader, first time asker here.
I am creating multiple plots using plotly and dplyr's group_by (one figure per level of the group_by variable).
In the example below, I am creating one plot per year (the group_by variable), and I would like to assign the year as the figure title. But, I can't figure out how to use the stored value from the data frame (or tibble) to assign the title.
Any suggestions are greatly appreciated! Thank you!
require(dplyr)
require(plotly)
# creating data table
d = tibble(year=rep(2016:2017,2), type=c(1,1,2,2), amount=1:4)
d
# creating 2 figures, grouped by year (one for each year).
# Using the same title for each figure (this code works).
chart = d %>%
group_by(year) %>%
do(plots = plot_ly(., values = ~amount, type = 'pie') %>% layout(title="Great Title") )
# printing first plot
chart$plots[1][[1]]
# I'd like the title of each figure to be the year.
# I get an error when I try to assign the title with the year variable.
chart.title = d %>%
group_by(year) %>%
do(plots = plot_ly(., values = ~amount, type = 'pie') %>% layout(title=year) )
Upvotes: 0
Views: 1548
Reputation: 6542
In the tidyverse, purrr
is the tool to iterate over element and a helper for functionnal programming.
Combining purrr
and nested data.frame with list columns is a powerful workflow.
You can then do the same as group_by
and do
but it is more powerful.
I have read somewhere it could replace dplyr::do
.
Here is a solution for your problem the tidyverse
way
library(dplyr, warn.conflicts = F)
library(plotly)
# for iteration and fonctionnal programming
library(purrr)
# for nesting dataframe
library(tidyr)
# creating the data
d <- tibble(year=rep(2016:2017,2), type=c(1,1,2,2), amount=1:4)
d
#> # A tibble: 4 x 3
#> year type amount
#> <int> <dbl> <int>
#> 1 2016 1 1
#> 2 2017 1 2
#> 3 2016 2 3
#> 4 2017 2 4
As you want to work by Year, you could nest data by Year and have a tibble with one row per year and a list column named data in which each element is a tibble, the subset of the initial data for the year on the line
nested_data <- d %>%
nest(-year)
nested_data
#> # A tibble: 2 x 2
#> year data
#> <int> <list>
#> 1 2016 <tibble [2 x 2]>
#> 2 2017 <tibble [2 x 2]>
purrr
fonctions with map
family allow you to iterate through lists.
Combined with dplyr
verbs, we will add a column containing the
plotly
graph. map2
takes 2 arguments, the list column data and the
column year and apply a fonction We get a list as a result that we'll
store in another list column named plots
charts <- nested_data %>%
mutate(plots = map2(data, year, ~ plot_ly(.x, values = ~amount, type = 'pie') %>% layout(title = .y)))
You can continue to work with this tibble. The plots are calculated and stored with your data.
charts
#> # A tibble: 2 x 3
#> year data plots
#> <int> <list> <list>
#> 1 2016 <tibble [2 x 2]> <S3: plotly>
#> 2 2017 <tibble [2 x 2]> <S3: plotly>
To print plot manually, you can access it
charts$plots[1]
#> [[1]]
You can you purrr
to iterate over the list column and print all plots
# This will print plot in the RStudio viewer
print_plot <- charts %>%
select(plots) %>%
walk(print)
In conclusion, you can replace in the tidyverse
ecosystem, group_by
and do
by nest
and purrr
functions.
charts <- d %>%
nested(- year) %>%
mutate(plots = map2(data, year, ~ plot_ly(.x, values = ~amount, type = 'pie') %>% layout(title = .y)))
Upvotes: 1
Reputation: 1228
This should not be complicated, since you can access the local year variable through .$year
and thus the unique year through .$year[1]
for instance (since year
in each group is a constant).
But you get a problem because of your double use of the %>%
pipe sign, outside and inside do
, that makes it impossible for .
to refer to the grouped data – instead, it refers to the current plot. You can get rid of this problem by un-nesting:
chart = d %>%
group_by(year) %>%
do(plots = layout(
plot_ly(., values = ~amount, type = 'pie'),
title = paste('Chart of year', .$year[1]))
)
chart$plots[1][[1]]
Upvotes: 1