Search code examples
javascriptlogarithm

Calculating the length of a segment in a logarithmic scale


I want to calculate the length of a line for a series of events.

I'm doing this with the following code.

var maxLineLength = 20;
var lineLen = function(x, max) {
    return maxLineLength * (x / max);
}
var events = [0.1, 1, 5, 20, 50];
var max = Math.max.apply(null, events);
events.map(function (x) {
    console.log(lineLen(x, max));
});

This works, but I'm using linear scaling, while I'd like to use logarithms, because I don't want small events to become too small numbers when big ones are present.

I modified the lineLen function as you can see below, but - obviously - it doesn't work for events equals to one, because the log of one is zero. I want to show events equals to one (opportunely scaled) and not make them become zero. I also need positive numbers to remain positive (0.1 becomes a negative number)

How should I modify lineLen to use a logarithmic scale?

var maxLineLength = 20;
var lineLen = function(x, max) {
   return maxLineLength * (Math.log(x) / Math.log(max));
}
var events = [0.1, 1, 5, 20, 50];
var max = Math.max.apply(null, events);
events.map(function (x) {
    console.log(lineLen(x, max));
});


Solution

  • You can take log(x+1) instead of log(x), that doesn't change the value too much and the ratios are maintained for smaller numbers.

    var maxLineLength = 20;
    var lineLen = (x, max) => maxLineLength * Math.log(x+1)/Math.log(max+1);
    var events = [ 0.1, 1, 5, 20, 50];
    var visualizer = function(events){
        var max = Math.max.apply(null, events);
        return events.reduce((y, x) => {
             y.push(lineLen(x, max));
             return y;
        }, []);
    };
    
    console.log(visualizer(events));