javascript - 管理用于 HTML Canvas 的对数数组数据

标签 javascript arrays normalization logarithm

我有一个数组中的数据集,范围从 0.00164737 到 0.0021966

What I am trying to do is get the shape fixed by logarithmic scale, then to normalize it ready for drawing on the canvas. Say normalized to 0,100 or -100,0,100 so I can work in pixels

要在 0-100 之间简单地归一化(不执行日志函数),这在 for 循环中非常有效:

normalized[i] = ( ( close[i] - min ) / dif ) * 100;

dif 是封闭数组的最大值减去它的最小值 toFixed(7)

Normalized

我不是数学家,但我认为我对日志部分“有点接近”,尽管我只在规范化期间应用日志函数时看到视觉上的差异。这显然打乱了归一化,它还会产生 Infinity 或 -Infinity 以及非常不必要的大数

Out of view

请注意,图表现在不再以像素为单位进行管理,因为它没有正确地位于 Canvas 上,所以为了看看我做了什么,我在所有 y 点上添加 150 以使其可见

Pushed into view

所以当我这样做时,我通过应用对数函数来破坏/改变同一行上的东西(我知道这部分是错误的)

function logWithBase(n,b){return Math.log(n)/Math.log(b);}

像这样改变行:

normalized[i] = logWithBase( ( close[i] - min ) / dif , 10 ) * 100;

以下是我尝试使其对数化前后的一小部分数据:

之前:

0: "0.00168927"
1: "0.00168742"
2: "0.0016818"
3: "0.00168124"
4: "0.00168067"
5: "0.0016805"
6: "0.00168657"
7: "0.00168362"
8: "0.00166886"
9: "0.00165052"    // < why does 0.00165 cause -Infinity
10: "0.0016647"
11: "0.00166251"
12: "0.00166664"
13: "0.00167196"
14: "0.00167084"
15: "0.00167667"

之后的相同集合:

0: 38.93017025063121
1: 36.805636182304255
2: 29.629674005179268
3: 28.845120702345767
4: 28.03173121401521
5: 27.786162417624155
6: 35.79352647194307
7: 32.08579894397015
8: 6.4429326997987175
9: -Infinity             // < WOW!!
10: -4.729377348896662
11: -12.015082123716525
12: 0.8395033133056131
13: 13.225477668471285
14: 10.8953699275865
15: 21.850168886727374

这里可能有相关线索

如果我得到 min 和 max/2 之间的差异(我可能会因此得到不好的分数)并将其用作我的基础(在我进行简单归一化之前),我会看到图表颠倒...

var logclose = [];

var base = ( Math.max.apply(this,close) - Math.min.apply(this,close) ) / 2;

for( var i = close.length - 1; i >= 0; i-- ){

    logclose[i] = logWithBase( close[i] , base );

    }

close=logclose;

Upside down

结论;我认为最后一个示例说明基数应该以某种方式与数组编号范围相关,因为它确实有影响。

我如何驯服对数而不是大得离谱的数字,然后将其归一化以适合 Canvas 区域?

Please do not recommend I use a library (I prefer vanilla JavaScript where it can be used, plus, I would very much like to grasp this proccess)

编辑,这里是代码:

var close=[data]; // for example data see this question (line: 19) as the full data will not fit here (over 10000 entries)

//###

var max=Math.max.apply(this,close);
var min=Math.min.apply(this,close);
var dif=(max-min).toFixed(7);

var normalclose=[];
var logAttemptClose=[];

function logWithBase(n,b){return Math.log(n)/Math.log(b);}

for(var i=close.length-1;i>=0;i--){

    normalclose[i]=((close[i]-min)/dif)*100;

    logAttemptClose[i]=logWithBase( ( close[i] - min ) / dif , 10 ) * 100; // <-- here bad code
    }

//drawing to canvas
var top=100;
var x=1000-100;
var pen=[];

pen[0]=document.getElementById("chart");
pen[0]=pen[0].getContext("2d");
pen[0].clearRect(0,0,1000,300);
pen[0].beginPath();
pen[0].moveTo(x,normalclose[normalclose.length-1]+top);

for(var i=close.length-1;i>=0;i--){
    x=x-(2);
    pen[0].lineTo(x,normalclose[i]+top);
    }

pen[0].strokeStyle='#000000';
pen[0].stroke();

最佳答案

明白了!

好吧,这不是最好的解决方法,但它确实有效!如果有人可以做得更好,请发帖..

将此添加到上面代码的第 2 行(注释“###”所在的位置):

var Lmax=Math.max.apply(this,close);
var Lmin=Math.min.apply(this,close);
var Ldif=(Lmax-Lmin);
var Logar=[];
var infinity=[];
for(var i=close.length-1;i>=0;i--){
    Logar[i]=Math.log((close[i]-Lmin)/Ldif);
    if(Logar[i]===-Infinity){infinity.push(i);}
    }
close=Logar;

现在我们有了对数尺度的数组,但总有 -Infinity 在某处,所以我们将其删除。在下一行写...

for(var i=0;i<=infinity.length-1;i++){close.splice(infinity[i],1);

然后我们可以继续代码以进行简单的规范化,我们有一个漂亮的新日志图表:

Hacked

关于javascript - 管理用于 HTML Canvas 的对数数组数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25666864/

相关文章:

sql - 向非程序员解释为什么 "Just add another column to the DB"是个坏主意

mysql - mysql规范化数据库中PRIMARY KEY的使用方法

c++ - 如何在 Arduino 上将 HexBytes 数组转换为 C/C++ 中的字符串?

javascript - 使用 Canvas 连接具有相同类的元素

javascript - 当旧日期选择器关闭时打开新日期选择器

javascript - 如何在 react-native 中播放来自 url 的视频文件

javascript - d3 path.line stroke-width with IF 语句/三元运算符

php - 将 mysql 数组结果分配给 php 变量

python - 为了比较信号而标准化互相关的基础知识

javascript - 无法使用 Javascript 在窗口加载时添加带有样式的 div 元素