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

R Shiny散点图保留带空格变量名的技术问题咨询

解决Shiny散点图中带空格变量名的报错问题

你在RStudio开发的Shiny应用中,时间序列图能正常处理Water Temperature和Air Temperature这类带空格的变量名,但散点图出现解析错误:

Warning: Error in parse: <text>:1:7: unexpected symbol
1: Water Temperature
          ^

或

Warning: Error in parse: <text>:1:5: unexpected symbol
1: Air Temperature
        ^

问题根源是你使用的aes_string()函数会将传入的字符串当作R代码解析,而带空格的变量名不符合R默认语法规则(R要求变量名无空格,除非用反引号包裹)。要保留变量名空格,只需替换aes_string()为支持动态引用带空格变量的语法即可,以下是两种可行方案:

方案1:使用.data代词(推荐)

这是tidyverse官方推荐的动态变量引用方式,通过.data[[变量名]]可以安全调用带空格的变量:

关键修改点

  1. 散点图需要宽格式数据,因此将数据源从长格式的dat_long改为原始宽格式的dat(长格式仅适用于时间序列图的单变量展示)
  2. 用aes(x = .data[[input$xAxisInput]], y = .data[[input$yAxisInput]])替换aes_string()

修改后的散点图渲染代码:

output$scatterPlot <- renderPlot({
  filteredData2 <- dat %>%
    filter(Site == input$siteInput2)
  
  xLabel <- switch(input$xAxisInput[1],
                   `Air Temperature` = expression(Air~Temperature~(degree*C)),
                   `Water Temperature` = expression(Water~Temperature~(degree*C)))
  
  yLabel <- switch(input$yAxisInput[1],
                   `Air Temperature` = expression(Air~Temperature~(degree*C)),
                   `Water Temperature` = expression(Water~Temperature~(degree*C)))
  
  ggplot(filteredData2, aes(x = .data[[input$xAxisInput]], y = .data[[input$yAxisInput]])) +
    geom_point() +
    labs(x = xLabel, y = yLabel,
         title = paste('Site:', input$siteInput2)) +
    theme_bw()
})

方案2:使用sym()和非标准求值

通过rlang::sym()将字符串转换为R符号,再用!!注入到aes()中:

output$scatterPlot <- renderPlot({
  filteredData2 <- dat %>%
    filter(Site == input$siteInput2)
  
  xLabel <- switch(input$xAxisInput[1],
                   `Air Temperature` = expression(Air~Temperature~(degree*C)),
                   `Water Temperature` = expression(Water~Temperature~(degree*C)))
  
  yLabel <- switch(input$yAxisInput[1],
                   `Air Temperature` = expression(Air~Temperature~(degree*C)),
                   `Water Temperature` = expression(Water~Temperature~(degree*C)))
  
  ggplot(filteredData2, aes(x = !!rlang::sym(input$xAxisInput), y = !!rlang::sym(input$yAxisInput))) +
    geom_point() +
    labs(x = xLabel, y = yLabel,
         title = paste('Site:', input$siteInput2)) +
    theme_bw()
})

完整修改后的应用代码

library(tidyverse)
library(shiny)
library(shinydashboard)

# Create example dataset
set.seed(123)

dat <- data.frame(
  Time = rep(seq(1,10,1), times = 2),
  Site = rep(c('A', 'B'), each = 10),
  Water_Temperature = round(rnorm(20, mean = 20, sd = 5)),
  Air_Temperature = round(rnorm(20, mean = 25, sd = 3))
)

dat <- dat %>%
  rename(`Water Temperature` = Water_Temperature,
         `Air Temperature` = Air_Temperature)

dat_long <- dat %>%
  pivot_longer(cols = c("Water Temperature","Air Temperature"),
               names_to = 'Variable',
               values_to = 'Value') %>%
  arrange(Site, Time)

# Define user interface for time series and scatterplot
ui.R <- dashboardPage(
  dashboardHeader(title = "Example", titleWidth = 350),
  dashboardSidebar(
    tags$head(
      tags$style(
        HTML("
          .sidebar-footer {
            text-align: center;
          }
          .sidebar-logo {
            display: flex;
            align-items: center;
            justify-content: center;
          }
          .sidebar-menu a span {
            font-size: 24px;
          }
        ")
      )
    ),
    sidebarMenu(
      menuItem("Time Series", tabName = "time_series", icon = icon("chart-line")),
      menuItem("Scatterplot", tabName = "scatter_plot", icon = icon("chart-line"))
    )
  ),
  dashboardBody(
    tabItems(
      tabItem(
        tabName = "time_series",
        fluidRow(
          box(
            title = "Time Series",
            status = "primary",
            solidHeader = TRUE,
            width = 2,
            selectInput("siteInput", "Select Site", choices = unique(dat_long$Site)),
            selectInput("variableInput", "Select Variable", choices = unique(dat_long$Variable))
          ),
          box(
            title = "Plot",
            status = "primary",
            solidHeader = TRUE,
            width = 10,
            plotOutput("timeSeriesPlot", height = "700px")
          )
        )
      ),
      tabItem(
        tabName = "scatter_plot",
        fluidRow(
          box(
            title = "Scatterplot",
            status = "primary",
            solidHeader = TRUE,
            width = 2,
            selectInput("siteInput2", "Select Site", choices = unique(dat_long$Site)),
            selectInput("xAxisInput", "Select X-axis Variable:", choices = unique(dat_long$Variable)),
            selectInput("yAxisInput", "Select Y-axis Variable:", choices = unique(dat_long$Variable))
          ),
          box(
            title = "Plot",
            status = "primary",
            solidHeader = TRUE,
            width = 10,
            plotOutput("scatterPlot", height = "700px")
          )
        )
      ),
      tabItem(
        tabName = "site_info",
        fluidPage(
          fluidRow(
            selectInput("siteInput3", "Select Site", choices = unique(dat_long$Site)),
            column(4, dataTableOutput('table'))
          )
        )
      )
    )
  )
)

# Define server
server.R <- function(input, output) {
  output$timeSeriesPlot <- renderPlot({
    filteredData <- dat_long %>%
      filter(Site == input$siteInput, Variable == input$variableInput)
    
    variableName <- unique(filteredData$Variable)
    yLabel <- ifelse(variableName == "Water Temperature", expression(Water~Temperature~(degree*C)),
                     ifelse(variableName == "Air Temperature", expression(Air~Temperature~(degree*C))))
    
    ggplot(filteredData, aes(x = Time, y = Value)) +
      geom_line() +
      geom_point() +
      scale_x_continuous(breaks = seq(1,10,1)) +
      labs(x = "", y = yLabel,
           title = paste('Site:', input$siteInput)) +
      theme_bw()
  })
  
  output$scatterPlot <- renderPlot({
    filteredData2 <- dat %>%
      filter(Site == input$siteInput2)
    
    xLabel <- switch(input$xAxisInput[1],
                     `Air Temperature` = expression(Air~Temperature~(degree*C)),
                     `Water Temperature` = expression(Water~Temperature~(degree*C)))
    
    yLabel <- switch(input$yAxisInput[1],
                     `Air Temperature` = expression(Air~Temperature~(degree*C)),
                     `Water Temperature` = expression(Water~Temperature~(degree*C)))
    
    ggplot(filteredData2, aes(x = .data[[input$xAxisInput]], y = .data[[input$yAxisInput]])) +
      geom_point() +
      labs(x = xLabel, y = yLabel,
           title = paste('Site:', input$siteInput2)) +
      theme_bw()
  })
}

# Run the application
shinyApp(ui = ui.R, server = server.R)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 22:47:33