You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 12:48:10