Problemet er den måde, forespørgslen er opbygget på, når du kun vælger én element og brug IN
operatør. dplyr
oversættelse til SQL
tilføjer ikke den rigtige parentes og fejler derfor. Dette spørgsmål blev diskuteret indgående her
.
En måde at omgå dette på er at sende en anden instruktion til filter()
når length
af input er lig med 1 (se eksempel nedenfor).
Her er, hvad der sker:
tbl(mydb, "iris") %>%
filter(Species %in% c("setosa", "versicolor")) %>%
.$query
Giver den korrekte SQL
forespørgselssyntaks:
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" IN ('setosa', 'versicolor')
<PostgreSQLConnection>
Og, hvis den udføres, giver den forventede:
#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
#.. ... ... ... ... ...
Lad os se, hvad der sker, hvis du prøver at sende et enkelt element:
tbl(mydb, "iris") %>%
filter(Species %in% "setosa") %>%
.$query
Forespørgslen vil være:
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" IN 'setosa'
<PostgreSQLConnection>
Hvilket, hvis det udføres, vil resultere i følgende fejl:
Det er fordi for et enkelt element, dplyr
oversættelse til SQL
forespørgslen tilføjer ikke den rigtige parentes. Læg mærke til, hvordan det er 'setosa'
i stedet for ('setosa')
.
For at omgå det kan vi gøre:
if(length(input$Species) == 1) {
tbl(mydb, "iris") %>%
filter(Species == input$Species) %>%
}
Hvilket vil bygge en syntaktisk gyldig SQL
forespørgsel:
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" = 'setosa'
<PostgreSQLConnection>
Følgende eksempel løser dette problem. Her instruerer jeg blot appen til at bestå filter(Species == ...)
hvis input$Species
er af length
1 og filter(Species %in% ...)
Ellers.
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)