Le problème est la façon dont la requête est construite lorsque vous n'en sélectionnez qu'un un élément et utilisez le IN
opérateur. Le dplyr
traduction en SQL
n'ajoute pas la parenthèse appropriée et échoue donc. Ce problème a été longuement discuté ici
.
Une façon de contourner ce problème est de passer une instruction différente à filter()
quand length
d'entrée est égal à 1 (voir exemple ci-dessous).
Voici ce qui se passe :
tbl(mydb, "iris") %>%
filter(Species %in% c("setosa", "versicolor")) %>%
.$query
Donne le bon SQL
syntaxe de requête :
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" IN ('setosa', 'versicolor')
<PostgreSQLConnection>
Et, s'il est exécuté, donne l'attendu :
#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
#.. ... ... ... ... ...
Voyons ce qui se passe si vous essayez de passer un seul élément :
tbl(mydb, "iris") %>%
filter(Species %in% "setosa") %>%
.$query
La requête sera :
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" IN 'setosa'
<PostgreSQLConnection>
Ce qui, s'il est exécuté, entraînera l'erreur suivante :
C'est parce que pour un seul élément, le dplyr
traduction en SQL
la requête n'ajoute pas la bonne parenthèse. Remarquez comment c'est 'setosa'
au lieu de ('setosa')
.
Pour contourner cela, nous pouvons faire :
if(length(input$Species) == 1) {
tbl(mydb, "iris") %>%
filter(Species == input$Species) %>%
}
Qui construira un SQL
syntaxiquement valide requête :
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" = 'setosa'
<PostgreSQLConnection>
L'exemple suivant contourne ce problème. Ici, je demande simplement à l'application de passer filter(Species == ...)
si input$Species
est de length
1 et filter(Species %in% ...)
Par ailleurs.
Application Shiny
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)