I am using Shiny and ggplot2 for an interactive graph. I also used "plot1_click" to get x and y locations.
output$selected <- renderText({
paste0("Value=", input$plot1_click$x, "\n",
"Names=", input$plot1_click$y) }) #how to get names???
This is part of server code. Here what I want is, instead of printing the "y" coordinates, I want to print the corresponding name written in y-axis. Is there any possible way for it??
As far as I know clicking points is not supported in plotOutput. Click events will only return coordinates of the click location. Those coordinates can however be used to figure out the nearest point.
This shiny app from the shiny gallery pages uses the function shiny::nearPoints which does exactly that. Here is a minimal example.
library(shiny)
library(ggplot2)
shinyApp(
fluidPage(
plotOutput("plot", click = "plot_click"),
verbatimTextOutput('print')
),
server = function(input, output, session){
output$plot <- renderPlot({ggplot(mtcars, aes(wt, mpg)) + geom_point()})
output$print = renderPrint({
nearPoints(
mtcars, # the plotting data
input$plot_click, # input variable to get the x/y coordinates from
maxpoints = 1, # only show the single nearest point
threshold = 1000 # basically a search radius. set this big enough
# to show at least one point per click
)
})
}
)
The verbatimTextOutput shows you the nearest point to the clicked location. Notice that nearPoints only works with ggplots like that. But the help page suggests that there is also a way to use this with base graphics.
Related
My app that i built outputs the coordinates of the clicked point but my objective is to output the coordinates of the plotted point and that is by printing out the real correspendent coordinates existing on the x axis .This is the first part of the post i want to resolve, then if it is done then we will deal with the fact that my app deals with an x axis of a date nature then we will plot another plot, instaed of the actual, which in fact based on filtering the data based on that date .But now i want to get using the code below the abscisse which is written on the x axis and not that numerical delivered but R shiny:
library(ggplot2)
library(shiny)
library(shiny)
df<-data.frame("pr"=c("a","n","z","o"),"value"=c(5,1,13,9))
ui <- basicPage(
plotOutput("plot1", click = "plot_click"),
verbatimTextOutput("info")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
plot(as,factor(df$pr ), df$value)
})
output$info <- renderText({
paste0("x=", input$plot_click$x, "\ny=", input$plot_click$y)
})
}
shinyApp(ui, server)
By the way who can disply the points in form of points and not in form of bars or bold lines like in my example so please do it .i will be thankful.
I am using Shiny in R to make two different tabs.
I think one tab would be a good idea to make a summary tab and another one is for the plot.
I want to give user a selection of x, y and color section... When I finished the part of ggplot section, the plot is not shown as I expected.
Please help me out where I made up mistake and please help me to understand of it.
Thank you.
# ui.R
library(shiny)
library(ggplot2)
library(plyr)
library(dplyr)
data(mtcars)
new_mtcars <- mtcars %>%
select(wt,mpg,cyl,vs,am,gear,carb)
# Define UI for an application that draws a histogram
shinyUI(fluidPage(
# Application title
titlePanel("prac"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("xvalue","Please Choose X Value : ", c("wt","mpg")),
selectInput("yvalue","Please Choose Y Value : ", c("wt","mpg")),
selectInput("color","Please Choose color Value : ", choices = c("cyl","vs","am","gear","carb"))
),
mainPanel(
tabsetPanel(#tabPanel("Information",tableOutput("info")),
tabPanel("Summary",tableOutput("summary")),
tabPanel("Comparison",plotOutput("plot")))
)
)
# Show a plot of the generated distribution
))
library(shiny)
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
df_sub <- reactive({
new_mtcars[,c(input$xvalue,input$yvalue,input$color)]
})
output$plot <- renderPlot({
category <- input$color
ggplot(df_sub(), aes(input$xvalue,input$yvalue)) +
geom_point(aes_(color = as.name(category)),size = 3) +
geom_smooth(method = "lm")
})
})
The issue is that input$xvalue and input$yvalue are characters. To tell ggplot that it should look for variables with these names in your dataset
use .data[[input$xvalue]] and .data[[input$yvalue]] inside aes() or
use aes_string instead of aes().
So for example suppose I have these three plots
p1 <- iris%>%ggplot(aes(x=Sepal.Length,y=Sepal.Width))+geom_point()
p2 <- iris%>%ggplot(aes(x=Sepal.Length,y=Sepal.Width))+geom_bar(stat="identity", width = 1, fill="#98ff98")
p3 <- iris%>%ggplot(aes(x=Species,y=Sepal.Width))+geom_bar(stat="identity", width = 1, fill="blue")
So instead printing each plot out separately in the html markdown so that the user has to scroll down to view each of the figures, is there a way to output some sort of ui where the left hand side is the plot and right hand side are the selection for the plots. Then the user can simply select which plot to view and it will appear on the left. Is this possible? The reason why I ask is because often I can have 10-20 figures per comparison that can get unwieldy very fast and I think this would be an excellent way to organize them.
thanks!
Maybe something like this can get you started
library(shiny)
# create a list of plots
plots <- list(
p1 = iris%>%ggplot(aes(x=Sepal.Length,y=Sepal.Width))+geom_point(),
p2 = iris%>%ggplot(aes(x=Sepal.Length,y=Sepal.Width))+geom_bar(stat="identity", width = 1, fill="#98ff98"),
p3 = iris%>%ggplot(aes(x=Species,y=Sepal.Width))+geom_bar(stat="identity", width = 1, fill="blue")
)
# put names of plots in a list in sidebar
ui <- fluidPage(sidebarLayout(
sidebarPanel(tags$ul(purrr::map(names(plots), ~tags$li(actionLink(paste0("show", .), .))))),
mainPanel(plotOutput("currentplot"))
))
server <- function(input, output, session) {
# draw the first plot by default
current_plot <- reactiveVal(plots[[1]]);
# set up observers for each of the action links in the UI
purrr::map(names(plots), function(p) {
observeEvent(input[[paste0("show",p)]], {
# set current plot
current_plot(plots[[p]])
})
})
# render whatever the current plot is
output$currentplot <- renderPlot(current_plot())
}
shinyApp(ui, server)
This will give you a list of plots on the left and will draw which ever you click on on the right.
you could probably make this more efficient if you wanted to write some javascript, but this at least gives a basic idea of how it might work.
Reactive expressions in Shiny propagate changes where they need to go. We can suppress some of this behaviour with isolate, but can we suppress changes being propagated based on our own logical expression?
The example I give is a simple scatterplot, and we draw a crosshair with abline where the user clicks. Unfortunately, Shiny considers the result to be a new plot, and our click value is reset to NULL... which in turn is treated as an update to the value to be propagated as usual. The plot is redrawn, and NULL is passed to both arguments of abline.
My hack (commented out below) is to place a condition in the renderPlot call which updates some non-reactive variables for the plotting coordinates, only when the click values are non-NULL. This works fine for trivial plots, but it actually results in the plot being drawn twice.
What's a better way to do this? Is there a correct way?
Server file:
library(shiny)
shinyServer(function (input, output)
{
xclick <- yclick <- NULL
output$plot <- renderPlot({
#if (!is.null(input$click$x)){
xclick <<- input$click$x
yclick <<- input$click$y
#}
plot(1, 1)
abline(v = xclick, h = yclick)
})
})
UI file:
library(shiny)
shinyUI(
basicPage(
plotOutput("plot", click = "click", height = "400px", width = "400px")
)
)
Winston calls this problem "state" accumulation - you want to display not only the current data, but something generated by the previous plot (the best place to learn about this is at https://www.rstudio.com/resources/videos/coordinated-multiple-views-linked-brushing/)
The basic idea is to create your own set of reactive values, and update them when the user clicks on the plot. They won't be invalidated until the next click, so you don't get circular behaviour.
library(shiny)
shinyApp(
shinyUI(basicPage(plotOutput("plot", click = "click"))),
function(input, output) {
click <- reactiveValues(x = NULL, y = NULL)
observeEvent(input$click, {
click$x <- input$click$x
click$y <- input$click$y
})
output$plot <- renderPlot({
plot(1, 1)
abline(v = click$x, h = click$y)
})
}
)
I recently start building shiny app but I got stuck. Please help me.Thank you in advance
I am trying to create a bar chart to show the count for different type of cash and different term. This part, the code went well.
And I also want to create the box plot to show the numeric summary for different variables selected by the user. I created a selectInput called "metric" and then create a reactive called "metric1" in server.R. and then use "metric1" as the variables I selected to create box plot in server.R.
But it keep saying "cannot find the function "metric1". I don't know why it regards "metric1" as a function? it should be a vector-name of the variable selected by the user.
And if I use input$metric in ggplot to create box plot directly, it still say Error: " object 'input' not found". Why cannot find input? I have paste the code below. It is not a long code. And please help me!
library(shiny)
library(ggplot2)
cash <- read.csv("cash 042014-032015.csv")
cash$TERM <- as.numeric(cash$TERM)
shinyServer(function(input, output) {
dataset <- reactive({cash[cash$mapped_name %in% (input$model),]})
metric1 <- reactive({input$metric})
output$caption <- renderText({
input$model
})
output$countPlot <- renderPlot({
p <- ggplot(dataset(), aes(Incentive.Type, fill=factor(Incentive.Type))) + geom_bar()+ facet_grid(~TERM, margins=TRUE)+theme(axis.text.x = element_blank(),axis.ticks=element_blank(),legend.text = element_text(size=20))+guides(fill=guide_legend(title="Incentive Type"),title.theme=element_text(size=30))+scale_x_discrete(limits=c("Standard","Standard+Captive","Standard+Customer","Standard+Captive+Customer","Special","Special+Captive","Special+Customer","Special+Captive+Customer"))
print(p)
})
output$summaryPlot <- renderPlot({
p <- ggplot(dataset(),aes(factor(Incentive.Type), metric1()))+geom_boxplot()
print(p)
})
})
Here is the ui.R
library(shiny)
library(ggplot2)
dataset <- cash
shinyUI(
fluidPage(
# Give the page a title
titlePanel("Incentives by Model"),
# Generate a row with a sidebar
sidebarPanel(
checkboxGroupInput("model", "Select Models:",
choices=c("370Z","Altima","Armada","Crew","Cube","Frontier","GTR","Juke","Leaf",
"Maxima","Murano","NV","Other","Pathfinder","Quest","Rogue","Sentra","Titan","Versa","Xterra"),selected="Altima"),
selectInput("metric","Please select an option below:", choices=c("Dealer Commission Amount"="DLR_COMM_AMT", "Total Monthly Payment"="TOT_MO_PMT","Original Loan Amount"="ORIG_LN_AMT", "Rate"="RATE"),
selected="DLR_COMM_AMT"),
width=2
),
mainPanel(
h3(textOutput("caption", container=span)),
plotOutput("countPlot"),
plotOutput("summaryPlot")
)
))
Try changing metric1() in the second ggplot call to metric1. As in:
p <- ggplot(dataset(),aes(factor(Incentive.Type), metric1))+geom_boxplot()
Actually I think you will have to use something like:
p <- ggplot(dataset(),aes_string(factor("Incentive.Type"), "metric1"))+geom_boxplot()
In order to get it to see the value of your variable metric1 and properly interpret the use of string variables inside of ggplot.