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

R Shiny函数循环绘图故障:selectInput传参报字符串转符号错误

问题解决:Shiny中ggplot自定义函数传字符串列名报错

问题

自定义散点图函数在R Markdown中直接传列名(如Petal.Length)能正常运行,在Shiny中直接传列名也能工作,但通过selectInput传递字符串格式的列名时,出现Only strings can be converted to symbols错误,尝试改用aes_string未解决问题。

错误原因

函数中使用ensym()处理参数,该函数仅能将**裸变量名(符号)**转换为符号对象,而Shiny的selectInput返回的是字符串类型的列名,导致转换失败。此外,原函数中部分数据引用和全局赋值的写法也存在优化空间。

修复方案

  1. 将参数转换从ensym()改为sym(),sym()专门用于将字符串转换为符号对象,兼容Shiny的字符串输入。
  2. 修正相关系数计算时的数据引用方式,使用pull()替代字符串索引,更符合tidyverse规范。
  3. 移除不必要的全局赋值corr<<-corr,避免污染全局环境。

修改后的完整代码

library(shiny)
library(tidyverse)
library(scales)
library(ggpubr)

scatter_fun <- function(data, xval, yval) {
  # 将字符串转为符号
  xval <- sym(xval)
  yval <- sym(yval)
  
  plot_list = list()
  corr = list()
  
  for (i in 0:3) {
    data2 <- data %>% mutate(x1 = lag(!!xval, i), y1 = !!yval)
    
    p <- ggplot(data2, aes(x1, y1)) +
      geom_point(size = 3, color = "#6724C6") +
      theme(
        axis.line.x.bottom = element_line("black"),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_blank(),
        axis.line.y.left = element_line("black"),
        panel.grid.major.x = element_blank(),
        legend.title = element_blank()
      ) +
      ylab(quo_name(yval)) +
      xlab(quo_name(xval)) +
      scale_y_continuous(labels = scales::comma) +
      scale_x_continuous(labels = scales::comma) +
      expand_limits(y = 0) +
      geom_smooth(se = FALSE, method = 'lm', colour = "gray48") +
      ggtitle(paste0("Lag", i)) +
      annotate(
        geom = 'text', 
        label = paste0("R=", round(cor(pull(data2, x1), pull(data2, y1), use = "complete.obs", method = "spearman"), 2)), 
        x = -Inf, y = Inf, hjust = 0, vjust = 1
      )
    
    plot_list[[i+1]] = p
    q = round(cor(pull(data2, x1), pull(data2, y1), use = "complete.obs", method = "spearman"), 2)
    corr[[i+1]] = q
  }
  
  return(plot_list)
}

dataset <- iris

ui <- fluidPage(
  titlePanel("Example"),
  fluidRow(
    column(7,
           selectInput("variable1", "Variable 1:",
                       choices = names(dataset[1:4]))),
    column(7,
           selectInput("variable2", "Variable 2:",
                       choices = names(dataset[1:4])))),
  mainPanel(
    plotOutput("distPlot")
  )
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    m <- scatter_fun(dataset, input$variable1, input$variable2)
    print(ggarrange(plotlist = m, ncol = 2, nrow = 3, common.legend = T))
  })
}

shinyApp(ui = ui, server = server)

关键修改点说明

  • sym(xval):将字符串格式的列名转换为ggplot和dplyr可以识别的符号对象,解决参数类型不匹配问题。
  • pull(data2, x1):直接提取列数据,替代原有的data2[,"x1"],代码更简洁且避免潜在的索引错误。
  • 移除corr<<-corr:函数内部的corr变量无需全局赋值,仅作为局部变量存储计算结果即可。

内容的提问来源于stack exchange,提问作者awz1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:17:01