I'm quite comfortable using the tidyverse and ggplot. I'm trying to produce an interactive graph to deploy with flexdashboard. I'm therefore trying to generate my usual ggplots in plotly.
Suppose I have the following dataframe:
data.frame(id = c(1:5),
product = c("product1","product2","product1","product3","product2"),
variable = c("var1","var1","var3","var2","var1"),
price = c(100,120,140,90,80))
With output:
id product variable price
1 1 product1 var1 100
2 2 product2 var1 120
3 3 product1 var3 140
4 4 product3 var2 90
5 5 product2 var1 80
If I want to display all of this on a plot, I would do the following in ggplot:
library(tidyverse)
library(hrbrthemes)
data.frame(id = c(1:5),
product = c("product1","product2","product1","product3","product2"),
variable = c("var1","var1","var3","var2","var1"),
price = c(100,120,140,90,80)) %>%
ggplot(aes(x = id, y = price, color = variable))
geom_point()
facet_wrap(~product)
theme_ft_rc()
Which woud yield:
I understand I can achieve something similar in plotly by using the subplot()
function. The issues is that I have somewhere between 14-28 categories to plot as facets. Which as far as I understand, would mean that I would have to produce 14-28 plots and then arrange them in a grid. It seems a bit tedious and I was wondering if there was a more efficient way to achieve that, such as the facet option in ggplot. I also got a snippet of code on another post:
library(plotly)
dataframe <- data.frame(id = c(1:5),
product = c("product1","product2","product1","product3","product2"),
variable = c("var1","var1","var3","var2","var1"),
price = c(100,120,140,90,80)) %>%
pivot_wider(names_from = "product", values_from = "price")
vars <- setdiff(names(dataframe),"id")
plots <- lapply(vars, function(var){
plot_ly(dataframe, x = ~id, color =~variable, y = as.formula(paste0("~",var))) %>%
add_bars(name = var)
})
subplot(plots, nrows = length(plots), shareX = TRUE, titleX = FALSE)
Which yields:
and requires to use tidyr's pivot_wider()
function with the product
column in the sample frame. However, my real columns contain numbers and characters, which yields an error when using the above sample code. The variable column is also displayed in an odder manner. Is there are workaround to this issue, or is the best way truly to manually write the code for every single plot?
CodePudding user response:
According to your first example (I just removed your theme styling) it works like this.
df <- data.frame(
id = c(1:5),
product = c("product1","product2","product1","product3","product2"),
variable = c("var1","var1","var3","var2","var1"),
price = c(100,120,140,90,80)
)
plot <- ggplot(df, aes(x = id, y = price, color = variable))
geom_point()
facet_wrap(~product)
ggplotly(plot)
The only difference is that I did not chain with %>% as it seems that plotly throws an error when I try this below:
data.frame(
id = c(1:5),
product = c("product1","product2","product1","product3","product2"),
variable = c("var1","var1","var3","var2","var1"),
price = c(100,120,140,90,80)
) %>% ggplot(aes(x = id, y = price, color = variable))
geom_point()
facet_wrap(~product) %>% ggplotly()
# Error in UseMethod("ggplotly", p) :
# no applicable method for 'ggplotly' applied to an object of class "c('FacetWrap', 'Facet', 'ggproto', 'gg')"
Extended example with custom tooltip
You can make it as fancy as you like, I added price formatting and for the fun of it combined product and variable as one line in the tooltip.
custom_tooltip <- paste0("ID: ", df$id, "\n", "Product: ", df$product, " (", df$variable, ")\n", "Sold for: £ ", df$price)
plot <- ggplot(df, aes(x = id, y = price, color = variable))
geom_point(aes(text = custom_tooltip))
facet_wrap(~product)
ggplotly(plot, tooltip = c("text"))