简体   繁体   中英

How to assign figure titles from a group_by (dplyr) variable when creating multiple plotly figures in R

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

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]]


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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM