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

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'等。

错误原因

  1. 列名不匹配:执行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,导致无法找到对应列。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:34:54