R Shiny中Reactive Plotly绘图异常:pm_cor直线其余系列缺失
R Shiny Plotly多变量显示异常修复方案
问题现象
- 基于每小时更新的CSV文件,在Shiny中使用Reactive Plotly绘制多变量时,仅
pm_cor系列以1:1直线显示,其余系列(pm_a、pm_b、pdiff)全部缺失。 - 控制台抛出警告:
Unknown or uninitialised column: 'pm_a'、Unknown or uninitialised column: 'pm_b'等。
错误原因
- 列名不匹配:执行
pivot_wider(data, names_from = sensor_index, values_from = c(humidity, temperature, pm_a, pm_b, pdiff, pm_cor))后,生成的列名格式为[变量名]_[sensor_index](如pm_a_93325),但绘图代码中仍引用原始列名pm_a、pm_b,导致无法找到对应列。 pm_cor显示异常:因引用了不存在的pm_cor列,Plotly默认将y轴值设为与x轴(date)相同,从而形成1:1直线。
修复步骤
1. 修正绘图代码中的列名引用
将add_trace中的y轴变量改为pivot_wider生成的带后缀列名,如pm_a_93325、pm_b_93325等。
2. 简化数据处理逻辑(可选但推荐)
将重复计算的rowMeans(cbind(pm_a, pm_b), na.rm = TRUE)提前存为变量,提升代码可读性并减少计算冗余。
修复后完整代码
library(shinydashboard) library(plotly) library(readr) library(xts) library(lubridate) library(tidyr) library(dplyr) ui <- dashboardPage( dashboardHeader(title = "Sensors", disable = T), dashboardSidebar( disable = T, sidebarMenu() ), dashboardBody( fluidRow( box(width= 9, title = "Sensors", background = "black", plotlyOutput("plot1")) ), shinyjs::useShinyjs() ) ) percentage_difference <- function(value, value_two) { abs((value - value_two) / ((value + value_two) / 2)) * 100 } server <- function(input, output, session) { ez.read = function(file, ..., skip.rows=NULL, tolower=FALSE) { if (!is.null(skip.rows)) { tmp = readLines(file) tmp = tmp[-(skip.rows)] tmpFile = tempfile() on.exit(unlink(tmpFile)) writeLines(tmp, tmpFile) file = tmpFile } result = read.csv(file, ...) if (tolower) names(result) = tolower(names(result)) return(result) } data <- reactivePoll(1000 * 60 * 15, session, checkFunc = function() { file.info("sensor.csv")$mtime}, valueFunc = function() { data <- ez.read("sensor.csv", tolower = T) data$time_stamp <- as_datetime(data$time_stamp) names(data)[1] <- "date" names(data)[5] <- "pm_a" names(data)[6] <- "pm_b" data$humidity <- as.numeric(data$humidity) # 提前计算pm_a和pm_b的均值,简化后续逻辑 data <- data %>% mutate(pm_mean = rowMeans(cbind(pm_a, pm_b), na.rm = TRUE)) %>% mutate(pm_cor = case_when( abs(pm_a - pm_b) < 5 ~ ifelse(pm_mean < 30, 0.524 * pm_mean - 0.0862 * humidity + 5.75, ifelse(pm_mean < 50, (0.786 * ((pm_mean / 20) - 3/2) + 0.524 * (1 - ((pm_mean / 20) - 3/2))) * pm_mean - 0.0862 * humidity + 5.75, ifelse(pm_mean < 210, 0.786 * pm_mean - 0.0862 * humidity + 5.75, ifelse(pm_mean < 260, (0.69 * ((pm_mean / 50) - 21/5) + 0.786 * (1 - ((pm_mean / 50) - 21/5))) * pm_mean - 0.0862 * humidity * (1 - ((pm_mean / 50) - 21/5)) + 2.966 * (pm_mean / 50 - 21/5) + 5.75 * (1 - (pm_mean / 50 - 21/5)) + 8.84 * 10^-4 * pm_mean^2 * (pm_mean / 50 - 21/5), 2.966 + 0.69 * pm_mean + 8.84 * 10^-4 * pm_mean^2 ) ) ) ), TRUE ~ NA_real_ )) %>% mutate(pdiff = percentage_difference(pm_a, pm_b)) %>% pivot_wider(names_from = sensor_index, values_from = c(humidity, temperature, pm_a, pm_b, pdiff, pm_cor)) data }) output$table <- renderTable(data()) # Plot output$plot1 <- renderPlotly({ plot_data <- data() plot_data <- plot_data %>% arrange(date) fig <- plot_ly() # 使用pivot_wider生成的正确列名 fig <- add_trace(fig, x = plot_data$date, y = plot_data$pm_a_93325, name = "pm_a_93325", type = 'scatter', mode = 'lines') fig <- add_trace(fig, x = plot_data$date, y = plot_data$pm_b_93325, name = "pm_b_93325", type = 'scatter', mode = 'lines') fig <- add_trace(fig, x = plot_data$date, y = plot_data$pdiff_93325, name = "pdiff_93325", type = 'scatter', mode = 'lines') fig <- add_trace(fig, x = plot_data$date, y = plot_data$pm_cor_93325, name = "pm_cor_93325", type = 'scatter', mode = 'lines') fig <- layout(fig, title = "Sensor 93325 Data", xaxis = list(title = "Date"), yaxis = list(title = "Values")) fig }) } shinyApp(ui, server)
验证效果
- 控制台警告消失,所有系列(
pm_a_93325、pm_b_93325、pdiff_93325、pm_cor_93325)均正常显示。 pm_cor系列显示为基于湿度和PM均值计算的正确曲线,不再是1:1直线。
内容的提问来源于stack exchange,提问作者Kyle
相关产品推荐
相关产品推荐

