R Shiny应用中ggplot aes_string无法识别X/Y轴及日期显示异常
解决你的R Shiny应用两个问题
我来帮你逐个排查并解决这两个头疼的问题:
问题1:ggplot提示缺少x、y美学参数
你遇到的geom_point requires the following missing aesthetics: x, y错误,主要有两个核心原因:
未定义
choices变量:你的selectInput里用了choices = c(choices),但这个choices变量根本没提前定义!应该把它设置为数据集的列名(按需排除日期列),比如在UI定义前加一行:choices <- colnames(data4)[!colnames(data4) %in% "Deployment.Month"]这样下拉框就会自动显示除日期外的所有列选项。
aes_string的使用和参数位置错误:你把colour='red'放在了ggplot()的参数里,但这个是点的样式参数,应该移到geom_point()里;另外要确保input$x和input$y对应的列确实存在于筛选后的数据集里,且是适合做散点图的数值类型。修改后的renderPlot代码:output$scatterplot <- renderPlot({ # 确保所有必要输入都已加载 req(input$date, input$x, input$y) projects_selected_date <- data4 %>% filter(Deployment.Month >= input$date[1] & Deployment.Month <= input$date[2]) # 避免空数据导致报错 validate(need(nrow(projects_selected_date) > 0, "没有符合日期范围的数据哦")) ggplot(projects_selected_date, aes_string(x = input$x, y = input$y)) + geom_point(colour = 'red') # 把颜色参数放到geom层 })
问题2:表格中日期显示为数字
R中的Date类型本质是整数(从1970-01-01开始的天数),renderTable默认会把它转换成数字显示。给你两种解决方法:
方法1:将日期列转为字符格式(快速解决)
在输出表格前,把Deployment.Month转成可读的字符格式:
output$table <- renderTable({ req(input$date) projects_selected_date <- data4 %>% filter(Deployment.Month >= input$date[1] & Deployment.Month <= input$date[2]) %>% mutate(Deployment.Month = as.character(Deployment.Month)) # 转成人类可读的日期字符串 projects_selected_date })
方法2:使用DT包的renderDataTable(推荐)
DT包会自动识别Date类型并正确显示,还自带排序、搜索等实用功能。先安装加载DT:
install.packages("DT") library(DT)
然后修改UI和Server:
- UI里把
tableOutput("table")改成DTOutput("table") - Server里替换成:
output$table <- renderDT({ req(input$date) projects_selected_date <- data4 %>% filter(Deployment.Month >= input$date[1] & Deployment.Month <= input$date[2]) projects_selected_date })
完整修正后的代码示例
把上述修改整合后,完整代码如下(包含两种表格输出方式,按需注释切换):
library(shiny) library(dplyr) library(ggplot2) library(DT) # 用DT的话需要加载 # 先处理你的原始数据 data2$Deployment.Month <- as.Date(data2$Deployment.Month, format = "%d-%m-%Y") # 添加na.rm避免NA值影响日期范围计算 min_date <- min(data2$Deployment.Month, na.rm = TRUE) max_date <- max(data2$Deployment.Month, na.rm = TRUE) data3 <- as.data.frame(data2) data4 <- na.omit(data3) # 定义下拉框选项 choices <- colnames(data4)[!colnames(data4) %in% "Deployment.Month"] ui <- fluidPage( sidebarLayout( sidebarPanel( selectInput(inputId = "x", label = "Variable 1", choices = choices, selected = "Project.Id"), selectInput(inputId = "y", label = "Variable 2", choices = choices), dateRangeInput(inputId = "date", label = "Select dates:", start = "2013-01-01", end = "2017-12-31", startview = "year", min = min_date, max = max_date) ), mainPanel( plotOutput(outputId = "scatterplot"), DTOutput("table") # 用DT的话用这个,否则换成tableOutput("table") ) ) ) server <- function(input, output){ output$scatterplot <- renderPlot({ req(input$date, input$x, input$y) projects_selected_date <- data4 %>% filter(Deployment.Month >= input$date[1] & Deployment.Month <= input$date[2]) validate(need(nrow(projects_selected_date) > 0, "没有符合日期范围的数据哦")) ggplot(projects_selected_date, aes_string(x = input$x, y = input$y)) + geom_point(colour = 'red') }) # 方法1:用renderTable的写法(需要把UI里的DTOutput改回tableOutput) # output$table <- renderTable({ # req(input$date) # projects_selected_date <- data4 %>% # filter(Deployment.Month >= input$date[1] & Deployment.Month <= input$date[2]) %>% # mutate(Deployment.Month = as.character(Deployment.Month)) # projects_selected_date # }) # 方法2:用DT的写法 output$table <- renderDT({ req(input$date) projects_selected_date <- data4 %>% filter(Deployment.Month >= input$date[1] & Deployment.Month <= input$date[2]) projects_selected_date }) } shinyApp(ui = ui, server = server)
最后提两个小细节:
- 计算
min_date和max_date时加na.rm = TRUE,避免原始数据里的NA值导致报错; dateRangeInput里的min和max参数不用再转as.Date,因为min_date已经是Date类型了。
内容的提问来源于stack exchange,提问作者Nitesh Rohilla
相关产品推荐
相关产品推荐

