PD1
PD1

Reputation: 53

Dynamic filter, Add legend in ggvis and plot discrete X axis

I'm new in RShiny however have a little experience in R. I have just started working on R shiny and trying to prepare a simple two quantity linechart versus week on X axis. As its more presentable, I've used a csv upload feature and dynamically selecting the value to be populated on the UI. The sample CSV data that I'm using is as follows:

year-week   Group   big small   Time
1415          G1    10     5    1
1416          G1    20     6    2
1429          G1    15     4    3
1530          G1    17     5    4
1535          G1    20     7    5
1601          G1    13     6    6
1606          G1    12     5    7
1410          G2    9      3    1
1415          G2    11     4    2
1439          G2    13     5    3
1529          G2    15     6    4
1531          G2    15     4    5
1610          G2    12     5    6
1615          G2    19     6    7
1412          G3    9     10    1
1417          G3    20     6    2
1452          G3    13     5    3
1501          G3    10     4    4
1530          G3    17     7    5
1620          G3    16     5    6

My main objective is:

1) Select a CSV and upload it (It's working)

2)Take week on x axis (it's working with a small work around. Since I have year week and it's discrete value like 1415 which means 2014,15th week and then 1420 which means same year 20th week, then is 1515 that is for 2015, week 15th and so on. I wanted to plot it as is but on x axis, it's plotting a continuous week number. So, as a work around I just made a column for sequential weeks as time. Any hints on how to use the year week column as is and not as a continuous function on X axis is much appreciated.)

3) Select two dynamic axis and then plot them as line charts on Y axis with different colours (it's working)

4) Add label for the two lines added on Y. (It's not working. As the two plotted lines aren't a part of factor, but are two different columns getting selected dynamically, I'm unable to plot legend to explain which colour corresponds to which line. Require help on this).

5) Then the last part is that I want to include a dynamic filter for group number. (It's not working and need help on this) I tried putting selectinput drop down in UI but not sure how to map it to the selected CSV file in server.R .I can't directly put values since there are 100's of rows corresponding to one group and there are multiple groups. However, I know that only one column requires that filter and only that column's filter shall show the line charts but just little confused on how to enter that part. I've gone through many articles and questions but did not get a similar situation in which other fields are getting dynamically selected.

Following is the code and it's working for one group, taking week sequence as work around inspite of year-week, because year week is till 52 only and it treats gaps in between 1452 & 1501. So I require help on the legend part and the code to filter the groups so it can run on all the data together.

Following is the code I've worked till now:

UI.R

library(ggvis)
library(shiny)
shinyUI(pageWithSidebar(
  div(),
  sidebarPanel(
    fileInput('datfile', ''),
    selectInput('x', 'x:' ,'x'),
    selectInput('y', 'y:', 'y'),
    selectInput('z', 'z:', 'z'),
    ######### Need to choose one of the following 2 methods for filtering ########
    #1#
    #selectInput("w", label = h3("Filter group"),
    #            ("Group" = "Group"),selected = "Group"),
    ############################## OR ###################################             
    # 2# To make a select box 
    selectInput("select", label = h3("Filter Group"), 
               choices = list("G1" = 1, "G2" = 2, "G3" = 3), 
                selected = 1),
    ######################################################################
    hr(),
    fluidRow(column(3, verbatimTextOutput("value"))),
    uiOutput("plot_ui")

  ),
  mainPanel(
    ggvisOutput("plot")
  )
))

Server.R

library(shiny)
library(dplyr)
library(ggvis)

shinyServer(function(input, output, session) {
  #load the data when the user inputs a file
  theData <- reactive({
    infile <- input$datfile        
    if(is.null(infile))
      return(NULL)        
    d <- read.csv(infile$datapath, header = T)
    d        
  })

  # dynamic variable names
  observe({
    data<-theData()
    updateSelectInput(session, 'x', choices = names(data))
    updateSelectInput(session, 'y', choices = names(data))
    updateSelectInput(session, 'z', choices = names(data))
  }) # end observe

  #gets the y variable name, will be used to change the plot legends
  yVarName<-reactive({
    input$y
  })

  #gets the x variable name, will be used to change the plot legends
  xVarName<-reactive({
    input$x
  })

  #gets the z variable name, will be used to change the plot legends
  zVarName<-reactive({
    input$z
  })

  #make the filteredData frame

  filteredData<-reactive({
    data<-isolate(theData())
    #if there is no input, make a dummy dataframe
    if(input$x=="x" && input$y=="y" && input$z=="z"){
      if(is.null(data)){
        data<-data.frame(x=0,y=0,z=0)
      }
    }else{
      data<-data[,c(input$x,input$y,input$z)]    # Here data shall be filtered   
      names(data)<-c("x","y","z")
    }
    data
  })

  #plot the ggvis plot in a reactive block so that it changes with filteredData
  vis<-reactive({
    plotData<-filteredData()

    plotData %>%
      ggvis(~x, ~y) %>%
      #ggvis(~x, ~y, storke = c(~y,~z)) %>%   # It's not working & not picking y&z together
      #set_options(duration=0) %>%
      layer_paths(stroke := "darkblue", fill := NA) %>%
      layer_paths(x = ~x, y = ~z, stroke := "orangered", fill := NA) %>%
      add_axis("y", title = "Big v/s small") %>%
      add_axis("x", title = xVarName()) %>%
      #add_legend('stroke', orient="left") %>%   # Unable to put the legend
      add_tooltip(function(df) format(sqrt(df$x),digits=2))
  })
  vis%>%bind_shiny("plot", "plot_ui")

})

Any help is much appreciated. It may not be that tough and I've done a similar part in R by using dplyr for subset and filter but not sure how to map the same here. If anything above is unclear or require more info, please let me know. If the solution is better by loading the CVS directly or using plot inspite of ggvis, then also I'm ok to change the code piece but want to meet my objective.

Upvotes: 0

Views: 408

Answers (1)

PD1
PD1

Reputation: 53

UI.R

library(ggvis)
library(shiny)
shinyUI( fluidPage ( (img(src="picture.jpg")),
  theme = "bootstrap.css",
  fluidRow( 
    #headerPanel(title=div(img(src="picture.jpg"))),
      column(9, align="center", offset = 2,
           textInput("string", label="",value = "Big V/s Small"),
           tags$style(type="text/css", "#string { height: 50px; width: 100%; text-align:center; font-size: 26px;}")
    )
  ),
  pageWithSidebar(
    div(),
    sidebarPanel(
      fileInput('datfile', ''),
      selectInput('x', 'x:' ,'x'),
      selectInput('y', 'y:', 'y'),
      selectInput('z', 'z:', 'z'),
      ################ Need to choose one of the following method for filtering ############
      # To make a select box 
      selectInput("w", label = h3("Filter Group"), 
                  choices = list()),
      ######################################################################
      hr(),
      fluidRow(column(3, verbatimTextOutput("value"))),
      uiOutput("plot_ui")

    ),
    mainPanel(
      ggvisOutput("plot")
    )
  ))
)

Sevrer.R

#install.packages('rsconnect')
#install.packages('bitops')
library(shiny)
library(dplyr)
library(ggvis)
library(reshape2)

shinyServer(function(input, output, session) {
  #load the data when the user inputs a file
  theData <- reactive({
    infile <- input$datfile
    if (is.null(infile))
      return(NULL)
    d <-
      read.csv(infile$datapath,
               header = T,
               stringsAsFactors = FALSE)
    d
  })

  # dynamic variable names
  observe({
    data <- theData()
    updateSelectInput(session, 'x', choices = names(data))
    updateSelectInput(session, 'y', choices = names(data))
    updateSelectInput(session, 'z', choices = names(data))
    updateSelectInput(session, 'w', choices = unique(data$group))
  }) # end observe

  #gets the y variable name, will be used to change the plot legends
  yVarName <- reactive({
    input$y
  })

  #gets the x variable name, will be used to change the plot legends
  xVarName <- reactive({
    input$x
  })

  #gets the z variable name, will be used to change the plot legends
  zVarName <- reactive({
    input$z
  })

  #gets the w variable name, will be used to change the plot legends
  wVarName <- reactive({
    input$w
  })

  #make the filteredData frame

  filteredData <- reactive({
    data <- isolate(theData())
    #if there is no input, make a dummy dataframe
    if (input$x == "x" && input$y == "y" && input$z == "z") {
      if (is.null(data)) {
        data <- data.frame(x = 0, y = 0, z = 0)
      }
    } else{
      data = data[which(data$fineline_nbr == input$w), ]
      data <- data[, c(input$x, input$y, input$z)]
      names(data) <- c('x', input$y, input$z)
    }
    data
  })

  #plot the ggvis plot in a reactive block so that it changes with filteredData
  vis <- reactive({
    plotData <- filteredData()
    plotData <- melt(plotData, id.vars = c('x'))
    print(names(plotData))
    plotData %>% ggvis(x =  ~ x,
                       y =  ~ value,
                       stroke =  ~ variable) %>% layer_lines()
  })
  vis %>% bind_shiny("plot", "plot_ui")
})

Upvotes: 1

Related Questions