2016-03-31 19 views
1

現在、私はd3プロジェクトで作業していますが、誇大とマイナスの両方の膨大な値を持つ棒グラフを表示しようとしています。d3js - カスタムスケールを作成する - 正と負の対数

私はd3.scale.sqrt()を使用してウォークアラウンドを見たり、2つのログスケールを表示しましたが、独自のスケールを作成できるかどうかは疑問でした。

負の値のログスケールと[-e、e]の間の値の線形スケールと正の値の通常のログスケールのミックスです。そのように見えるかもしれません 何か:あなたはそれが可能かもしれないとhttp://img15.hostingpics.net/pics/12746197ln.png

y = -log(-x) if x < -e 
y = x/e  if -e <= x <= e 
y = log(x) if x > e 

思いますか? 私はJSFiddleも作成しました。

おかげで、

答えて

0

はここで私が見つけた一つの解決策である:JSFiddle

それはあるかもしれない奇妙な方法、私はあなたが改善のアドバイスの任意の部分を持っている場合は、躊躇しないで、考えて取り組んでいます。私は間違いを犯したと思う、特にログベースとダニで。

ここには、d3.js自体に基づいて作成した関数があります。

(function() { 
    scalepnlog = { 
    init: function(){ 
     return d3_scale_pnlog(d3.scale.linear().domain([ 0, 1 ]), [ 1, 10 ]); 
    } 
    } 
    function d3_scaleExtent(domain) { 
    var start = domain[0], stop = domain[domain.length - 1]; 
    return start < stop ? [ start, stop ] : [ stop, start ]; 
    } 
    var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { 
    floor: function(x) { 
     return -Math.ceil(-x); 
    }, 
    ceil: function(x) { 
     return -Math.floor(-x); 
    } 
    }; 
    function sign(x){ 
    return x >= 0 ? 1:-1; 
    } 


    function d3_scale_pnlog(linear, domain) { 
    function pnlog(x) { 
     return (x >= Math.E || x <= -Math.E) ? sign(x)*Math.log(Math.abs(x)) : x/Math.E; 
    } 
    function pnpow(x) { 
     return (x >= 1 || x <= -1)? sign(x)*Math.pow(Math.E,Math.abs(x)) : Math.E*x; 
    } 
    function scale(x) { 
     return linear(pnlog(x)); 
    } 
    scale.invert = function(x) { 
     return pnpow(linear.invert(x)); 
    }; 
    scale.domain = function(x) { 
     if (!arguments.length) return domain; 
     linear.domain((domain = x.map(Number)).map(pnlog)); 
     return scale; 
    }; 
    scale.nice = function() { 
     var niced = d3_scale_nice(domain.map(pnlog), positive ? Math : d3_scale_logNiceNegative); 
     linear.domain(niced); 
     domain = niced.map(pow); 
     return scale; 
    }; 
    scale.ticks = function() { 
     var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(pnlog(u)), j = Math.ceil(pnlog(v)), n = 10 % 1 ? 2 : 10; 
     if (isFinite(j - i)) { 
     for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pnpow(i) * k); 
     ticks.push(pnpow(i)); 
     for (i = 0; ticks[i] < u; i++) {} 
     for (j = ticks.length; ticks[j - 1] > v; j--) {} 
     ticks = ticks.slice(i, j); 
     } 
     return ticks; 
    }; 
    scale.tickFormat = function(n, format) { 
     if (!arguments.length) return d3_scale_logFormat; 
     if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); 
     var k = Math.max(1, 10 * n/scale.ticks().length); 
     return function(d) { 
     var i = d/pnpow(Math.round(pnlog(d))); 
     if (i * 10 < 10 - .5) i *= 10; 
     return i <= k ? format(d) : ""; 
     }; 
    }; 
    scale.copy = function() { 
     return d3_scale_pnlog(linear.copy(), domain); 
    }; 
    return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); 
    } 
})(); 

は、私は本当に私がやっているかわからないが、基本的に、私はその逆数pnlogpnpowを作成し、それが働いたまで、必要に応じ異なるD3の機能を追加しました。

ここで彼らは、次のとおりです。

function pnlog(x) { 
    return (x >= Math.E || x <= -Math.E) ? sign(x)*Math.log(Math.abs(x)) : x/Math.E; 
} 

function pnpow(x) { 
    return (x >= 1 || x <= -1)? sign(x)*Math.pow(Math.E,Math.abs(x)) : Math.E*x; 
} 
関連する問題