圖表y軸的數據處理方案

問題

筆者最近在作圖表需求,遇到一個這樣的問題,圖表的y軸數據處理得不夠好看,以下:javascript

圖表的數據爲1005,1988,2500,3902,5530,很顯然這個處理數據的結果不盡人意。java

方案

既然有這個問題,那麼就須要一個新的處理方案,平時咱們在使用Excel等工具製做的折線圖,會發現上面的數據實際上是處理過的了,以下: 工具

對比可知,爲了讓圖表的數據規整,須要保證間隔的規整,如50,500等數字的倍數,其次是肯定起點,只要肯定好起點,經過間隔的累加便可。因此,對於這個方案有兩個須要處理的,那就是肯定起點min和找間隔interval。

制定需求

對於筆者而言,需求不只包含數據的規整,還有小數位數的格式化,其中涉及到單位的轉換,如初始值給了10345,21200,29001,y軸格式化爲1.0萬,2.0萬,3.0萬,那麼須要對小數位數作處理,使得最後結果爲1萬,2萬,3萬。因此對於筆者而言,找出間隔以後,還須要對最終結果的小數位數作去0操做。ui

步驟

1. 初始值

首先,須要找出數據集的最小值min,最大值max,這裏筆者給出的數據爲min = 47769543,max = 54961473,最多須要保留的小數位數decimal=1。還包含如下須要用到的方法:this

方法名 做用
formatDataByRanges 對數據進行單位轉換處理,如47769534作「萬」處理則爲 4776.9534

2. 計算過程

  1. 肯定起點
    首先計算range = max - min = 7191930,接着對range進行formatDataByRanges處理爲719.1930,而後originInterval = range/4 = 179.798,這時候的originInterval就是沒有處理過的間距值,接下來就是經過range找出規整的間距interval,首先經過range產生一組規整間距值爲1000 500 200 100, 產生的僞代碼以下:
export function genIntervalList(originInterval: number) {
    let base = genPowNum(originInterval)
    return [10 * base, 5 * base, 2 * base, base]
}

// 獲取數字的十的冪次方的位數
// 如 90 則爲 1
 // 如 0.01則爲 -2
function getPowBit(number) {
    return Math.floor(Math.log10(data))
}  

/** * 生成十的冪次方 * @param data */
export function genPowNum(data: number) {
    let bit = getPowBit(data)
    return Math.pow(10, bit)
}

複製代碼

接着從第二個數開始遍歷1000 500 200 100, 當找到大於originInterval的數時則中止,獲取當前點的上一個數爲咱們所需的interval,如179.798 > 100, 那麼interval就爲200。而後經過interval對min作處理,固然這裏的min也通過處理爲4776.9543,處理過程以下:spa

function handleMin(min, interval) {
    if(min < interval) {
        return 0
    } else {
         let baseNum = genPowNum(interval) * 10
       // 去掉最小值不須要比較的位數 
       // 如min爲4776.9543 interval爲200 那麼formatMin = 4000
       // 如min爲0.073 interval爲0.005 那麼formatMin = 0.07
         let formatMin = Math.floor(min / baseNum) * baseNum
         let minRange = min - formatMin
         
          // 找出適合的interval 這裏爲500
        // 因此最後的min = 4000 + 500 = 4500
         return formatMin + this.findMinInterval(minRange, interval)
    }
}

  function findMinInterval(minRange: number, interval: number) {
        let factorList = genIntervalList(interval)
        for (let i = 1; i < factorList.length; i++) {
            if (minRange >= factorList[i]) {
                return factorList[i]
            }
        }
        return 0
    }
複製代碼

通過上述的處理,可得最小值爲4500code

  1. 找間距
    因爲通過步驟1肯定了min,min已經改變了,因此range須要從新計算,interval也須要從新計算。計算方式參考步驟1的找間距,計算可得interval爲500。orm

  2. 最終計算
    通過步驟1,2能夠獲得min和interval,若是此時min< interval,那麼須要令min = 0,而後從新執行步驟2。這樣就能夠獲得最後的min,interval,接着須要計算最後須要保留的小數位數,以下:cdn

function getDecimal(interval, min) {
   if(interval < 1) {
       return  Math.abs(getPowBit(interval))
   } else {
       // 若是間距的range和max相等 則不須要保留小數位數
       // 如interval是1500萬 max是4000萬 range都爲萬 不須要保留小數
       if(interval.range = max.range) {
           return 0
       } else {
             // 當range不相等的狀況 可知min必定大於formatInterval
             // 如min爲121.1萬 interval爲2000 這時候對2000作range的處理
             // 則可獲得最大須要保留的位數
           return Math.abs(getPowBit(formatInterval / formatMinData.range))
       }
   }
}
複製代碼
  1. 最後結果
    最後可得y軸的數據爲4500萬 5000萬 5500萬 6000萬 6500萬

總結

對於這個方案,在於肯定min和interval,對於interval而言,則能夠本身靈活定義規整的間距,如520取的是550,而不是1000,這樣的好處是可讓圖表的走勢更加明顯。blog

相關文章
相關標籤/搜索