D3将点添加到堆叠的区域图表中

  • 本文关键字:区域 添加 D3 d3.js
  • 更新时间 :
  • 英文 :


我需要在下面的代码中将点添加到堆叠的区域图中。我在代码中使用.DATA(层(尝试了许多迭代,但是在我尝试过的所有迭代中寻找CX和CY时,它会出错。主要问题是,我不明白如何钻入层变量以获取cumultative求和,以便圆圈与堆叠区域中的线相匹配。

这是一个小提琴,这是一个片段:

var data = d3.csv.parse(d3.select("#dataset").text());
d3.select("#dataset").remove();
var format = d3.time.format("%m/%d/%y");
    
var margin = {top: 20, right: 30, bottom: 30, left: 40},
    width = 500 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;
    
var x = d3.time.scale()
    .range([0, width]);
var y = d3.scale.linear()
    .range([height, 0]);
    
var z = d3.scale.category20c();
    
var xAxis = d3.svg.axis()
   .scale(x)
   .orient("bottom")
   .ticks(d3.time.days);
    
var yAxis = d3.svg.axis()
   .scale(y)
   .orient("left");
    
var stack = d3.layout.stack()
   .offset("zero")
   .values(function(d) { return d.values; })
   .x(function(d) { return d.date; })
   .y(function(d) { return d.value; });
    
var nest = d3.nest()
   .key(function(d) { return d.key; });
    
var area = d3.svg.area()
  .interpolate("cardinal")
  .x(function(d) { return x(d.date); })
  .y0(function(d) { return y(d.y0); })
  .y1(function(d) { return y(d.y0 + d.y); });
    
var svg = d3.select("body").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
var mygroups = d3.map(data, function(d){return(d.key)}).keys()
    
    
var color = d3.scale.ordinal()
    .domain(mygroups)
    .range(['#CA999A','#99A3B0','#9FBD9F'])
    
data.forEach(function(d) {
   d.date = format.parse(d.date);
   d.value = +d.value;
});
    
var layers = stack(nest.entries(data));
      
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]);
    
svg.selectAll(".layer")
   .data(layers)
   .enter()
   .append("path")
   .attr("class", "layer")
   .attr("d", function(d) { return area(d.values); })
   .style("fill", function(d, i) { return color(i); })
   .style("stroke","black");
          
 svg.append("g")
   .attr("class", "x axis")
   .attr("transform", "translate(0," + height + ")")
   .call(xAxis)
   .selectAll("path","line")
   .style({
       fill: "none",
       stroke: "#000",
       "shape-rendering":"crispEdges"
    });
    
svg.append("g")
   .attr("class", "y axis")
   .call(yAxis)
   .selectAll("path","line")
   .style({
      fill: "none",
      stroke: "#000",
      "shape-rendering":"crispEdges"
   });
    
    
     //adds dots where original data would go but without error
    /* svg.selectAll("circle")
        .data(data)
        .enter()
        .append("circle")
        .attr("class", "dot")
        .attr("r", 5)
        .attr("cx", function(d) { return x(d.date); })
        .attr("cy", function(d) { return y(d.value); });
     */
    
    //errors out with <circle> attribute cx: Expected length, "NaN".  
    //Tired various looping functions that would not work. 
    //I want the dots to follow the lines in the stack.
    // it does at least put a dot on the graph
    
svg.selectAll("circle")
   .data(layers)
   .enter()
   .append("circle")
   .attr("class", "dot")
   .attr("r", 5)
   .attr("cx", function(d) { return x(d.date); })
   .attr("cy", function(d) { return y(d.value); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<pre id = "dataset">key,value,date
Group1,37,04/23/12
Group2,12,04/23/12
Group3,46,04/23/12
Group1,32,04/24/12
Group2,19,04/24/12
Group3,42,04/24/12
Group1,45,04/25/12
Group2,16,04/25/12
Group3,44,04/25/12
Group1,24,04/26/12
Group2,52,04/26/12
Group3,64,04/26/12</pre>

⚠️这个问题并回答两者都使用d3v3 -d3v4 堆栈创建具有不同结构的数据数组 - 因此,此答案对于D3V4

使用data变量绘制圆圈也无法正常工作,即使缩放,返回的值将用于非肿瘤线/区域图。或者,layers变量中的绘制值无法正常工作,因为它仅包含每个层的一个值。layers中的每个层都包含一个数组,其中所有属于该层的点,我们可以抓住所有这些点并将其绘制为圆圈。

这是layers结构:

[
  {
    "key": "Group1",
    "values": [
      {
        "key": "Group1",
        "value": 37,
        "date": "2012-04-23T07:00:00.000Z",
        "y0": 0,
        "y": 37
      },
      ...
      {
        "key": "Group1",
        "value": 24,
        "date": "2012-04-26T07:00:00.000Z",
        "y0": 0,
        "y": 24
      }
    ]
  },
  {
    "key": "Group2",
    "values": [
      {
        "key": "Group2",
        "value": 12,
        "date": "2012-04-23T07:00:00.000Z",
        "y0": 37,
        "y": 12
      },
      ...  // an so on.

因此,我们可以循环浏览layers的每个项目,这意味着我们循环遍历每一层,并收集所有点。这样的事情就足够了:

// Grab all coordinates of all layers:
var points = []; 
layers.forEach(function(d) {
  return points.push(...d.values);
})

现在,让我们看一下points数组中的每个项目:

  {
    "key": "Group1",
    "value": 37,
    "date": "2012-04-23T07:00:00.000Z",
    "y0": 0,
    "y": 37
  }

在这里,y代表项目高度,y0代表其底座(该点的层底部(。由于我们只想绘制每个点一次,并且我们不想绘制底层y0属性的0个值,我们只能绘制最上方的y值(y+y0(:

//adds dots where original data would go but without error
svg.selectAll("circle")
   .data(points)
   .enter()
   .append("circle")
   .attr("class", "dot")
   .attr("r", 5)
   .attr("cx", function(d) { return x(d.date); })
   .attr("cy", function(d) { return y(d.y0+d.y); });

看起来完全像这样:

var data = d3.csv.parse(d3.select("#dataset").text());
d3.select("#dataset").remove();
var format = d3.time.format("%m/%d/%y");
    
var margin = {top: 20, right: 30, bottom: 30, left: 40},
    width = 500 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;
    
var x = d3.time.scale()
    .range([0, width]);
var y = d3.scale.linear()
    .range([height, 0]);
    
var z = d3.scale.category20c();
    
var xAxis = d3.svg.axis()
   .scale(x)
   .orient("bottom")
   .ticks(d3.time.days);
    
var yAxis = d3.svg.axis()
   .scale(y)
   .orient("left");
    
var stack = d3.layout.stack()
   .offset("zero")
   .values(function(d) { return d.values; })
   .x(function(d) { return d.date; })
   .y(function(d) { return d.value; });
    
var nest = d3.nest()
   .key(function(d) { return d.key; });
    
var area = d3.svg.area()
  .interpolate("cardinal")
  .x(function(d) { return x(d.date); })
  .y0(function(d) { return y(d.y0); })
  .y1(function(d) { return y(d.y0 + d.y); });
    
var svg = d3.select("body").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
var mygroups = d3.map(data, function(d){return(d.key)}).keys()
    
    
var color = d3.scale.ordinal()
    .domain(mygroups)
    .range(['#CA999A','#99A3B0','#9FBD9F'])
    
data.forEach(function(d) {
   d.date = format.parse(d.date);
   d.value = +d.value;
});
    
var layers = stack(nest.entries(data));
      
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]);
    
svg.selectAll(".layer")
   .data(layers)
   .enter()
   .append("path")
   .attr("class", "layer")
   .attr("d", function(d) { return area(d.values); })
   .style("fill", function(d, i) { return color(i); })
   .style("stroke","black");
          
 svg.append("g")
   .attr("class", "x axis")
   .attr("transform", "translate(0," + height + ")")
   .call(xAxis)
   .selectAll("path","line")
   .style({
       fill: "none",
       stroke: "#000",
       "shape-rendering":"crispEdges"
    });
    
svg.append("g")
   .attr("class", "y axis")
   .call(yAxis)
   .selectAll("path","line")
   .style({
      fill: "none",
      stroke: "#000",
      "shape-rendering":"crispEdges"
   });
    
// Grab all coordinates of all layers:
var points = []; 
layers.forEach(function(d) {
  return points.push(...d.values);
})
//adds dots where original data would go but without error
svg.selectAll("circle")
   .data(points)
   .enter()
   .append("circle")
   .attr("class", "dot")
   .attr("r", 5)
   .attr("cx", function(d) { return x(d.date); })
   .attr("cy", function(d) { return y(d.y0+d.y); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<pre id = "dataset">key,value,date
Group1,37,04/23/12
Group2,12,04/23/12
Group3,46,04/23/12
Group1,32,04/24/12
Group2,19,04/24/12
Group3,42,04/24/12
Group1,45,04/25/12
Group2,16,04/25/12
Group3,44,04/25/12
Group1,24,04/26/12
Group2,52,04/26/12
Group3,64,04/26/12</pre>

最新更新