2011-07-19 53 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