我制作了一个网站,用于绘制用户从大型馆藏中挑选的数据集。为了对图表进行标准化(用户选项),我找到了每个数据集的max(y),并且我试图将其用作line().y()
中的分母但我无法做到找出一个好方法。
数据集是csvs,它们都是这样的:
site0586,id,depth,age,sed,quant,conc,influx,level
1, 94297, 0.1400, 8.390, 0.097, 50.5100, 50.5100, 4.87496, "C0P0"
2, 94298, 0.1760, 45.690, 0.083, 52.5800, 52.5800, 4.35011, "C0P0"
3, 94299, 0.2030, 73.660, 0.135, 29.8500, 29.8500, 4.03080, "C0P0"
...
默认的x和y是"年龄"和#34; conc"但是用户可以选择。用户选择数据集并将它们一个接一个地绘制在同一个图形上。随着图的添加,图表的比例调整以适应整体max-x和max-y以及更早的图表更新以符合。 X可以在数据集之间变化很好,并且y可以变化五个数量级,因此小值线可以得到相当大的压缩。通过一点过渡实现这一目标,并且效果很好。
有时用户希望看到带有[0,1]归一化的y,因此小值趋势将在与大值的x尺度相同的x尺度上显示;这是一个选择。轻松 - 将y域重置为[0,1]并将每个图表划分为该数据集的最大值(y)。对于完美运作的点;因为我遇到了很多麻烦。
这是一张图,所以我构建了一个数据结构;当用户选择我下载的每个数据集时,nest()
并将其推送到数组上,因为我以后需要最大值,而我在那里找到每个变量的域,将它们放在一个名为heads
的对象中,并将其附加到嵌套数据中。所以我的数据结构如下所示:
datae: [
{ "key": "300",
"values": [
{"site0300": 1, "id": 60383, "depth": 0, ... }, ...
{"site0300": 182, ... }
],
"heads": { "depth": [0,5.9], "age": [107.4,16589.5], ...}
},
{ "key": "586",
"values": [
{"site0586": 1, ...}, ...
],
"heads": {...}
}
]
我已将line().y()
设置为(可能)使用可能为1或thisData.max(y)的分母:
var lineFn = d3.svg.line()
.x(function(d) { return xScale(d[xVar]) })
.y(function(d) { return yScale(d[yVar]/normer) });
除了我无法弄清楚如何将datae[thisLineIdx].heads[yVar[1]]
加入通话:
var lines = graf.selectAll('.line')
.data(datae);
lines.enter()
.append('path')
.attr("d", function(d) { return lineFn(d.values) })
lines
的每个成员从datae
获得正确的条目,但由于svg.line()只想听听数组(并且不会从内部传达任何内容),它只会如果我用datae [thisLineIdx] .values调用它,然后datae [thisLineIdx] .heads是不可访问的。
我可以将所有datae [idx] .heads设置为全局但是必须有一个更好的方法 - 我只是无法看到任何方法从行内计算max(y)( ),也没有任何惯用的方式将其包括在电话中。
答案 0 :(得分:0)
Ach - duh!因为年龄而被困在这(一周一天),并且一直在那里。现在最后一个代码块出现了:
var lines = graf.selectAll('.line')
.data(datae);
lines.enter()
.append('path')
.attr("d", function(d) {
normer = gOpts.normIt.state ? d.heads[yVar][1] : 1;
return lineFn(d.values) })
现在我的lineFn()做了我想要的,当我想要的时候。
但是,我不喜欢这个解决方案,因为它确实让normer
(在更高级别声明)以半全局方式漂浮在相关范围之外,准备引起其他一些恶作剧。所以我认为这是一种愚蠢的方式,如果有人能提出更复杂的建议,我将非常感激。