2011-07-19 52 views
0

我在跟随刻度互动示例@http://mbostock.github.com/protovis/docs/invert.html,我正在试图绘制2线系列图。Protovis刻度互动折线图示例

我的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]}] 

我打算绘制使用日期和使用分别ScoresForA和ScoresForB 2线图的X轴,但感到困惑如何多的调整后也这样做。

我的代码如下:

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

日期仍没有显示出作为x轴,即使我使用的映射函数和数组引用。阅读'日期'属性似乎存在问题。任何建议

错误:类型错误:无法读取属性“日期”的未定义

+0

那又怎么了?你有什么错误吗?也许制作一个[JSFiddle](http://jsfiddle.net/)会帮助你得到答案。 –

回答

1

的第一件事就是在这样一个可视化的工作(尤其是继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对象(这是一个真正的痛苦,如果可能的话避免它)或映射,否则您将无法将它们用作数据他们到数字 - 后者很容易在这里,因为他们在一个普通的系列。 (如果日期间隔不均匀,这一切将会更加复杂,但现在让我们暂时忘记)。您可以使用日期的索引作为x值,然后使用两个序列作为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的预期最大值和最小值的任何假设)。

+0

嗨nrabinowitz,感谢您对这个问题的投入。是的,我正在尝试学习Protovis,并想尝试他们的例子。所以,我尝试了你的方法,并被困在为什么x轴不显示日期的地步。正如你前面提到的,它必须是一个数字而不是字符串,因此,我将日期更改为“日期”:[110,210,310,410,510,610,710,810]。再次,这是为了测试的目的,一旦我得到它的工作,我打算按照你的意见转换它们。 – Queryer

+0

这就是我所做的:/ * X-ticks。 */ vis.add(pv.Rule) .data(函数(d)[d [i] .Dates]) 另一个问题是折线图不显示,点和值分别显示出来。请建议。 – Queryer

+0

很难说没有完整的例子,但你可能没有正确地为你的数据设置x比例 - 范围应该从0到你的最大值(在上面的例子中为810)。如果我是你,我只是使用索引作为数据(例如'pv.range(0,psSeriesData.Dates.length)'),然后将它们映射到标签的日期字符串。 – nrabinowitz