nvd3散点图与序数比例

dgo*_*sen 6 javascript scatter-plot ordinal d3.js nvd3.js

我相对较新的d3和nvd3,并希望创建一个简单的散点图,就像示例,但有一个序数 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;
});
Run Code Online (Sandbox Code Playgroud)

但是,没有运气:

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 
..
Run Code Online (Sandbox Code Playgroud)

并且y轴简单地显示从-1到1的线性轴.尽管有一些圆圈在y = -1和y = 1(极值)处绘制.

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

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

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

在github上有一个相关的问题,但没有解决方案.


更新:经过一些调试我尝试更换chart.yAxis.scale(ys),chart.scatter.y(ys)这摆脱了错误.我也可以放弃手册selectAll.

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

And*_*rei 6

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

chart.xAxis.tickFormat(function(d){
            return labelValues[d];
        });
Run Code Online (Sandbox Code Playgroud)

其中labelValues在数值和所需标签之间映射.


cke*_*sch 1

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

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

此比例会将我的域映射到 1:5 范围内的数字,其中“this”-> 1、“is”-> 2 等。如果我不想单独设置每个点,我也可以定义我的范围与 rangePoints 一起,如下:

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

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

我在这里画了一些圆圈来说明如何做到这一点

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

另一种选择是在函数定义中应用比例。

yfun = function (d) { return ys(d.Title) } 
Run Code Online (Sandbox Code Playgroud)