2

I'm trying to reorder the x axis by the values in the y axis. The x axis is a name, the y axis is an integer. Both are reactive, user defined inputs. I have created a datatable that renders in the correct order, but ggplot does not take that order. Instead it does an alphabetical order.

My current code is:

Packages

library(shiny) 
library(readxl) # to load the data into R
library(tidyverse)
library(stringr)
library(DT)
library(tools)
library(magrittr)

Data

lpop <-read.csv("londonpopchange.csv", header=TRUE)

UI

# Define UI for application that plots features of movies
ui <- fluidPage(

  # Sidebar layout with a input and output definitions
  sidebarLayout(

    # Inputs
    sidebarPanel(

      # Select variable for y-axis
      selectInput(inputId = "y", 
                  label = "Y-axis:",
                  choices = c("Mid Year 2016" = "MYE2016", 
                              "Births" = "Births", 
                              "Deaths" = "Deaths",
                              "Births minus Deaths" = "BirthsminusDeaths",
                              "Internal Migration Inflow" = "InternalMigrationInflow", 
                              "Internal Migration Outflow" = "InternalMigrationOutflow",
                              "Internal Migration Net" = "InternalMigrationNet",
                              "International Migration Inflow" = "InternationalMigrationInflow",
                              "International Migration Outflow" = "InternationalMigrationOutflow",
                              "International Migration Net" = "InternationalMigrationNet"),
                  selected = "MYE2016"),

      # Select variable for x-axis
      selectInput(inputId = "x", 
                  label = "X-axis:",
                  choices = c("Borough" = "Name"), 
                  selected = "Name")
    ),

    # Output
    mainPanel(
      h1(textOutput("MainTitle")),
      br(),
      plotOutput(outputId = "geom_bar"),
      DT::dataTableOutput("mytable")
    )
  )
)

Server

# Define server function required to create the scatterplot
server <- function(input, output) {

  #this creates the title
  output$MainTitle <- renderText({ 
    paste(input$y, "for London Boroughs")
  })

  #creates a data table that reacts to the user variable input and arranges
  #by the y variable
  df <- reactive({
    lpop %>%
      select(input$x, input$y, "WF") %>%
      arrange_(.dots = input$y) #%>%
    # setNames(1:2, c("x", "y"))
  })

  #outputs the user defined data frame
  output$mytable = ({DT::renderDataTable({df()})})

  # Create the bar plot object the plotOutput function is expecting
  output$geom_bar <- renderPlot({
    ggplot(data = df(), aes_string(x = input$x, y = input$y, fill = "WF")) +
      geom_bar(stat = "identity") +
      scale_fill_manual(values=c("#000000", "#00D253")) +
      theme(axis.text.x = element_text(angle = 90)) +
      xlab(input$x)
  })
}

# Create a Shiny app object
shinyApp(ui = ui, server = server)

It renders as so: https://jwest.shinyapps.io/ShinyPopulation/

If I use the reorder function in ggplot, it amalgamates all "Names" into one bar, see below.

# Create the bar plot object the plotOutput function is expecting
      output$geom_bar <- renderPlot({
        ggplot(data = df(), aes_string(x = reorder(input$x, input$y), y = input$y, fill = "WF")) +
          geom_bar(stat = "identity") +
          scale_fill_manual(values=c("#000000", "#00D253")) +
          theme(axis.text.x = element_text(angle = 90)) +
          xlab(input$x)
      })
    }

Picture

How can I render it by the Y axis? Is it something to do with scale_x_discrete(limits = ...). If it is I am confused as to how i'm meant to reference the first column of the reactive df

The csv can be downloaded here: https://drive.google.com/file/d/1QLT8CX9XFSx3WU_tADyWgyddHYd3-VSp/view?usp=sharing

DPUT

structure(list(Code = structure(c(7L, 1L, 12L, 13L, 14L), .Label = c("E09000001", 
"E09000002", "E09000003", "E09000004", "E09000005", "E09000006", 
"E09000007", "E09000008", "E09000009", "E09000010", "E09000011", 
"E09000012", "E09000013", "E09000014", "E09000015", "E09000016", 
"E09000017", "E09000018", "E09000019", "E09000020", "E09000021", 
"E09000022", "E09000023", "E09000024", "E09000025", "E09000026", 
"E09000027", "E09000028", "E09000029", "E09000030", "E09000031", 
"E09000032", "E09000033"), class = "factor"), Name = structure(c(6L, 
7L, 12L, 13L, 14L), .Label = c("Barking and Dagenham", "Barnet", 
"Bexley", "Brent", "Bromley", "Camden", "City of London", "Croydon", 
"Ealing", "Enfield", "Greenwich", "Hackney", "Hammersmith and Fulham", 
"Haringey", "Harrow", "Havering", "Hillingdon", "Hounslow", "Islington", 
"Kensington and Chelsea", "Kingston upon Thames", "Lambeth", 
"Lewisham", "Merton", "Newham", "Redbridge", "Richmond upon Thames", 
"Southwark", "Sutton", "Tower Hamlets", "Waltham Forest", "Wandsworth", 
"Westminster"), class = "factor"), Geography = structure(c(1L, 
1L, 1L, 1L, 1L), .Label = "London Borough", class = "factor"), 
    MYE2016 = c(249162L, 7246L, 273239L, 181783L, 272078L), Births = c(2671L, 
    68L, 4405L, 2446L, 3913L), Deaths = c(1180L, 38L, 1168L, 
    895L, 1140L), BirthsminusDeaths = c(1491L, 30L, 3237L, 1551L, 
    2773L), InternalMigrationInflow = c(22189L, 856L, 21271L, 
    19109L, 22469L), InternalMigrationOutflow = c(25132L, 792L, 
    23324L, 20488L, 29113L), InternalMigrationNet = c(-2943L, 
    64L, -2053L, -1379L, -6644L), InternationalMigrationInflow = c(11815L, 
    756L, 5054L, 5333L, 7480L), InternationalMigrationOutflow = c(6140L, 
    441L, 3534L, 4336L, 4460L), InternationalMigrationNet = c(5675L, 
    315L, 1520L, 997L, 3020L), Other = c(-24L, -1L, -14L, 46L, 
    -3L), Estimated.Population..mid.2017 = c(253361L, 7654L, 
    275929L, 182998L, 271224L), WF = structure(c(1L, 1L, 1L, 
    1L, 1L), .Label = c("London Borough", "Waltham Forest"), class = "factor")), .Names = c("Code", 
"Name", "Geography", "MYE2016", "Births", "Deaths", "BirthsminusDeaths", 
"InternalMigrationInflow", "InternalMigrationOutflow", "InternalMigrationNet", 
"InternationalMigrationInflow", "InternationalMigrationOutflow", 
"InternationalMigrationNet", "Other", "Estimated.Population..mid.2017", 
"WF"), row.names = c(NA, 5L), class = "data.frame")
aosmith
  • 34,856
  • 9
  • 84
  • 118
  • 1
    I think the problem is that you reorder the string "Name" by the string input given in `input$y` and thus your x-axis is only the string "Name" and note the actual values. Would be easier to help if you provide a _minimal_ reproducible example and share some sample data. – kath Aug 30 '18 at 15:19
  • I thought the same, but cannot think of a way to sort the values of "Name" rather than what appears to be just the column title. I have attached the csv now – Jonathan West Aug 30 '18 at 15:33
  • 1
    I think you need to set the order of your factors, which you can do when you make your reactive `df`. Since you put `df` in the order you want, you can use something like `forcats::fct_inorder` to set the factor levels in the order they appear (maybe do this in `mutate_at()` to easily work with string inputs). – aosmith Aug 30 '18 at 16:07
  • I've been trying for a bit to come up with something, but haven't been able to. [This answer](https://stackoverflow.com/questions/50402737/why-isnt-bar-plot-updating-based-on-reactive-data-frame) may be of some use, but it's not reactive with axis inputs. – Anonymous coward Aug 30 '18 at 17:25
  • I've looked at both solutions and struggling to make something that works – Jonathan West Aug 31 '18 at 09:02

0 Answers0