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

R生成图表时存在0值导致报错的调整解决方法

问题根因

当查询2021-07-03、分类为ABC的数据时,所有DR0系列字段的数值均为0,代码会删除所有DR0开头的计算字段,导致最终生成的datas对象中Days和Numbers列全为NA,计算坐标轴范围时返回非有限值(Inf)触发报错。

核心修改点

  • 给datas对象增加全NA场景的兜底逻辑,自动填充0值和默认天数
  • 坐标轴范围计算增加非有限值兜底,避免plot函数报错
  • 优化0值场景的绘图逻辑,保证0值红线和标记点正常渲染

修改后完整代码

library(dplyr)
library(tidyr)
library(lubridate)
library(readr)

df1 <- structure(
  list(date1= c("2021-06-28","2021-06-28","2021-06-28"),
       date2 = c("2021-07-01","2021-07-02","2021-07-03"),
       Category = c("BCE","ABC","ABC"),
       Week= c("Wednesday","Thursday","Friday"),
       DR1 = c(11,5,0),
       DR01 = c(10,4,0), DR02= c(2,4,0),DR03= c(0,5,0),
       DR04 = c(2,4,0),DR05 = c(1,6,0)),
  class = "data.frame", row.names = c(NA, -3L))


f1 <- function(dmda, CategoryChosse) {
  
  x<-df1 %>% select(starts_with("DR0"))
  
  x<-cbind(df1, setNames(df1$DR1 - x, paste0(names(x), "_PV")))
  PV<-select(x, date2,Week, Category, DR1, ends_with("PV"))
  
  med<-PV %>%
    group_by(Category,Week) %>%
    summarize(across(ends_with("PV"), median), .groups = "drop")
  
  SPV<-df1 %>%
    inner_join(med, by = c('Category', 'Week')) %>%
    mutate(across(matches("^DR0\\d+$"), ~.x + 
                    get(paste0(cur_column(), '_PV')),
                  .names = '{col}_{col}_PV')) %>%
    select(date1:Category, DR01_DR01_PV:last_col())
  
  SPV<-data.frame(SPV)
  
  mat1 <- df1 %>%
    filter(date2 == dmda, Category == CategoryChosse) %>%
    select(starts_with("DR0")) %>%
    pivot_longer(cols = everything()) %>%
    arrange(desc(row_number())) %>%
    mutate(cs = cumsum(value)) %>%
    filter(cs == 0) %>%
    pull(name)
  
  (dropnames <- paste0(mat1,"_",mat1, "_PV"))
  
  SPV <- SPV %>%
    filter(date2 == dmda, Category == CategoryChosse) %>%
    select(-any_of(dropnames))
  
  
  if(length(grep("DR0", names(SPV))) == 0) {
    SPV[head(mat1, 20)] <- NA_real_
  }
  
  datas <-SPV %>%
    filter(date2 == ymd(dmda)) %>%
    group_by(Category) %>%
    summarize(across(starts_with("DR0"), sum), .groups = "drop") %>%
    pivot_longer(cols= -Category, names_pattern = "DR0(.+)", values_to = "val") %>%
    mutate(name = parse_number(name))
  colnames(datas)[-1]<-c("Days","Numbers")
  
  # 全NA兜底处理
  if(all(is.na(datas$Numbers))){
    # 按现有数据的DR0字段数量生成默认天数,数值设为0
    datas$Days <- 1:length(grep("^DR0\\d+$", names(df1)))
    datas$Numbers <- 0
  } else {
    datas <- datas %>% 
      group_by(Category) %>% 
      slice((as.Date(dmda) - min(as.Date(df1$date1) [
        df1$Category == first(Category)])):max(Days)+1) %>%
      ungroup
  }
  
  m<-df1 %>%
    group_by(Category,Week) %>%
    summarize(across(starts_with("DR1"), mean), .groups = "drop")
  
  m<-subset(m, Week == df1$Week[match(ymd(dmda), ymd(df1$date2))] & Category == CategoryChosse)$DR1
  
  # 坐标轴范围兜底
  maxrange <-  range(0, datas$Numbers, na.rm = TRUE)
  if(!is.finite(maxrange[2])) maxrange[2] <- 20
  else maxrange[2] <- max(datas$Numbers)+ 20
  
  max_days <- max(datas$Days, na.rm = TRUE)
  if(!is.finite(max_days)) max_days <- length(grep("^DR0\\d+$", names(df1)))
  max <- max_days + 1

  # 绘图
  plot(Numbers ~ Days,  xlim= c(0,max),  ylim= c(0,maxrange[2]),
       xaxs='i',data = datas,main = paste0(dmda, "-", CategoryChosse))
  
  # 适配0值场景的红线和点绘制
  if (nrow(datas)<=2 || m == 0){
    abline(h=m,lwd=2, col = "red") 
    points(0, m, col = "red", pch = 19, cex = 2, xpd = TRUE)
    text(.1,m+ .5, round(m,1), cex=1.1,pos=4,offset =1,col="black")
  }

}

# 所有测试用例均可正常运行
f1("2021-07-01", "BCE")
f1("2021-07-02", "ABC")
f1("2021-07-03", "ABC")

效果说明

修改后三类测试场景均可正常生成图表,全0值场景会在0值位置显示对应标记点,同时绘制红色0值水平线,和正常场景的展示效果一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:24:03