r:构建一个交互式sql查询并将数据复制到全局环境中

xt0899hw  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(332)

我试图建立一个闪亮的应用程序,让用户能够查询数据。用户应该提供一个感兴趣的值列表,这些值用于过滤存储在数据库中的数据。不幸的是, dplyr 的翻译似乎不是最有效/性能最好的解决方案,因此我必须构建一个字符串并通过 sql() . 字符串操作也是处理输入错误/变体的一种粗糙的故障安全机制。以下代码说明了此字符串生成和数据查询过程:

library(tibble)
library(dplyr)
library(dbplyr)
library(shiny)
library(RSQLite)
library(DBI)
library(stringr)

# Create string variables to experiment

mtcars1 <- tibble::rownames_to_column(mtcars, var = "model") %>% # Create column based on row names
    dplyr::mutate(carmaker = stringr::word(model, 1))            # Create column with first word of column with row names

# Establish example database

con <- DBI::dbConnect(RSQLite::SQLite(), path = ":memory:")
copy_to(con, mtcars1, "mtcars1", temporary = FALSE)

# Query example

# Input

string_input <- "Mazda,    Merc"

# Prepare input string to be used in SQL

string_filter <- string_input %>%
    base::gsub("[,]+", " ", .) %>%         # remove commas
    stringr::str_squish(.) %>%             # remove multiple blanks
    base::gsub(" ", ",", .) %>%            # substitute blanks for commas
    base::gsub("(\\w+)", "'\\1'", .) %>%   # enclose words with single quotation marks
    base::paste0("carmaker in (", ., ")")  # create sql where statement

# Data query

data <- tbl(con, "mtcars1") %>%
    filter(sql(string_filter)) %>%
    show_query() %>%
    collect()

我想在一个闪亮的应用程序中实现以下代码:


# Shiny user interface

ui <- fluidPage(

    textInput(inputId = "string_input", label = "Input", value = "", placeholder = "Enter list of car models without commas"),

    actionButton(inputId = "go", label = "Go"),

    textOutput(outputId = "string_output")

)

# Shiny server function

server <- function(input, output){

    observeEvent(input$go, {

        output$string_output <- reactive({input$string_input %>%
                base::gsub("[,]+", " ", .) %>%         # remove commas
                stringr::str_squish(.) %>%             # remove multiple blanks
                base::gsub(" ", ",", .) %>%            # substitute blanks for commas
                base::gsub("(\\w+)", "'\\1'", .) %>%   # enclose words with single quotation marks
                base::paste0("carmaker in (", ., ")")  # create sql where statement
        })
    })
}

# Launch shiny app

shinyApp(ui, server)

应用程序将用户提供的值列表作为输入,对其进行转换,并将转换后的列表显示为输出。
我想做的是:
我想将转换后的字符串输入存储在一个额外的本地对象中,以便在应用程序中进一步使用,也就是说,我想将字符串输入传递给数据查询,类似于上面的非闪亮示例。
我想将数据查询结果复制到 R 的全局环境,即使关闭应用程序,我也可以使用它。
关于我的第二点:我读到一个可以使用 <- 以及 <<- ,但我不能让它在被动的环境中工作。

6g8kf2rb

6g8kf2rb1#

第一个问题是:


# Shiny server function

server <- function(input, output){

string_output <- eventReactive(input$go, {
    input$string_input %>%
        base::gsub("[,]+", " ", .) %>%         # remove commas
        stringr::str_squish(.) %>%             # remove multiple blanks
        base::gsub(" ", ",", .) %>%            # substitute blanks for commas
        base::gsub("(\\w+)", "'\\1'", .) %>%   # enclose words with single quotation marks
        base::paste0("carmaker in (", ., ")")  # create sql where statement

  })
  output$string_output <-renderText(string_output())
}
``` `string_output()` React函数现在可以用于输出和数据查询。
请注意,您还可以使用 `input$string_input` 而不是 `input$go` 作为触发器,在键入条件时更新输出。
然后你可以使用 `input$go` 查询数据:

data <- eventReactive(input$go, { dbGetQuery(yourConnection,YourQuery(string_output())})
output$data <- renderTable(data())

不确定是否可以直接从shiny写入r的环境,但可以肯定地将data()保存为服务器上的文件。
toe95027

toe950272#

我想出了解决办法:

library(tibble)
library(dplyr)
library(dbplyr)
library(shiny)
library(RSQLite)
library(DBI)
library(stringr)

# Create string variables to experiment

mtcars1 <- tibble::rownames_to_column(mtcars, var = "model") %>% # Create column based on row names
    dplyr::mutate(carmaker = stringr::word(model, 1))            # Create column with first word of column with row names

# Establish example database

con <- DBI::dbConnect(RSQLite::SQLite(), path = ":memory:")
copy_to(con, mtcars1, "mtcars1", temporary = FALSE)

# Shiny user interface

ui <- fluidPage(

    textInput(inputId = "string_input",
              label = "Input",
              value = "",
              placeholder = "Enter a list of car makers (e.g. Mazda, Merc)"),

    textOutput(outputId = "string_output"),

    actionButton(inputId = "go", label = "Go"),

    tableOutput(outputId = "data_output")

)

# Custom function to save reactive object to global environment

saveData <- function(x) {
    export <<- x
}

# Shiny server function

server <- function(input, output){

        list <- reactive({

            input$string_input %>%
            base::gsub("[,]+", " ", .) %>%         # remove commas
            stringr::str_squish(.) %>%             # remove multiple blanks
            base::gsub(" ", ",", .) %>%            # substitute blanks for commas
            base::gsub("(\\w+)", "'\\1'", .) %>%   # enclose words with single quotation marks
            base::paste0("carmaker in (", ., ")")  # create sql where statement

        })

        output$string_output <- reactive({list()})

        data <- eventReactive(input$go, {

            tbl(con, "mtcars1") %>%
                dplyr::filter(sql(!!list())) %>%
                dplyr::collect()

        })

        output$data_output <- renderTable(data())

        observeEvent(input$go, {

            saveData(data())

        })

}

# Launch shiny app

shinyApp(ui, server)

诀窍是定义函数 saveData ,传递React data 对象并将其分配给 export 通过 <<- .
老实说,我不了解所有的基本原理,所以任何改进的建议都是欢迎的。然而,它是有效的。

相关问题