Shiny Screening App - Пользовательский фильтр / Mutate / Modify - PullRequest
0 голосов
/ 27 ноября 2018

Я нахожусь в процессе создания приложения для скрининга Shiny, которое позволило бы пользователям вводить команды R, такие как filter и mutate, на заранее заданном кадре данных.

Лично я думаю, что наиболее удобный способ сделать это - создать пустой столбец данных, содержащий параметры скрининга, где пользователи могут вводить такие команды, как filter(mpg >= 21) или mutate(cyl_sq = cyl^2), используя набор данных mtcars какпример.

Простое приложение для отображения предполагаемой функциональности:

library(shiny)
library(shinydashboard)
library(DT)
library(dplyr)
# Header ------------------------------------------------
header <- dashboardHeader(title = "Example Screening")
# Sidebar ------------------------------------------------
sidebar <- dashboardSidebar()
# Body ------------------------------------------------
body <-
dashboardBody(
  fluidRow(
       column(6,h3("Screening Parameters")),
       column(6,h3("Filtered/Modified Results"))),
  fluidRow(
       column(6,DT::dataTableOutput("screening_params")),
       column(6,DT::dataTableOutput("filtered_results")))
)
# APP ------------------------------------------------
shinyApp(ui <- dashboardPage(
  header,
  sidebar,
  body
),
# Server ----------------------------------------------------------
shinyServer(function(input,output){

  output$screening_params <- renderDataTable({
    tibble(params = c("filter(mpg >= 21)",
                      "mutate(cyl_sq = cyl^2)",
                      rep_len(NA_character_,8))) %>%
      DT::datatable(rownames = F,
                    editable = T)
  })

  output$filtered_results <- renderDataTable({
    mtcars %>%
      # input$screening_params
      DT::datatable()

  })

})) 

Я был бы открыт для использования DT или rhandsontable или любой альтернативы, которую кто-то можетдумать о.К сожалению, не похоже, что вы можете получить отредактированные значения таблицы в DT, но, надеюсь, это хороший пример того, что мне нужно.

Я перепробовал каждую комбинацию предложений и картографических функций, которые я могу придумать, но безрезультатно.

У кого-нибудь есть идеи?

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Благодарю Omri374 за то, что я с ней общался.

Простое приложение, удовлетворяющее требованиям:

library(shinydashboard)
library(DT)
library(dplyr)
library(rhandsontable)
# Header ------------------------------------------------
header <- dashboardHeader(title = "Example Screening")
# Sidebar ------------------------------------------------
sidebar <- dashboardSidebar()
# Body ------------------------------------------------
body <-
  dashboardBody(
    fluidRow(
      column(6,h3("Screening Parameters")),
      column(6,h3("Filtered/Modified Results"))),
    fluidRow(
      column(6, rHandsontableOutput("hot")),
      column(6, dataTableOutput("filtered_results")))
  )
# APP ------------------------------------------------
shinyApp(ui <- dashboardPage(
  header,
  sidebar,
  body
),
# Server ----------------------------------------------------------
shinyServer(function(input,output){

  output$hot <- renderRHandsontable({
    tibble(params = c("filter(mpg >= 21)",
                      "filter(cyl == 4)",
                      "mutate(cyl_sq = cyl^2)",
                      "select(cyl,mpg,drat)",
                      rep_len(NA_character_,6))) %>%
      rhandsontable() %>%
      hot_cols(colWidths = 500)
  })

  output$filtered_results <- renderDataTable({


    df <- mtcars

    params <- input$hot %>%
      hot_to_r() %>%
      filter(!is.na(params),params != "") %>%
      mutate(params = ifelse(row_number() == max(row_number()),
                             params,
                             paste0(params," %>% "))) %>%
      pull(params) %>%
      str_c(collapse = "")


    if(length(params)>=1){

      eval(parse(text = paste0("filt_df <- df %>%",params)))

    } else {

      filt_df <- df

    }

    filt_df %>%
      datatable()



  })

}))
0 голосов
/ 03 декабря 2018

Это немного другой подход, но, возможно, вы найдете его полезным.Я использую sqldf в качестве механизма SQL-запросов, и пользователи могут манипулировать данными, используя специальные SQL-запросы к данному набору данных.Если это не то, что вам нужно, я, по крайней мере, надеюсь, что он даст вам несколько советов о том, как это сделать с синтаксисом dplyr.

Если вы все равно выберете вариант dplyr и выЕсли у вас есть строка с запрошенной манипуляцией, вы можете использовать реактивный метод getDataset, чтобы оценить выражение, полученное от пользователя, манипулировать вашим набором данных.Затем вызовите getDataset в методе renderDataTable, как я это делал в прикрепленном коде.

Пример для вычисления строкового выражения:

eval(parse(text="res <- mtcars %>% filter(mpg < 20)"))

Для опции SQL:

library(shiny)
library(shinydashboard)
library(DT)
library(dplyr)
library(sqldf)
# Header ------------------------------------------------
header <- dashboardHeader(title = "Example Screening")
# Sidebar ------------------------------------------------
sidebar <- dashboardSidebar(collapsed = TRUE)
# Body ------------------------------------------------
body <-
  dashboardBody(
    fluidRow(
      #column(6,h3("Screening Parameters")),
      column(6,h3("Filtered/Modified Results"))),
    fluidRow(
      textInput("sql","SQL Query",value = "SELECT * FROM dataset"),
      DT::dataTableOutput(("filtered_results"))
    )
  )
# APP ------------------------------------------------
shinyApp(ui <- dashboardPage(
  header,
  sidebar,
  body
),
# Server ----------------------------------------------------------
shinyServer(function(input,output){

  ## A new function to load data and perform the SQL query on it
  getDataset <- reactive({
    query <- input$sql
    dataset <- mtcars
    sqldf::sqldf(query)
  })

  output$filtered_results <- renderDataTable({
    getDataset() %>%
      DT::datatable()

  })

})) 
...