dev@343: /** dev@343: * Created by lucast on 23/05/2017. dev@343: */ dev@343: dev@343: export function estimatePercentile(matrix, percentile) { dev@343: // our sample is not evenly distributed across the whole data set: dev@343: // it is guaranteed to include at least one sample from every dev@343: // column, and could sample some values more than once. But it dev@343: // should be good enough in most cases (todo: show this) dev@343: if (matrix.length === 0) { dev@343: return 0.0; dev@343: } dev@343: const w = matrix.length; dev@343: const h = matrix[0].length; dev@343: const n = w * h; dev@343: const m = (n > 50000 ? 50000 : n); // should base that on the %ile dev@343: let m_per = Math.floor(m / w); dev@343: if (m_per < 1) { dev@343: m_per = 1; dev@343: } dev@343: dev@343: const sample = []; dev@343: for (let x = 0; x < w; ++x) { dev@343: for (let i = 0; i < m_per; ++i) { dev@343: const y = Math.floor(Math.random() * h); dev@343: const value = matrix[x][y]; dev@343: if (!isNaN(value) && value !== Infinity) { dev@343: sample.push(value); dev@343: } dev@343: } dev@343: } dev@343: if (sample.length === 0) { dev@343: return 0.0; dev@343: } dev@343: sample.sort((a, b) => { return a - b; }); dev@343: const ix = Math.floor((sample.length * percentile) / 100); dev@343: const estimate = sample[ix]; dev@343: return estimate; dev@343: }