Problemet är hur frågan är konstruerad när du bara väljer en element och använd IN
operatör. dplyr
översättning till SQL
lägger inte till rätt parentes och misslyckas därmed. Den här frågan diskuterades utförligt här
.
Ett sätt att kringgå detta är att skicka en annan instruktion till filter()
när length
av input är lika med 1 (se exempel nedan).
Det här är vad som händer:
tbl(mydb, "iris") %>%
filter(Species %in% c("setosa", "versicolor")) %>%
.$query
Ger rätt SQL
frågesyntax:
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" IN ('setosa', 'versicolor')
<PostgreSQLConnection>
Och, om den körs, ger den förväntade:
#Source: postgres 9.3.13 [[email protected]:5432/csvdump]
#From: iris [100 x 5]
#Filter: Species %in% c("setosa", "versicolor")
#
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# (dbl) (dbl) (dbl) (dbl) (chr)
#1 5.1 3.5 1.4 0.2 setosa
#2 4.9 3.0 1.4 0.2 setosa
#3 4.7 3.2 1.3 0.2 setosa
#4 4.6 3.1 1.5 0.2 setosa
#5 5.0 3.6 1.4 0.2 setosa
#6 5.4 3.9 1.7 0.4 setosa
#7 4.6 3.4 1.4 0.3 setosa
#8 5.0 3.4 1.5 0.2 setosa
#9 4.4 2.9 1.4 0.2 setosa
#10 4.9 3.1 1.5 0.1 setosa
#.. ... ... ... ... ...
Låt se vad som händer om du försöker skicka ett enda element:
tbl(mydb, "iris") %>%
filter(Species %in% "setosa") %>%
.$query
Frågan blir:
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" IN 'setosa'
<PostgreSQLConnection>
Vilket, om det körs, kommer att resultera i följande fel:
Det beror på att för ett enskilt element, dplyr
översättning till SQL
query lägger inte till rätt parentes. Lägg märke till hur det är 'setosa'
istället för ('setosa')
.
För att kringgå det kan vi göra:
if(length(input$Species) == 1) {
tbl(mydb, "iris") %>%
filter(Species == input$Species) %>%
}
Vilket kommer att bygga en syntaktisk giltig SQL
fråga:
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" = 'setosa'
<PostgreSQLConnection>
Följande exempel löser problemet. Här instruerar jag helt enkelt appen att passera filter(Species == ...)
om input$Species
är av length
1 och filter(Species %in% ...)
annat.
ShinyApp
server <- function(input, output) {
selectedQuery <- reactive({
if(length(input$Species) == 1) {
tbl(mydb, "iris") %>%
filter(Species == input$Species) %>%
.$query
}
else(
tbl(mydb, "iris") %>%
filter(Species %in% input$Species) %>%
.$query
)
})
selectedData <- reactive({
if(length(input$Species) == 1) {
tbl(mydb, "iris") %>%
filter(Species == input$Species) %>%
data.frame
}
else(
tbl(mydb, "iris") %>%
filter(Species %in% input$Species) %>%
data.frame
)
})
output$plot <- renderPlot({
ggplot2::qplot(Sepal.Length, Petal.Length, data = selectedData(), color = Species)
})
output$query <- renderPrint({
selectedQuery()
})
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("Species", "Species",
tbl(mydb, "iris") %>%
data.frame %>%
.$Species %>%
unique,
selected = "setosa", multiple = TRUE)
),
mainPanel(
textOutput("query"),
plotOutput("plot")
)
)
)
shinyApp(ui = ui, server = server)