src/forecast.js
// KDE which doesn't get wider, just taller
KDE which doesn't get wider, just taller
KDE which doesn ' t get wider just taller
function kde(XW, opts={}) {
  opts = Object.assign({hp:.1, hf: null, n: 80}, opts)
  let {hp, hf, n} = opts
  const norm = gaussian(0, 1)
  const minV = d3.min(XW, d => d[0])
  const maxV = d3.max(XW, d => d[0])
  if (!hf) {
    hf = Math.max(maxV - minV, 0.00001)
  }
  const ppf = .999
  const widthSc = norm.ppf(ppf)*2
  const h = widthSc/(hp*hf)
  const rangeValues = []
  for (const [x, w] of XW) {
    const value = norm.ppf(ppf)/h
    rangeValues.push(x + value)
    rangeValues.push(x - value)
  }
  const domain = d3.extent(rangeValues)
  const step = (domain[1] - domain[0]) / n
  const sc = 1 / (norm.pdf(0)*XW.length)
  const vs = []
  const kernelVs = []
  for (let a = domain[0]; a < domain[1]; a += step) {
    let totalV = 0
    for (const [i, [x, w]] of XW.entries()) {
      const v = sc * w * norm.pdf(h*(a - x))
      totalV += v
      kernelVs.push({v: a, p: v, k: i})
    }
    vs.push({v: a, p: totalV})
  }
  return {ps: vs, kernelPs: kernelVs}
}
function kde ( XW , opts = { } ) { opts = Object . assign ( { hp : .1 , hf : null , n : 80 } , opts ) let { hp , hf , n } = opts const norm = gaussian ( 0 , 1 ) const minV = d3 . min ( XW , d => d [ 0 ] ) const maxV = d3 . max ( XW , d => d [ 0 ] ) if ( ! hf ) { hf = Math . max ( maxV - minV , 0.00001 ) } const ppf = .999 const widthSc = norm . ppf ( ppf ) * 2 const h = widthSc / ( hp * hf ) const rangeValues = [ ] for ( const [ x , w ] of XW ) { const value = norm . ppf ( ppf ) / h rangeValues . push ( x + value ) rangeValues . push ( x - value ) } const domain = d3 . extent ( rangeValues ) const step = ( domain [ 1 ] - domain [ 0 ] ) / n const sc = 1 / ( norm . pdf ( 0 ) * XW . length ) const vs = [ ] const kernelVs = [ ] for ( let a = domain [ 0 ] ; a < domain [ 1 ] ; a += step ) { let totalV = 0 for ( const [ i , [ x , w ] ] of XW . entries ( ) ) { const v = sc * w * norm . pdf ( h * ( a - x ) ) totalV += v kernelVs . push ( { v : a , p : v , k : i } ) } vs . push ( { v : a , p : totalV } ) } return { ps : vs , kernelPs : kernelVs } }
KDE which doesn't get wider, just taller
KDE which doesn ' t get wider just taller