nvd3散点图与序数比例

时间:2013-06-25 12:08:58

标签: javascript d3.js scatter-plot nvd3.js ordinal

我对d3和nvd3比较陌生,想要创建一个简单的散点图,就像example但是有ordinal y轴一样。所以y轴值是分类字符串。这就是我认为我需要做的事情:

var xfun = function (d) { return d.Pos }    //simple ints
  , yfun = function (d) { return d.Title }  //the ordinal values

var chart = nv.models.scatterChart()
    .showDistX(true)
    .showDistY(true)
    .color(d3.scale.category10().range())
    .margin({ top: 30, right: 20, bottom: 50, left: 130 })
    .tooltips(false)
    .x(xfun)   
    .y(yfun);

// create an ordinal scale with some test values
var ys = d3.scale.ordinal()
    .domain(["this","is","an","ordinal","scale"])
    .range(5);

// tell nvd3 to use it
chart.yAxis.scale(ys);

// add to the page
nv.addGraph(function () {
    d3.select(selector).datum(data).transition().duration(500).call(chart);
    nv.utils.windowResize(chart.update);
    return chart;
});

然而,没有运气:

Error: Invalid value for <circle> attribute cy="NaN" d3.js:690
Error: Invalid value for <line> attribute y1="NaN" d3.js:690
Error: Invalid value for <line> attribute y2="NaN" d3.js:690
Error: Invalid value for <circle> attribute cy="NaN" d3.js:7532
Uncaught TypeError: Cannot read property '0' of undefined 
..

y轴只显示从-1到1的线性轴。有趣的是,在y = -1和y = 1(极值)处绘制了一些圆圈。

手动强制使用cy的正确值我尝试在调用后添加(图表):

d3.selectAll("#mychart circle").attr("cy", function(d){
        return = ys(yfun(d));
        });

但仍然是同样的错误。如何让序数量表正常工作?注意当我使用nvd3图例在数据集之间切换(包含不同的x / y数据)时,我还需要它才能正确更新。

github上有related question,但没有解决方案。


更新:经过一些调试后,我尝试将chart.yAxis.scale(ys)替换为chart.scatter.y(ys),这样可以消除错误。我也可以删除手册selectAll

然而,y轴仍显示0.99-1.01的线性标度,所有点均绘制在y = 1。所以更接近但没有顺序尺度。

3 个答案:

答案 0 :(得分:6)

如果其他人偶然发现这个问题,这对我有用:不是试图在轴上强制按顺序刻度(X,在我的情况下),我使用线性刻度,但提供了返回的自定义tickFormat函数所需的标签。

chart.xAxis.tickFormat(function(d){
            return labelValues[d];
        });

其中labelValues在数值和所需标签之间进行映射。

答案 1 :(得分:2)

solution可以轻松@robinfhu

不要使用有序量表!

相反,设置x函数以返回元素的索引:

chart.x(function(d,i){ return i;})

并设置tickFormat功能以阅读正确的标签:

tickFormat(function(d) {return that.data[0].values[d].x;})

工作示例Plunker

复制并粘贴:

  nv.models.lineChart()
    .x(function(d, i) {
      return i;
    }).xAxis
    .tickFormat(function(d) {
      return that.data[0].values[d].x;
    });

答案 2 :(得分:1)

我没有使用过nvd3.js,但根据我的d3经验,错误似乎是你的规模范围。对于序数比例,您需要为要映射的域定义相应值的数组。例如,我可以设置以下比例:

var myScale = d3.scale.ordinal()
    .domain(['this','is','an','ordinal','scale'])
    .range([1,2,3,4,5])

这个比例会将我的域名映射到1:5范围内的数字,并带有'this' - &gt; 1,'是' - &gt;如果我不想单独设置每个点,我也可以使用rangePoints定义我的范围,如下所示:

var myScale = d3.scale.ordinal()
    .domain(['this','is','an','ordinal','scale'])
    .rangePoints([1,5])

rangePoints为我提供了从最小指定值到最大指定值的均匀间隔范围,因此这将导致生成相同的范围。

我已经制作了一些圈子来说明如何执行此操作here.

当您更改为其他数据系列时,您必须更新您的域。由于范围对应于您的点所映射到的页面上的位置,因此您不需要更新它,除非nvd3.js应用辅助映射并且执行ordinalDomain - &gt;整数 - &gt; pointLocation分两步进行。

另一种选择是在功能定义中应用比例。

yfun = function (d) { return ys(d.Title) }