2013-06-25 21 views
6

比較的新しいd3とnvd3で、exampleのように単純な散布図を作成したいと考えていましたが、y軸はordinalです。したがって、y軸の値はカテゴリ文字列です。これは私が私が行うために必要と思ったものです:nvd3散布図

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軸は、単にIterestinglyいくつかの円がある-1から1の直線軸を示していませんy = -1およびy = 1(極値)でプロットされている。

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

それでも同じエラー:手動Iは、コール(チャート)の後に追加しようとしたCYの正しい値を強制的に

。順序尺度を正しく機能させるにはどうすればよいですか?注:nvd3凡例を使用してdataseries(異なるx/yデータを含む)を切り替えるときにも、正しく更新する必要があります。

githubにはrelated questionがありますが、解決策はありません。


更新:いくつかのデバッグの後、私はchart.scatter.y(ys)chart.yAxis.scale(ys)を交換しようと、これはエラーを取り除きます。マニュアルselectAllを削除することもできます。

しかし、y軸は依然として0.99-1.01の直線尺度を示し、すべての点はy = 1にプロットされています。だから一歩近づいているが、序数はまだない。

+0

uは、元scaterrplotを視察している... uは参照円は円ではありません。彼らは円形の道drwanです:) –

+0

@Dom:そうかもしれないが、それでもまだsvg 要素について不平を言って、私は間違いなくドムのように見えるかもしれません(しかし、すべてcyのNaN値を持つ) – dgorissen

答えて

1

私はnvd3.jsを使用していませんが、私のd3の経験から、エラーはあなたの縮尺の範囲のようです。序数のスケールでは、マッピングするドメインに対応する値の配列を定義する必要があります。場合など、> 2 - > 1、「ある」 - 「これは」で5、このスケールはレンジ1の番号に自分のドメインをマップする

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

:たとえば、私は以下のスケールを設定することができます

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

rangePointsが最大指定した値に最小規定値から私にポイントの等間隔の範囲を与え、次のように私は、私もrangePointsと私の範囲を定義することができ、個別に各ポイントを設定したくありませんでしたこのため、同じ範囲が生成されます。

私はあなたが別のデータ系列に変更すると、あなたのドメインを更新する必要があります。このhere.

を行う方法を説明し、いくつかの円を作りました。 nvd3.jsがセカンダリマッピングを適用し、ordinalDomain - > integers - > pointLocationを2つのステップで実行しない限り、範囲はページ上のどこにマッピングされているかに対応するため、ポイントを更新する必要はありません。

もう1つのオプションは、関数定義にスケールを適用することです。この時にケースの他の誰かつまずくで

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

ありがとう。私はそれも試みたが、運がなかった。上記の編集を参照してください。この問題はこれよりも早い、つまりnvd3に最初の序列を実際に使用するようになっているようです。ダイナミック・シリーズ・スイッチングに関して、nvd3は、マルチバーの例でこれをそのままの状態で提供します(序数データも含む)。だから私はそれが散布図でも動作するはずだと思います。 – dgorissen

+1

あなたはnvd3で何を意味しているのか分かります。 1つの可能性は、元の関数でysを使用してnvd3がそれらを見る前に値を変更することです。私は上記の投稿にそれを行う方法を追加しました。 – ckersch

+1

実際、その場合、私はnvd3からその序数のスケールを隠し、ちょうど整数を返します。これは実際に働き、私が今持っていることです。私は手動で目盛りを上書きしようとすることができましたが、すべてが大規模なハックのように感じる:) nvd3側でgithubの問題も作成しました。https://github.com/novus/nvd3/issues/177 – dgorissen

6

、ここに私のために働いていたものです:代わりに、軸(私の場合はX、)上の順序尺度を強制しようとしているのは、私はリニアスケールを使用しますが、カスタムを提供目的のラベルを返したtickFormat関数。

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

ここで、labelValuesは数値と目的のラベルの間をマッピングします。

+0

はい。今、ラベルを垂直に回転させる方法を理解する必要があります。 – subsci

+0

'chart.xAxis.rotateLabels(90)'は、ラベルを必要に応じて回転させますが、重なりを避けるライブラリのラベル隠蔽アルゴリズムにはn番目のラベルのみが表示されます。私の場合、すべての7番目のラベルがレンダリングされます。 – subsci

+0

このような「数値と希望するラベルの間のマップ」の例を提供できますか? –

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; 
    });