Shiny中如何将input输入变量正确传入自定义函数作为参数
结论
Shiny中完全可以将input组件获取的用户输入作为自定义函数的参数传入,你当前运行失败是因为混淆了dplyr/ggplot的非标准求值传参规则,错误使用了get()函数。
问题原因
input$var的返回值是字符串类型:当用户选择下拉框的A选项时,input$var的值是"A"(带引号的字符串),不是未加引号的裸列名A。- 你调用时写的
get(input$var),会在当前运行环境中查找名为A的独立变量,但你的环境中并没有定义名为A的全局变量,A只是数据框dsa的内部列,因此查找失败。 - 你最初版本函数里写的
{{get(x_axis)}}属于语法混用:{{}}是专门用于承接传入的裸列名的元编程运算符,和get()搭配使用本身就不符合tidyverse的传参规范。
修正方案
你的函数内部用!!sym(x_axis)处理参数的写法本身是适配字符串入参的,只需要修改调用逻辑,直接传入input$var字符串即可,不需要额外加get()。
修正后完整可运行代码
library(shiny) library(dplyr) library(ggplot2) library(plotly) ui <- fluidPage( selectInput("var", "Sel", choices = c("A", "B"), selected = "A"), plotlyOutput("sd") ) server <- function(input, output, session) { dsa <- data.frame( A = c("x","y","z"), B = c("x1","y1","z1"), Se = c("d","d", "f"), x = c(3,4,5) ) # 函数入参x_axis接收字符串类型的列名 fun_sam <- function(dt, x_axis) { dt1 <- dt %>% dplyr::group_by(!!sym(x_axis), `Se`) %>% dplyr::summarise(Weight = sum(`x`), .groups = "drop") dt1 <- as.data.frame(dt1) p <- ggplot(dt1, aes(x = !!sym(x_axis), y = Weight, fill = `Se`)) + geom_bar(width = 1, stat = "identity") + theme_bw() + theme( panel.border = element_blank(), panel.grid = element_blank(), axis.text.x = element_text(angle = 45) ) return(p) } output$sd <- renderPlotly({ # 直接传入input$var的字符串值即可,不需要get() fun_sam(dsa, input$var) }) } shinyApp(ui, server)
补充说明
如果你希望自定义函数同时兼容「裸列名传入」和「字符串传入」两种场景,可以用.data[[ ]]代词的写法,稳定性更高,不需要处理符号注入的问题,写法如下:
fun_sam <- function(dt, x_axis) { dt1 <- dt %>% dplyr::group_by(.data[[x_axis]], `Se`) %>% dplyr::summarise(Weight = sum(`x`), .groups = "drop") dt1 <- as.data.frame(dt1) p <- ggplot(dt1, aes(x = .data[[x_axis]], y = Weight, fill = `Se`)) + geom_bar(width = 1, stat = "identity") + theme_bw() + theme( panel.border = element_blank(), panel.grid = element_blank(), axis.text.x = element_text(angle = 45) ) return(p) }
这种写法下,不管你传fun_sam(dsa, "A")还是fun_sam(dsa, A)都能正常运行,更适合多场景复用。
内容的提问来源于stack exchange,提问作者manu p
相关产品推荐
相关产品推荐

