gpt4 book ai didi

r - 将 renderUI 输入从一个 Shiny 模块传递到另一个

转载 作者:行者123 更新时间:2023-12-04 11:12:59 25 4
gpt4 key购买 nike

我正在尝试模块化 Shiny 代码,以将 CSV 文件作为输入上传到 scatterD3 图中。额外的 UI 控件将从 renderUI 更改 x 变量和 y 变量。这只是来自 How to organize large R Shiny apps? 的 Mikael Jumppanen 答案的一个小修改,但我一直在努力,无法让这最后一点发挥作用。

对于这个数据集,我使用 mtcars 数据集 https://gallery.shinyapps.io/066-upload-file/_w_469e9927/mtcars.csv

## load libraries
library(shiny)
library(stringr)
library(scatterD3)

#source("/Users/echang/scratch/tmp/MSD_D3scatter/csvFile_Module.R")
csvFileInput <- function(id, label="CSV file") {
## Create namespace
ns<-NS(id)
tagList(
uiOutput(ns("controls"))
)
}

csvFileControl <- function(id){
ns <- NS(id)
tagList(
column(width=3, uiOutput(ns("ColName"))),
column(width=3, uiOutput(ns("ColEntry")))
)
}

csvFileUI <- function(id){
ns <- NS(id)
tagList(
uiOutput(ns("csvTable"))
)
}

## server module
csvFile <- function(input, output, session, stringsAsFactors) {
ns <- session$ns
## to reuse namespace, session must be first!!!

## User selected file
userFile <- reactive({
# If no file is selected, don't do anything
validate(need(input$file, message = FALSE))
input$file
})

dataframe <- reactive({
read.csv(
userFile()$datapath,
header = input$header,
sep=input$sep,
quote = input$quote,
stringsAsFactors = stringsAsFactors
)
})
# We can run observers in here if we want to
observe({
msg <- sprintf("File %s was uploaded", userFile()$name)
cat(msg, "\n")
})

output$controls <- renderUI({
## use taglist to keep everything together
tagList(
fileInput(ns('file'), 'Choose CSV file',
accept=c('txt/csv','text/comma-separated-values,text/plain','.csv')),
checkboxInput(ns('header'), 'Has heading', TRUE),
radioButtons(ns('sep'),'Separator', c(Comma=',',Semicolon=';',Tab='\t'), ','),
selectInput(ns('quote'),'Quote', c(None ='','Double Quote'='"','Single Quote'="'"),'"')
)
})

## use renderUI to display table
output$csvTable <- renderUI({
output$table <- renderDataTable(dataframe())
dataTableOutput(ns("table"))
})

## Column Name
output$ColName <- renderUI({
df <- dataframe()
if (is.null(df)) return(NULL)
items=names(df)
names(items)=items
tagList(
selectInput(ns("xvar"), "Column Names", items),
selectInput(ns("yvar"), "Column Names", items)
)
})

## Column Entry
output$ColEntry <- renderUI({
df <- dataframe()
if (is.null(input$col)) return(NULL)
tagList(
selectInput(ns("entry"), "Entry Names", df[,input$xvar])
)
})

# Return the reactive that yields the data frame
return(dataframe)

}## End of module


## scatterD3 module -------------------------------------------------------------

D3scatterUI <- function(id){
ns<-NS(id)
tagList(
scatterD3Output(ns("scatterplot1"))
)
}

D3scatter <- function(input,output,session,data,xvar,yvar){
ns <- session$ns

output$scatterplot1 <- renderScatterD3({
#scatterD3(data = data, x=mpg, y=carb,
scatterD3(data = data, x=xvar, y=yvar,
labels_size= 9, point_opacity = 1,
#col_var=cyl, symbol_var= data$Assay,
#lab= paste(mpg, carb, sep="|") , lasso=TRUE,
#xlab= "IFN-γ", ylab= "IL-10",
#click_callback = "function(id, index) {
# alert('scatterplot ID: ' + id + ' - Point index: ' + index)
# }",
transitions= T)
})
}


## Shiny ######################################################################
ui <- fluidPage(
titlePanel("Upload"),

tabsetPanel(type="tabs",
tabPanel("tab1",
sidebarLayout(
sidebarPanel(csvFileInput("basic")),
mainPanel(csvFileUI("basic"))
)
),
tabPanel("tab2",
tagList(
fluidRow(csvFileControl("basic")),
fluidRow(D3scatterUI("first"))
)
)
)
)

server <- function(input, output, session) {
## Option 1. CSV uploaded file
datafile <- callModule(csvFile, "basic", stringsAsFactors = FALSE)

## Option 2. mtcar data loaded at start
#datafile <- reactive({mtcars}) ## data loaded at runApp()
#callModule(csvFile, "basic")

xvar <- reactive(input$xvar)
yvar <- reactive(input$yvar)

callModule(D3scatter, "first", datafile(), xvar, yvar)

}

shinyApp(ui, server)

我还从 https://itsalocke.com/shiny-module-design-patterns-pass-module-input-to-other-modules/ 咨询了 Shiny 模块设计。

我观看了网络研讨会,但无法正确理解逻辑。 https://www.rstudio.com/resources/webinars/understanding-shiny-modules/任何帮助将不胜感激!!

最佳答案

好的,这确实有点困难,因为使用模块并不是很简单。你很接近...你的主要问题是没有收拾行李全部 列表中的 react 物并将它们传递到需要它们的地方。

我做了以下更改:

  • csvFile : 声明了额外的 react 函数 xvaryvarcsvFile服务器模块功能类似于您已经为 dataframe 所做的工作.
  • csvFile :将所有需要的响应式(Reactive)打包成一个列表,并将其作为返回值返回,如您帖子中的设计模式链接中所述。 (谢谢斯蒂芬洛克)。
  • server : 在 callModule(D3scatter,... ) 中传递该列表,再次如该链接中所述。
  • D3scatter : 通过调用 scatterD3 进行了一些重构使用从指定数据帧中提取的向量。这是因为我无法让它将字符串用作列说明符(但肯定有某种方法)。

  • 以下是上面更改的代码部分:

    csv文件服务器模块
    csvFile <- function(input, output, session, stringsAsFactors) {
    ns <- session$ns
    ## to reuse namespace, session must be first!!!

    ## User selected file
    userFile <- reactive({
    # If no file is selected, don't do anything
    validate(need(input$file, message = FALSE))
    input$file
    })

    dataframe <- reactive({
    read.csv(
    userFile()$datapath,
    header = input$header,
    sep=input$sep,
    quote = input$quote,
    stringsAsFactors = stringsAsFactors
    )
    })
    # We can run observers in here if we want to
    observe({
    msg <- sprintf("File %s was uploaded", userFile()$name)
    cat(msg, "\n")
    })

    xvar <- reactive({input[[ "xvar" ]] })
    yvar <- reactive({input[[ "yvar" ]] })

    output$controls <- renderUI({
    ## use taglist to keep everything together
    tagList(
    fileInput(ns('file'), 'Choose CSV file',
    accept=c('txt/csv','text/comma-separated-values,text/plain','.csv')),
    checkboxInput(ns('header'), 'Has heading', TRUE),
    radioButtons(ns('sep'),'Separator', c(Comma=',',Semicolon=';',Tab='\t'), ','),
    selectInput(ns('quote'),'Quote', c(None ='','Double Quote'='"','Single Quote'="'"),'"')
    )
    })

    ## use renderUI to display table
    output$csvTable <- renderUI({
    output$table <- renderDataTable(dataframe())
    dataTableOutput(ns("table"))
    })

    ## Column Name
    output$ColName <- renderUI({
    df <- dataframe()
    if (is.null(df)) return(NULL)
    items=names(df)
    print(items)
    names(items)=items
    tagList(
    selectInput(ns("xvar"), "Column Names", items),
    selectInput(ns("yvar"), "Column Names", items)
    )
    })

    ## Column Entry
    output$ColEntry <- renderUI({
    df <- dataframe()
    if (is.null(input$col)) return(NULL)
    tagList(
    selectInput(ns("entry"), "Entry Names", df[,input$xvar])
    )
    })

    rlist <- list(dataframe=dataframe,xvar=xvar,yvar=yvar)
    # Return the reactive that yields the data frame
    return(rlist)

    }## End of module

    服务器
    server <- function(input, output, session) {
    ## Option 1. CSV uploaded file
    rlist <- callModule(csvFile, "basic", stringsAsFactors = FALSE)

    ## Option 2. mtcar data loaded at start
    #datafile <- reactive({mtcars}) ## data loaded at runApp()
    #callModule(csvFile, "basic")

    callModule(D3scatter, "first", rlist)

    }

    D3scatter
    D3scatter <- function(input,output,session,rlist){
    ns <- session$ns

    output$scatterplot1 <- renderScatterD3({
    #scatterD3(data = data, x=mpg, y=carb,
    mtdf <- rlist$dataframe()
    x <- mtdf[[rlist$xvar()]]
    y <- mtdf[[rlist$yvar()]]
    scatterD3(x=x,y=y,
    labels_size= 9, point_opacity = 1,
    #col_var=cyl, symbol_var= data$Assay,
    #lab= paste(mpg, carb, sep="|") , lasso=TRUE,
    #xlab= "IFN-γ", ylab= "IL-10",
    #click_callback = "function(id, index) {
    # alert('scatterplot ID: ' + id + ' - Point index: ' + index)
    # }",
    transitions= T)
    })
    }

    然后它起作用了:

    enter image description here

    这是所有正在运行的代码,以防我忘记了某处的更改,或者有人只想运行它。顺便说一句,散点图从一个情节变为另一个情节的方式非常酷……它以类似动画的效果连续变形。异常。

    整个应用程序在一个文件中
    ## load libraries
    library(shiny)
    library(stringr)
    library(scatterD3)

    #source("/Users/echang/scratch/tmp/MSD_D3scatter/csvFile_Module.R")
    csvFileInput <- function(id, label="CSV file") {
    ## Create namespace
    ns<-NS(id)
    tagList(
    uiOutput(ns("controls"))
    )
    }

    csvFileControl <- function(id){
    ns <- NS(id)
    tagList(
    column(width=3, uiOutput(ns("ColName"))),
    column(width=3, uiOutput(ns("ColEntry")))
    )
    }

    csvFileUI <- function(id){
    ns <- NS(id)
    tagList(
    uiOutput(ns("csvTable"))
    )
    }

    ## server module
    csvFile <- function(input, output, session, stringsAsFactors) {
    ns <- session$ns
    ## to reuse namespace, session must be first!!!

    ## User selected file
    userFile <- reactive({
    # If no file is selected, don't do anything
    validate(need(input$file, message = FALSE))
    input$file
    })

    dataframe <- reactive({
    read.csv(
    userFile()$datapath,
    header = input$header,
    sep=input$sep,
    quote = input$quote,
    stringsAsFactors = stringsAsFactors
    )
    })
    # We can run observers in here if we want to
    observe({
    msg <- sprintf("File %s was uploaded", userFile()$name)
    cat(msg, "\n")
    })

    xvar <- reactive({input[[ "xvar" ]] })
    yvar <- reactive({input[[ "yvar" ]] })

    output$controls <- renderUI({
    ## use taglist to keep everything together
    tagList(
    fileInput(ns('file'), 'Choose CSV file',
    accept=c('txt/csv','text/comma-separated-values,text/plain','.csv')),
    checkboxInput(ns('header'), 'Has heading', TRUE),
    radioButtons(ns('sep'),'Separator', c(Comma=',',Semicolon=';',Tab='\t'), ','),
    selectInput(ns('quote'),'Quote', c(None ='','Double Quote'='"','Single Quote'="'"),'"')
    )
    })

    ## use renderUI to display table
    output$csvTable <- renderUI({
    output$table <- renderDataTable(dataframe())
    dataTableOutput(ns("table"))
    })

    ## Column Name
    output$ColName <- renderUI({
    df <- dataframe()
    if (is.null(df)) return(NULL)
    items=names(df)
    print(items)
    names(items)=items
    tagList(
    selectInput(ns("xvar"), "Column Names", items),
    selectInput(ns("yvar"), "Column Names", items)
    )
    })

    ## Column Entry
    output$ColEntry <- renderUI({
    df <- dataframe()
    if (is.null(input$col)) return(NULL)
    tagList(
    selectInput(ns("entry"), "Entry Names", df[,input$xvar])
    )
    })

    rlist <- list(dataframe=dataframe,xvar=xvar,yvar=yvar)
    # Return the reactive that yields the data frame
    return(rlist)

    }## End of module


    ## scatterD3 module -------------------------------------------------------------

    D3scatterUI <- function(id){
    ns<-NS(id)
    tagList(
    scatterD3Output(ns("scatterplot1"))
    )
    }

    D3scatter <- function(input,output,session,rlist){
    ns <- session$ns

    output$scatterplot1 <- renderScatterD3({
    #scatterD3(data = data, x=mpg, y=carb,
    mtdf <- rlist$dataframe()
    x <- mtdf[[rlist$xvar()]]
    y <- mtdf[[rlist$yvar()]]
    scatterD3(x=x,y=y,
    labels_size= 9, point_opacity = 1,
    #col_var=cyl, symbol_var= data$Assay,
    #lab= paste(mpg, carb, sep="|") , lasso=TRUE,
    #xlab= "IFN-γ", ylab= "IL-10",
    #click_callback = "function(id, index) {
    # alert('scatterplot ID: ' + id + ' - Point index: ' + index)
    # }",
    transitions= T)
    })
    }


    ## Shiny ######################################################################
    ui <- fluidPage(
    titlePanel("Upload"),

    tabsetPanel(type="tabs",
    tabPanel("tab1",
    sidebarLayout(
    sidebarPanel(csvFileInput("basic")),
    mainPanel(csvFileUI("basic"))
    )
    ),
    tabPanel("tab2",
    tagList(
    fluidRow(csvFileControl("basic")),
    fluidRow(D3scatterUI("first"))
    )
    )
    )
    )

    server <- function(input, output, session) {
    ## Option 1. CSV uploaded file
    rlist <- callModule(csvFile, "basic", stringsAsFactors = FALSE)

    ## Option 2. mtcar data loaded at start
    #datafile <- reactive({mtcars}) ## data loaded at runApp()
    #callModule(csvFile, "basic")

    callModule(D3scatter, "first", rlist)

    }

    shinyApp(ui, server)

    关于r - 将 renderUI 输入从一个 Shiny 模块传递到另一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43038967/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com