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

如何解决R Shiny中ggplot表达式传递与变量重排序失效问题

问题原因
  • aes_string已被ggplot2弃用,且原代码中对reorder的调用存在核心错误:将字符型的input$xaxis直接传入reorder,同时把排序变量(visitnum/avisitn)用引号包裹,导致reorder无法识别数据框中的实际列。
  • expr和eval_tidy的组合在这里不适合配合aes_string使用,因为aes_string需要的是字符串形式的表达式,而非求值后的结果。
修复方案

改用ggplot2推荐的符号引用(sym())和非标准求值(!!),或者使用.data代词处理动态变量,同时正确构建reorder的逻辑:

修正后的完整代码

library(shiny)
library(tidyverse)
library(tidyCDISC)
library(DT)
library(shinyjs)
library(timevis)
library(rlang)

data('advs', package = 'tidyCDISC')
advs <- advs %>% rename_all(tolower) %>% filter(anl01fl=='Y')

parvs <- unique(advs$param)
usubjid <- unique(advs$usubjid)

ui <- fluidPage(
  
  titlePanel("Patient Profile"),
  
  sidebarLayout(
    sidebarPanel(
      selectInput("subj",
                  "Please Select a USUBJID",
                  choices = usubjid,
                  selected = usubjid[1])
    ),
    
    mainPanel(tags$div(selectInput('para', 'Parameter', choices = parvs), style="display:inline-block"),
              tags$div(selectInput('yaxis', 'Analysis Y Variable', choices = list('aval','chg', 'pchg')), style="display:inline-block") ,
              tags$div(selectInput('xaxis', 'Analysis X Variable', choices = list('ady','visit', 'avisit')), style="display:inline-block") ,
              plotOutput("plot2"))
  )
)


server <- function(input, output, session) {
  output$plot2 <- renderPlot({
    req(input$para, input$yaxis, input$xaxis)
    
    # 提前筛选数据,简化后续代码
    plot_data <- advs %>% 
      filter(usubjid == input$subj & param == input$para)
    
    # 将字符型输入转为符号,用于动态引用列
    x_var <- sym(input$xaxis)
    
    # 根据x轴选择构建对应表达式
    x_expr <- if(input$xaxis == 'visit'){
      expr(reorder(!!x_var, visitnum))
    } else if(input$xaxis == 'avisit'){
      expr(reorder(!!x_var, avisitn))
    } else {
      x_var
    }
    
    # 使用标准aes和动态变量引用
    ggplot(plot_data, aes(x = !!x_expr, y = .data[[input$yaxis]], group = atpt)) + 
      geom_line(aes(color = atpt)) +
      ggtitle(paste(input$para, 'Line Plot'))
  })
}

shinyApp(ui, server)

关键改动说明

  1. 替换aes_string为标准aes:
    • 用.data[[input$yaxis]]直接引用动态y轴变量,这是ggplot2官方推荐的动态变量引用方式。
    • 用sym()将字符型的input$xaxis转换为符号,再通过!!(强制求值)传入aes中,让ggplot识别为数据框的列。
  2. 正确构建reorder逻辑:
    • 当需要重排序时,用expr()构建reorder(!!x_var, 排序变量)的表达式,其中!!x_var会被替换为实际的x轴列(如visit或avisit),排序变量直接使用数据框中的列名(无需加引号)。
  3. 提前筛选数据:把数据筛选步骤单独提取,让代码更清晰,也避免重复计算。

更简洁的替代写法

如果不想单独构建表达式,也可以直接在aes中判断:

ggplot(plot_data, aes(
  x = if(input$xaxis == 'visit') reorder(visit, visitnum) else 
       if(input$xaxis == 'avisit') reorder(avisit, avisitn) else .data[[input$xaxis]],
  y = .data[[input$yaxis]],
  group = atpt
)) + 
  geom_line(aes(color = atpt)) +
  ggtitle(paste(input$para, 'Line Plot'))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 05:40:25