0

スケールの相互作用の例@http ://mbostock.github.com/protovis/docs/invert.htmlに従って、 2本の線の系列グラフを描画しようとしています。

私のJSONファイルは次のとおりです。

var psSeriesData =
    [{"Dates":["1-10","2-10","3-10","4-10","5-10","6-10","7-10","8-10"],"ScoresForA":    
    [78.78,79.79,78.78,78.78,78.78,79.79,79.79,76.92],"ScoresForB":
    [78.78,79.79,78.78,78.78,78.78,79.79,79.79,76.92]}]

日付を使用してx軸をプロットし、ScoresForAとScoresForBをそれぞれ使用して2つの折れ線グラフをプロットするつもりですが、多くの調整を行った後、その方法がわかりません。

私のコードは次のとおりです。

                var data = pv.range(2).map(function(i) {
                    return pv.range(0, 10, .1).map(function(x) { 
                        return {x: psSeriesData.Dates, y: psSeriesData.ScoresForA,ScoresForB  };
                    });
                });

                /* Chart dimensions and scales. */
                var w = 400,
                h = 200,
                x = pv.Scale.linear(0, 9.9).range(0, w),
                y = pv.Scale.linear(0, 10).range(0, h),
                i = -1;

                /* The root panel. */
                var vis = new pv.Panel()
                .width(w)
                .height(h)
                .bottom(20)
                .left(20)
                .right(10)
                .top(5);

                /* Y-ticks. */
                vis.add(pv.Rule)
                .data(pv.range(100))
                .visible(function() !(this.index % 2))
                .bottom(function(d) Math.round(y(d)) - .5)
                .strokeStyle(function(d) d ? "#eee" : "#000")
                .anchor("left").add(pv.Label)
                .text(function(d) (d * 10).toFixed(0) );

                /* X-ticks. */
                vis.add(pv.Rule)
                .data(x.ticks())
                .visible(function(d) d > 0)
                .left(function(d) Math.round(x(d)) - .5)
                .strokeStyle(function(d) d ? "#eee" : "#000")
                .anchor("bottom").add(pv.Label)
                .text(function(d) d.toFixed());

                /* A panel for each data series. */
                var panel = vis.add(pv.Panel)
                .data(data);

                /* The line. */
                var line = panel.add(pv.Line)
                .data(function(d) d)
                .left(function(d) x(d.x))
                .bottom(function(d) y(d.y))
                .lineWidth(3);

                /* The mouseover dots and label. */
                line.add(pv.Dot)
                .visible(function() i >= 0)
                .data(function(d) [d[i]])
                .fillStyle(function() line.strokeStyle())
                .strokeStyle("#000")
                .size(20)
                .lineWidth(1)
                .add(pv.Dot)
                .left(10)
                .bottom(function() this.parent.index * 12 + 10)
                .anchor("right").add(pv.Label)
                .text(function(d) (d.y * 10).toFixed(5));

                /* An invisible bar to capture events (without flickering). */
                vis.add(pv.Bar)
                .fillStyle("rgba(0,0,0,.001)")
                .event("mouseout", function() {
                    i = -1;
                    return vis;
                })
                .event("mousemove", function() {
                    var mx = x.invert(vis.mouse().x);
                    i = pv.search(data[0].map(function(d) d.x), mx);
                    i = i < 0 ? (-i - 2) : i;
                    return vis;
                });



                vis.render();

私は何が間違っているのですか?

入力がnrabinowitzによって与えられた後:

     var psSeriesData = {
  "Dates": ["1/10","2/10","3/10","4/10","5/10","6/10","7/10","8/10"],
  "ScoresForA": [78.78,79.79,78.78,78.78,78.78,79.79,79.79,76.92],
  "ScoresForB": [78.78,79.79,78.78,78.78,78.78,79.79,79.79,76.92]
};

                // start by iterating over the two keys for your time series data
                var data = ["ScoresForA","ScoresForB"].map(function(seriesKey) {
                    // use pv.range to walk through the indexes of the
                    // date array (basically the same as a for loop)
                    return pv.range(0, psSeriesData.Dates.length)
                    // map these indexes to an array of objects
                    .map(function(dateIndex) {
                        // now return an object with the date index
                        // and series value for that index
                        return {
                            x: dateIndex,
                            y: psSeriesData[seriesKey][dateIndex]
                        }
                    });
                });


                /* Chart dimensions and scales. */
                var w = 400,
                h = 200,
                x = pv.Scale.linear(0, 9.9).range(0, w),
                y = pv.Scale.linear(0, 10).range(0, h),
                i = -1;

                /* The root panel. */
                var vis = new pv.Panel()
                .width(w)
                .height(h)
                .bottom(20)
                .left(20)
                .right(10)
                .top(5);

                /* Y-ticks. */
                vis.add(pv.Rule)
                .data(pv.range(100))
                .visible(function() !(this.index % 2))
                .bottom(function(d) Math.round(y(d)) - .5)
                .strokeStyle(function(d) d ? "#eee" : "#000")
                .anchor("left").add(pv.Label)
                .text(function(d) (d * 10).toFixed(0) );

                /* X-ticks. */
                vis.add(pv.Rule)
                //.data(function(d) [d[i].Dates])
                .data(pv.range(0, psSeriesData.Dates.length).map(function(a) (psSeriesData[a].Dates)))
                .visible(function(d) d > 0)
                .left(function(d) Math.round(x(d)) - .5)
                .strokeStyle(function(d) d ? "#eee" : "#000")
                .anchor("bottom").add(pv.Label)
                .text(function(d) (d).toFixed());

                /* A panel for each data series. */
                var panel = vis.add(pv.Panel)
                .data(data);

                /* The line. */
                var line = panel.add(pv.Line)
                .data(function(d) d)
                .left(function(d) x(d.x))
                .bottom(function(d) y(d.y))
                .lineWidth(3);

                /* The mouseover dots and label. */
                line.add(pv.Dot)
                .visible(function() i >= 0)
                .data(function(d) [d[i]])
                .fillStyle(function() line.strokeStyle())
                .strokeStyle("#000")
                .size(20)
                .lineWidth(1)
                .add(pv.Dot)
                .left(10)
                .bottom(function() this.parent.index * 12 + 10)
                .anchor("right").add(pv.Label)
                .text(function(d) (d.y ).toFixed(5));

                /* An invisible bar to capture events (without flickering). */
                vis.add(pv.Bar)
                .fillStyle("rgba(0,0,0,.001)")
                .event("mouseout", function() {
                    i = -1;
                    return vis;
                })
                .event("mousemove", function() {
                    var mx = x.invert(vis.mouse().x);
                    i = pv.search(data[0].map(function(d) d.x), mx);
                    i = i < 0 ? (-i - 2) : i;
                    return vis;
                });



                vis.render();

map関数と配列参照を使用したにもかかわらず、日付がx軸として表示されません。'Dates'プロパティの読み取りに問題があるようです。アドバイス

エラー:TypeError:未定義のプロパティ'日付'を読み取ることができません

4

1 に答える 1

2

このような視覚化で作業するとき(特にProtovisの例に従うとき)に最初に行うことは、データが必要な形式であることを確認することです。ここですべてのコードを確認したわけではありませんが、データに関するいくつかの明確な問題があります。

  • 初期データが配列に含まれているのはなぜですか?囲んでいるストレートブレース(つまり、の外側のブラケット)を含める理由はありますpsSeriesData = [{ ... }]か?あなたがそれを提示したときに私がコードで見ることができるこれの理由はありません、そしてそれは物事を混乱させるだけです(例えばpsSeriesData.Dates未定義-あなたは参照する必要があるでしょうpsSeriesData[0].Dates)。

  • 私はあなたが最初のデータセットアップコードで何をしているのか全くわかりませんが、それがあなたが望むものをあなたに与えていないことはかなり確信しています-それは例からのブラインドカットアンドペーストのようにさえ見えます適用されませんが。この例では、pv.range偽のデータを生成するために使用しています。これは必要ありません。実際のデータがあり、代わりにこれをウォークスルーできます。

ここから始める最良の方法は、データがどのように見えるかを理解することです。この例では、データは次のように生成されます。

data = pv.range(3).map(function(i) {
    return pv.range(0, 10, .1).map(function(x) {
        return {x: x, y: i + Math.sin(x) + Math.random() * .5 + 2};
    });  
});

これをコンソールで実行すると、生成されるデータは次のようになります。

[
    [
        {
            x: 0.1,
            y: 2.34
        },
        // ...
    ],
    // ...
]

外側の配列は、異なる時系列を保持します。各時系列は、のようなオブジェクトの配列です{x:0.1, y:2.34}。データがこのように見えない場合、サンプルコードでは機能しません。

これには初期データが正常に機能するはずですが、正しい形式にする必要があります。Dateここでの問題の1つは、日付のリストです。これらは数値ではなく文字列であり、オブジェクトに変換するか(これは非常に面倒です。可能であれば避けてください)、マップしない限り、データとして使用することはできません。数字に-後者は通常のシリーズであるため、ここでは簡単です。(日付の間隔が不均等な場合、これはすべてより複雑になりますが、今のところそれを忘れましょう。)日付のインデックスxを値として使用し、次に2つの系列をy値として使用できます。

これをすべてまとめると、次のようにデータをフォーマットできます。

// note - no enclosing array
var psSeriesData = {
  "Dates": ["1-10","2-10","3-10","4-10","5-10","6-10","7-10", "8-10"], 
  "ScoresForA": [78.78,79.79,78.78,78.78,78.78,79.79,79.79,76.92],
  "ScoresForB": [78.78,79.79,78.78,78.78,78.78,79.79,79.79,76.92]
};

// start by iterating over the two keys for your time series data
var data = ["ScoresForA","ScoresForB"].map(function(seriesKey) {
        // use pv.range to walk through the indexes of the
        // date array (basically the same as a for loop)
        return pv.range(0, psSeriesData.Dates.length)
            // map these indexes to an array of objects
            .map(function(dateIndex) {
                // now return an object with the date index 
                // and series value for that index
                return {
                    x: dateIndex,
                    y: psSeriesData[seriesKey][dateIndex]
                }
            });
});

これを行う方法は他にもたくさんありますが、重要な点は、次のような配列を作成することです[[{x:0, y:79.79}, ...], ...]。残りのコードは確認していませんが、データが正しい形式になっているので、例の偽のデータをコードの実際のデータに置き換えて、すべてを次のように機能させることができます。期待される(ただし、との期待される最大値と最小値に関する例の仮定を変更する必要がありますxy

于 2011-07-19T19:43:43.130 に答える