0

I am developing a shiny application to visualize earthquakes better. I have got two attributes which are depth and magnitude and want to draw 3 different plots according to only depth, only magnitude and selection of both. However I can not select the case with multiple inputs by using if statement. How can I do this? Thanks in advance

Here is the data and the code.

 structure(list(latitude = c(39.597, 39.2815, 40.6823, 40.427, 
 39.0462, 40.854), longitude = c(34.3363, 40.2353, 36.6918, 26.2398, 
 41.4552, 27.9235), depth = c(8.6, 5, 13.7, 7.2, 12.9, 14.9), 
  magnitude = c(5.2, 5.5, 5.1, 5.1, 5.1, 5.1), time = structure(c(-7304, 
-7271, -7067, -7059, -6974, -6716), class = "Date")), .Names = 
 c("latitude", 
 "longitude", "depth", "magnitude", "time"), row.names = c(NA, 
  6L), class = "data.frame")
library(shiny)
library(sp)
library(aspace)

 ui <- fluidPage(headerPanel("Earthquakes"),
  dateRangeInput(inputId = "time","Date range:",format = "yyyy-mm-dd",min=min(turkat$time),max = max(turkat$time),start=min(turkat$time),end=max(turkat$time),separator="-" ),
            sidebarPanel(
              selectInput("att", "Select an attribute", choices=c("depth","magnitude"),selected="magnitude",multiple=TRUE,selectize=TRUE)),
            mainPanel(plotOutput("map1"))


 )
 server <- function(input, output) {


 myturkat <- reactive({
  turkat[turkat$time>=input$time[1]&turkat$time<=input$time[2],]
 })
   clr<-reactive({as.factor(cut(myturkat()$depth,breaks=c(0,20,40,60,Inf)))        })
  mag<-reactive({as.factor(cut(myturkat()$magnitude,breaks= seq(floor(min(myturkat()$magnitude)),ceiling(max(myturkat()$magnitude)))),include.lowest=TRUE)
  })



 output$map1 <- 
    renderPlot({ if (is.null(input$att)){ warning("select at least one attribute"); return(NULL)}


     else if(input$att=="magnitude"){
    req(myturkat())
    par(mar=c(5.1, 4.1, 3.1, 2.1))
     plot(turkiye, axes=TRUE,ylim=c(38,42),xlim=c(26,42))  
     points(myturkat()$longitude,myturkat()$latitude,pch=1,cex=myturkat()[,input$att]-(min(myturkat()[,input$att])-1),col="blue",lwd=1.2)
     }
      else if(input$att=="depth"){
       req(myturkat())
      par(mar=c(5.1, 4.1, 3.1, 2.1))
      plot(turkiye, axes=TRUE,ylim=c(38,42),xlim=c(26,42))  
      points(myturkat()$longitude,myturkat()$latitude,pch=16,cex=1.2,col=clr())
      lev<-levels(clr())
       legend("topright",lev,col=palette(),pch=16,title="depth (km)",pt.cex=1.2)}

     else if(input$att=="depth" && input$att=="magnitude") { 
     {req(myturkat())
       grup<-split(myturkat(),mag)
       par(mar=c(5.1, 4.1, 3.1, 2.1))
       plot(turkiye, axes=TRUE,ylim=c(38,42),xlim=c(26,42))
       for (i in 1: length(levels(mag)))
       {
         points(grup[[i]]$longitude,grup[[i]]$latitude,pch=i,cex=1,col=black)}
     }}}
 )
 }

      shinyApp(ui = ui, server = server)

program gave this error.

  Listening on http://127.0.0.1:3066
  Warning in renderPlot(...) : select at least one attribute
  Warning in if (input$att == "magnitude") { :
  the condition has length > 1 and only the first element will be used
  Warning in if (input$att == "depth") { :
  the condition has length > 1 and only the first element will be used
Cengover
  • 89
  • 13

1 Answers1

2

input$att is a vector with potentially two elements, but you're asking if it's equal to a vector of one element. replace the == with %in% (and switch the order):

if ("magnitude" %in% input$att & "depth" %in% input$app) ...

An alternative, probably better solution would be to replace the equal sign with identical, which isn't vectorized:

if(identical(input$att,"magnitude")) {...}
else if(identical(input$att,"depth")) {...}
else if (identical(input$att, c("magnitude", "depth") | identical(input$att, c("depth","magnitude")) {...}
iod
  • 7,412
  • 2
  • 17
  • 36
  • Thanks for the answer. however I still get the same error for multiple input case with if . `Warning in if (length(input$att) == 1 & input$att == "magnitude") { : the condition has length > 1 and only the first element will be used Warning in if (length(input$att) == 1 & input$att == "depth") { : the condition has length > 1 and only the first element will be used` – Cengover Dec 21 '18 at 11:57
  • I also thought the nested ifs thanks again. Will try asap and comment again. – Cengover Dec 21 '18 at 13:47
  • See the (again) revised answer - I believe using `identical` instead of `==` will be a better solution. – iod Dec 21 '18 at 13:48
  • thank you @iod this solves the problem. if did not work for controlling two vectors. the second suggestion did work. the first one still gave the same error. You made my day . I need to learn use pipes in R., had better. the code is getting too complex as you see. any advices? – Cengover Dec 22 '18 at 12:27
  • Glad I could help. Don't forget to upvote and accept! I would also recommend that you look into ggplot2 rather than the base plot, to give you more options. Hard to give specific advice without more info, but try to rethink your data structure so you can just use the user input directly in your call (say, as a filter) rather than build different calls for each input. – iod Dec 22 '18 at 12:45
  • Both done . The last suggestion I did not quite get it. Want to use Google api as a base map may be. It is much more understandable and visible with basic plot setting for now. I may upgrade it later on with use of ggmap and ggplot. Thanks a lot. – Cengover Dec 22 '18 at 13:26