多个selectInput值会创建意外的dplyr(postgres)行为

多个selectInput值会创建意外的dplyr(postgres)行为,r,postgresql,shiny,R,Postgresql,Shiny,我有一个可爱的闪亮的应用程序,它接受selectInput值,查询postgres数据库,并输出图形。这是一个简单的接口,但由于dplyr数据库连接,在这里很难重现 今天我将第一个selectInput值更改为multiple=TRUE;将传递到数据库的变量更新为修改控件返回的列表中的%in%;所有的麻烦都散开了 在我选择一个值之前,控件是空的,所以我遇到了一个闪亮的红色错误:RS-DBI驱动程序。。。在中告诉我我的查询无效 当只选择一个值时,我得到一个语法错误,“A108030”中的locat

我有一个可爱的闪亮的应用程序,它接受selectInput值,查询postgres数据库,并输出图形。这是一个简单的接口,但由于dplyr数据库连接,在这里很难重现

今天我将第一个selectInput值更改为multiple=TRUE;将传递到数据库的变量更新为修改控件返回的列表中的%in%;所有的麻烦都散开了

在我选择一个值之前,控件是空的,所以我遇到了一个闪亮的红色错误:RS-DBI驱动程序。。。在中告诉我我的查询无效 当只选择一个值时,我得到一个语法错误,“A108030”中的locationID 我可以通过在返回的列表周围加括号来解决这个问题。。。 %input$rtnLocid中的locationID% 但是,由于添加了括号,当我选择多个列表项时,这会创建一个新的运算符不存在错误:在“A108030”、“B…” 我认为现在的情况是,postgres驱动程序总是希望SQL列表值放在括号中,而在某些DBs中使用SQL列表值可能会更宽松一些;添加括号将修复第一个选择;当multi-select处于启用状态时,添加的括号再次打断postgres驱动程序

其他使用Shiny/postgres的人是否可以验证此行为

问候,, 杰夫


更新:@Steven在评论中指出了这个信息链接,而我在发布时没有找到它:

问题在于当您只选择一个元素并使用in运算符时,查询的构造方式。dplyr到SQL的转换没有添加正确的括号,因此失败。对这个问题进行了详细的讨论

解决这个问题的一种方法是,当输入长度等于1时,将不同的指令传递给过滤器,请参见下面的示例

下面是正在发生的事情:

tbl(mydb, "iris") %>%
  filter(Species %in% c("setosa", "versicolor")) %>%
  .$query
提供正确的SQL查询语法:

<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" IN ('setosa', 'versicolor')
<PostgreSQLConnection>
让我们看看如果尝试传递单个元素会发生什么:

tbl(mydb, "iris") %>%
  filter(Species %in% "setosa") %>%
  .$query
查询将是:

<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"
FROM "iris"
WHERE "Species" IN 'setosa'
<PostgreSQLConnection>
这将生成语法有效的SQL查询:


虽然史蒂文的回答很好,但我使用了一种稍微不同的方法,允许您使用单个管道。当您还想执行其他操作时,这很方便

这是selectedData反应器的外观:

selectedData <- reactive({
  tbl(mydb, "iris") %>% 
  {
    if(length(input$Species) == 1) 
      filter(., Species == input$Species)
    else
      filter(., Species %in% input$Species)
  } %>%
    data.frame %>%
    mutate() %>%
    etc... 
})

谢谢史蒂文-我现在正在调整这个,我对R还不放心,特别是管道,很抱歉耽搁了。让我感到困惑的是,我可以使用IN编写一个SQL查询,但只有一个条件——以下是。我觉得有点让我吃惊的是,dplyr隐式地控制了%IN%,而不是让程序员在==和%IN%之间做出决定,以便更好地匹配SQL。在SQL中,这是有效的:选择Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species FROM iris,其中Species在'setosa'中@Jeff抱歉,如果我不够明确的话。问题不在于不能使用IN和单个元素进行SQL查询,而是dplyr所做的语法转换。我会编辑得更清楚。谢谢。也感谢github链接。我将为下面的整数滑块添加一个乱码;来源相同的不同问题。这是可行的,但属于“必须是更好的方式”类别。crit这里有一个关于R中%in%问题的问题:
if(length(input$Species) == 1) { 
  tbl(mydb, "iris") %>% 
    filter(Species == input$Species) %>% 
}
<Query> SELECT "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species" 
FROM "iris" 
WHERE "Species" = 'setosa' 
<PostgreSQLConnection>
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)
selectedData <- reactive({
  tbl(mydb, "iris") %>% 
  {
    if(length(input$Species) == 1) 
      filter(., Species == input$Species)
    else
      filter(., Species %in% input$Species)
  } %>%
    data.frame %>%
    mutate() %>%
    etc... 
})