Rob
Rob

Reputation: 41

How to create a reusable plot_ly function?

I am looking at a dataset from tidytuesday, available here:

video_games <- readr::read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2019/2019-07-30/video_games.csv")

I wrote this code to create a horizontal bar plot, ranked in descending order.

video_games %>% 
  top_n(10, metascore) %>% 
  arrange(desc(metascore)) %>% 
  plot_ly(x = ~metascore, y = ~fct_reorder(game, metascore), 
          type = "bar") %>% 
  layout(xaxis = list(title = "Metascore"),
         yaxis = list(title = ""))

I want to reuse the code with multiple variables without copying and pasting, so I created a function with 2 entries for the variables I want to plot. (I left out the layout section. If there is a way to automatically re-lable the plot inside the function, that would be cool.)

video_games_ranking_plot <- function(A, B) {
  top_n(10, A) %>% 
    arrange(desc(A)) %>% 
    plot_ly(x = ~A, y = ~fct_reorder(B, A), 
            type = "bar")
}

When I run the function

video_games %>%           
video_games_ranking_plot(metascore, game)

... I get the error message Error in video_games_ranking_plot(., metascore, game) : unused argument (game)

Does anyone know why?

Upvotes: 2

Views: 244

Answers (1)

vestland
vestland

Reputation: 61104

The source of the problem seems to be that you are passing the same arguments metascore, game of one type to very different elements of your custom function that accepts arguments of different types:

  1. top_n(10, metascore)
  2. arrange(desc(metascore)
  3. plot_ly(x = ~metascore, y = ~fct_reorder(game, metascore)

The fact that you are also passing columns ase arguments using piping can also pose certain challenges. I haven't found the time to build a complete solution, but hopefully this will help you on your way to a complete solution:

Plot:

enter image description here

Code:

library(dplyr)
library(forcats)
library(plotly)

# get data
video_games <- readr::read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2019/2019-07-30/video_games.csv")

data <- video_games

# custom function
video_games_ranking_plot <- function(data, topn, col_top, col_ord){

  # select and arrand data
  df <- data %>% top_n(topn, {{col_top}}) %>% arrange(desc({{col_ord}})) #%>%

  col_top_name <- deparse(substitute(col_top))
  col_ord_name <- deparse(substitute(col_ord))
  df2<- df[c(col_top_name, col_ord_name)]

  # build plotly pliot
  p <- plot_ly(x = df2[[col_top_name]], y = df2[[col_ord_name]], type = "bar")


}

plt <- video_games_ranking_plot(data=video_games, topn=5, metascore, game)  

plt

There's still an issue with the ~fct_reorder(game, metascore) part. I had to raise a question myself to even get this far. Take a look at the answer from user Ronak Shah to the post How to pass a dataframe column as an argument in a function using piping? to learn more on how to pass arguments to piping functions.

I hope this helps!

Upvotes: 2

Related Questions