I want to plot a facet plot with added geom_hline and show the line in the legend. However, when I add the line to the legend, all entries duplicate to the number of facets.
How can I avoid this behaviour?
Here is my MWE
library(shiny)
library(plotly)
library(ggplot2)
df <- mpg
# Define UI for application that draws a histogram
ui <- fluidPage(
mainPanel(
plotlyOutput('graph')
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$graph <- renderPlotly({
p <- ggplot2::mpg %>%
plot_ly %>%
ggplot() +
geom_point(aes(displ, hwy, color = class))
facet <- p + facet_wrap(~year)
facet + geom_hline(aes(yintercept = 20, linetype = 'hline20'), color = '#00b700') +
scale_linetype_manual(name = 'line', values = 1,
guide = guide_legend(aes = list(color = "#00b700")))
})
}
# Run the application
shinyApp(ui = ui, server = server)
The problem is not shiny nor ggplot2. The problem is the conversion of a ggplot2 object into a plotly object.
Below I've isolated the ggplot steps from the plotly step and completely removed shiny from the picture.
p <- ggplot2::mpg %>%
ggplot() +
geom_point(aes(x = displ, y = hwy, color = class))
facet <- p + facet_wrap(~year)
final <- facet + geom_hline(aes(yintercept = 20, linetype = 'hline20'), color = '#00b700') +
scale_linetype_manual(name = 'line', values = 1, guide = guide_legend(aes = list(color = "#00b700")))
print(final)
The above displays fine.
ggplotly(final)
This above has the same display errors as yours, without involving shiny.
Legend issues and other display issues are common when converting ggplot2 objects to plotly objects. Plotly and ggplot2 are completely independent plotting frameworks with their own syntax and graphics objects. Plotly provides conversion function methods but things still get lost in translation from one format to the other, because there is not a complete equivalency between them.
I'd recommend trying to implement your plot in native plotly syntax instead of trying to convert it from ggplot2.
Related
I have a bar chart that I want to make interactive in my R Shiny app using plotly.
When it is rendered as a plot, everything is fine using ggplot:
#Bar plots
ggplot(data = df_continents) +
geom_bar(aes(x=country, y=coal_co2), stat="identity", fill="#2596be") +
scale_y_continuous(labels = number_format())`
But, when I try to use plotly, the format gets messed up in an incredible way:
#Bar chart - Adding Labels
ticklabels <- seq(from=0, to=round(max(df$coal_co2*100000)), by=100000)
ticktexts <- c(0,paste(ticklabels[-1]/1000, " 000", sep=""))
output$bar <- renderPlotly({
df %>%
plot_ly(x =~ country, y = ~ coal_co2, type = "bar", marker = list(color = "#2596be")) %>%
layout(yaxis=list(tickvals = ticklabels,
ticktext = ticktexts
))
})
So, I'm not sure what is the problem here, why do I have those white horizontal lines inside the bars?. How do I get my bar chart plot to look like the first screenshot?.
I am working on creating an interactive line graph using ggplot in R shiny. The way I am doing it is having the user in the UI select the values they want to see in the plot using a picker input. In the server the data is then filtered based on the selection from the user. I specified the x axis in ggplot using scale_x_continuous. I set a sequence to be 0 through 24 with breaks by 1. However when a user would select, say 1-10, the x-axis would change to only show 1-10.
I want the x-axis to remain 0 through 24 no matter what the user selects. Is there a way to do that? Would the solution be in specifying the ggplot x-axis limits in a different way limits or in how I am using the picker input to filter the data?
Thanks!
Here is my code if it helps:
library(shiny)
library(tidyverse)
library(shinyWidgets)
# Create sample dataset and name bin
set.seed(1234)
hour <- sample(1:24, size=100, replace=TRUE)
calls <- sample(1:55, size=100, replace =TRUE)
mydata <- data.frame(hour,calls)
name <- mydata %>%
group_by(hour) %>%
summarize(n())
name_bin <- as.data.frame(name$hour)
ui <- fluidPage(
h1 ("R shiny ggplot Question"),
pickerInput(
inputId = "myPicker",
label = "Select Hour in the day",
choices = name_bin,
options = list(
`actions-box` = TRUE,
size = 10,
`selected-text-format` = "count > 3"),
multiple = TRUE),
box(
width = 11,
plotOutput("graph1"))
)
server <- function(input,output,session) {
output$graph1 <- renderPlot({
g1 <- dplyr::filter(mydata,hour %in% input$myPicker)
g2 <- g1 %>%
group_by(hour) %>%
summarize(number = n())
ggplot(g2, aes(x=hour, y=number)) +
geom_line(color = 'darkblue') + geom_point() +
scale_x_continuous(breaks = seq(0,24, by=1)) + ###### Better way to set x-limits?
scale_y_continuous(breaks = seq(0, max(g2$number), by=5))+
theme_minimal()+
labs(y="Number of Calls", x="Hour in the day",title = "")
})
}
shinyApp(ui, server)
There are a few ways to set the limits on your axis: you were almost there!
The call to scale_x_continuous in your renderPlot() function only sets the breaks in the axis (kind of how it's labeled). You want to set the limits, and you can do that within the scale_x_continuous function via the argument limits=. See the documentation for more information, but this should work for you:
scale_x_continuous(breaks = seq(0,24, by=1), limits = c(0,24))
Alternatively, if you just want to set the limits, but the default "breaks" in the axis are fine, you can access x and y limits more easily using xlim(0,24) in place of scale_x_continuous.
Use caution though: setting limits of the axis will result in dropping that data - meaning it won't be used in any further stat functions. If you still need to keep that data for other stat functions within the plot, you can use coord_cartesian() (see the documentation here).
I have a script using ggplotly to produce a couple of interactive charts. I then try to produce addition charts that are not interactive using ggplot. They refuse to plot even if I introduce Sys.sleep() pauses.
Is there a reason why one cannot mix the interactive Javescript ggplotly plots with non-interactive ggplot plots in the same script? I cannot find anything answers regarding this question.
Update: Here is a mini-version of the code I am using. Actually, it doesn't work in RStudio. The second plot appears to write on top of the first one. Whatever plot is created last appears to overwrite the previous plot. If I remove the call to 'ggplotly' and just print the ggplot construction, all is well. It has something to do with the call to ggplotly.Conversely, if I use ggplotly for both charts, all is well. Seems they don't mix.
library("ggplot2")
library("plotly")
test_data <- data.frame(A = c(1,5,7,4,2),
B = c(3,3,6,8,4),
C = c(6,2,9,4,5))
my_dates <- as.Date(c("2010-01-01", "2010-02-01",
"2010-03-01", "2010- 4-01",
"2010-05-01"))
xts_data <- xts(test_data, order.by = my_dates)
p <- autoplot(xts_data, facets = NULL) +
guides(color = guide_legend(override.aes = list(size = 2))) +
geom_line(size = 1)
print(ggplotly(p))
new_df <- data.frame(P = c(70, 70, 70),
Category = c("A", "B", "C"),
Value = c(5, 15, 10))
p <- ggplot(data = new_df, aes(
x = Category, y = Value)) +
geom_bar(position = position_dodge(), stat = "identity")
print(p)
The "problem" I was having is the ggplot chart is displayed in the Plot pane and the ggplotly charts are displayed in the Viewer pane. Problem solved.
thank you in advance for the help.
I am trying to use plotly within a shiny app I have. I am a bit new to plotly so I apologize if this is a no brainer. I would like to use a scatterplot that paints each point a different color based on input$Col, then for each group within input$Col I would like to draw a smoothed line for each color. Everything works fine except for the fact that when I use add_lines() it just draws one line, and does not differentiate for the different colors that are on the scatterplot.
plot_ly(poolfinderdata1(), type = "scatter", x = ~get(input$X),
y = ~get(input$Y),
mode = "markers",
color = ~get(input$Col),
symbol = as.factor(poolfinderdata1()$Matcher))%>%
add_lines(y = ~fitted(loess(get(input$Y) ~ get(input$X)),
color ~ get(input$Col)))%>%
layout(xaxis =list(title= input$X), yaxis = list(title = input$Y))
ggplot2 has been around for a long time so it already has a bunch of stuff you can use and I think learning it it's worth the effort, specially since you can turn your plots interactive with the ggplotly function. Here's one way to solve your problem:
library(plotly)
library(ggplot2)
data <- poolfinderdata1()
data[[input$Col]] <- as.factor(data[[input$Col]]) # so the color is mapped as discrete
data$Matcher <- as.factor(data$Matcher) # same for the markers
p <- ggplot(data, aes_string(x = input$X, y = input$Y, color = input$Col)) +
geom_point(aes(shape = Matcher)) +
geom_smooth(method = "loess")
ggplotly(p)
Hope this helps.
I just installed the latest plotly R package (devtools::install_github("ropensci/plotly")).
I'm trying to generate a violin plot for a single variable and I would like to suppress the x-axis label.
I tried:
library(dplyr)
library(plotly)
df <- read.csv("https://raw.githubusercontent.com/plotly/datasets/master/violin_data.csv")
plot_ly(y =~ df$total_bill,type = 'violin',
box = list(visible = T),
meanline = list(visible = T)) %>%
layout(xaxis = list(title = ""),yaxis = list(title = "Total Bill",zeroline = F))
But I'm getting "trace 0" as the x-axis label:
I tried playing around with the x0 parameter but couldn't get a violin with no x-axis label.
Any idea?
Here's an example using ggplot2 + ggplotly:
library(dplyr)
library(plotly)
librart(ggplot2)
df <- read.csv("https://raw.githubusercontent.com/plotly/datasets/master/violin_data.csv")
# Generate a ggplot with a violin plot and a boxplot
vioplot <- ggplot(df, aes(x = "", y=total_bill)) +
geom_violin(fill = "blue", alpha = 0.3) +
geom_boxplot(fill = "blue", alpha = 0.3) +
xlab("") + ylab("Total bill")
# Render the ggplot as a plotly object using ggplotly()
ggplotly(vioplot)
Here is the resulting plotly
P.S. I wan't able to reproduce your plot using plot_ly(). I Got an error "Error: Trace type must be one of the following:...". Anyway I'm not a big fan of the plot_ly() way. I always go first through a ggplot.