micstr micstr - 1 month ago 10
R Question

Shiny reactive dropdown misbehaving (with number inputs)

This is a mockup of a summary block that shows the Top or Bottom 10 of a value that is being plotted elsewhere.

ISSUE

Changing the variable name or sort direction is working fine, but changing the limit (

limit1
) of how much data to show, works initially showing 10 but changing it to less like 5 ends up showing all the data. Changing to higher values sometimes works but not always. It is very weird!

So OK

Deafult app on startup

Not OK

App when choose 5

CODE

library(shiny)
library(data.table)

dataset1 <- as.data.table(iris)

server <- function(input, output) {
# Top table
datatop1 <- reactive({

dt <- copy(dataset1)
setorderv(dt,input$t1, input$sort1) # -1 is descending

# choose subset of rows
row.limit <- min(nrow(dataset1), input$limit1)
dt <- dt[1:row.limit, ]

# choose columns
dt <- dt[, .(Species, get(input$t1))]
setnames(dt,"V2",input$t1)

return(dt)
})

output$top1 <- renderUI({
if(!is.null(dataset1)) {

fluidRow(inputPanel(
selectInput("limit1", "Limit:",
c("5", "10", "15", "20", "25", "50"),
selected = "10"),
selectInput(("t1"), "Variable:", choices = names(dataset1),
selected = "Sepal.Length"),
selectInput("sort1", "Sort by:",
choices = c('Bottom / Asc.' = +1 , 'Top / Desc.' = -1),
selected = -1)
))
}
})


# Top panel
output$screenTop1 <- renderTable({
# top dataset is in reactive as function
datatop1()
})
output$screenTop <- renderUI({
tagList(
uiOutput("top1"),
uiOutput("screenTop1")
)
})
}

ui <- shinyUI(
fluidPage(tabPanel("Top", uiOutput("screenTop"))
)
)

shinyApp(ui=ui, server = server)


Is it a problem with the subsetting of the
data.table
? Or the way I am using reactive? Shiny experts - I would appreciate a steer on what I am doing wrong, and why as I have not fully grasped reactivity yet. Apologies the code is a bit convoluted as the main code is inside a different file structure.

> sessionInfo()
R version 3.2.4 Revised (2016-03-16 r70336)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

locale:
[1] LC_COLLATE=English_United Kingdom.1252 LC_CTYPE=English_United Kingdom.1252
[3] LC_MONETARY=English_United Kingdom.1252 LC_NUMERIC=C
[5] LC_TIME=English_United Kingdom.1252

attached base packages:
[1] stats graphics grDevices utils datasets methods base

other attached packages:
[1] data.table_1.9.6 shiny_0.13.2


EDIT: Explanation

@Pork Chop's great comments below explains that
min
can end up coercing all to character. So when faced with 226 and "5" it became a test of "226 " and "5" and on an element by element basis "2" beats "5" so "226" was chosen as minimum and all rows where shown.

But for 10 and 20 it was not e.g. "226" and "10" first digit 1<2. And correct minimum was shown. Lesson: watch type and make sure you set SelectInput input$vars to
as.numeric
when needed.


Mystery explained!

Answer

Update your subset with:

row.limit <- min(nrow(dataset1), as.numeric(input$limit1))

Edit:

1) As min needs a numeric variable to compute the min properly you need to cast to correct data type: as.numeric(input$limit1), otherwise it will take the other numeric variables

2) By default the selectinput is of type string, as selectInput() and selectizeInput() use the JavaScript library selectize.js

3) If you read selectize documentation you will find that "Selectize is instantiated from a <input type="text"> element"

Going forward in your development I would suggest you to use validate and need as much as possible, you can find some documentation here. Also try to use print as much as you can

To clarify taking a min of character strings:

If you type ?min you will find that for character string the evaluation is follows:

  • If a one string is present in the collection it will coerce the entire set to type character
  • When taking min the sorting for character strings is done using Lexicographical order, meaning the alphabetical order, this means that if you take min(c("10",2)), it will return "10" as 1 comes before 2 once 2 is coerced into the character string
Comments