在这个d3.js日历视图中包含json? [英] Include json in this d3.js calendar view?

查看:66
本文介绍了在这个d3.js日历视图中包含json?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



经过大量研究后,我可以用图表填充图表一个CSV文件。所以现在,我试图用 json 数据填充图表。



这是我的代码。它基于这个例子。但我更喜欢使用我的代码(即。d3.v4):

var width = 960,height = 136,cellSize = 17; var color = d3.scaleQuantize().domain([9000,12000]).range([Blue,Red,Green,Yellow紫色,黑色]); var dateParse = d3.timeFormat(%Y-%m-%d); var svg = d3.select(body).selectAll(svg).data(d3 .range(2017,2018)).enter()。append(svg).attr(width,width).attr(height,height).append(g).attr(transform ,translate(+((width-cellSize * 53)/ 2)+,+(height - cellSize * 7 - 1)+)); svg.append(text).attr(transform ,translate(-6,+ cellSize * 3.5 +)rotate(-90)).attr(font-family,sans-serif).attr(font-size,10)。 attr(text-anchor,middle).text(function(d){return d;}); var rect = svg.append(g).attr(fill,none).attr (STRO (d,0,1),new Date(d + 1,0,1))。 ; }).enter()。append(rect).attr(width,cellSize).attr(height,cellSize).attr(x,function(d){return d3.timeWeek.count d3.timeYear(d),d)* cellSize;}).attr(y,function(d){return d.getDay()* cellSize;}).datum(d3.timeFormat(%Y-%m - %d)); svg.append(g).attr(fill,none).attr(stroke,#000).selectAll(path).data(function d){return d3.timeMonths(new Date(d,0,1),new Date(d + 1,0,1));}).enter()。append(path).attr(d ,pathMonth); d3.json(data3.json,function(error,data){//填充数据,因为我没有文件data = [{date:2017-01-04,打开:10430.69},{date:2017-01-05,open:10584.56}]; data.forEach(function(d){d.dd = dateParse(new Date(d.date)) ; console.log(d.dd);}); var nest = d3.nest().key(function(d){return d.dd;}).map(data); rect.filter(function(d) {return d in data;}).attr(fill,function(d){return color(data [d]);}) .append(title).text(function(d){return d +:+ data [d]; });});函数pathMonth(t0){var t1 = new Date(t0.getFullYear(),t0.getMonth()+ 1,0),d0 = t0.getDay(),w0 = d3.timeWeek.count (d3.timeYear(t0),t0),d1 = t1.getDay(),w1 = d3.timeWeek.count(d3.timeYear(t1),t1);返回M+(w0 + 1)* cellSize +V+ w1 * cellSize +V+ 7 * cellSize +H+ w1 * cellSize +V+( d1 + 1)* cellSize +H+(w1 + 1)* cellSize +V+0 +H+(w0 + 1)* cellSize +Z;}

< script src =http://d3js.org/d3.v4.min。 js>< / script>

解决方案

您的代码需要进行一些更改才能工作。这些主要与使用 data 而不是 nest 以及一个小的变化(我无法找到信息on)在d3 v4中与d3 v3相比。

过滤器

首先,你没有正确过滤你的数据:



你不想这样过滤:

 在数据中返回d; 

运算符中的用于对象, data 是一个数组。
您希望按照您的嵌套进行过滤(如示例所示):

 在嵌套中返回d; 

其次,至少在我的简短测试中,d3.nest在d3 v4中的表现略有不同依赖于版本,我在下面的代码片段中使用了4.9.1(min))。当使用以数字开头的键时,在使用d3.nest时,d3似乎在每个键的开头附加一个美元符号:



D3v4示例:



< ,open:10430.69},{date:2017-01-05,open:10584.56}]; var nest = d3.nest().key(function(d){return d.date;}).map(data); console.log(nest);

< script src = https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js\"></script>

与D3v3相比:

  data = [{date:2017-01-04,open:10430.69},{date:2017-01-05 ,open:10584.56}]; var nest = d3.nest().key(function(d){return d.date;}).map(data); console.log(nest);  

< script src = https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js\"></script>

 在嵌套中返回($+ d); 

访问套件属性


$ b $第三,由于 data 只是一个数组,所以 data [d] 不可能得到想要的结果因为 d 将是一个日期字符串,您需要访问 nest 对象。记录可能有助于找到正确的属性。而不是:

  return color(data [d]); 

试试:

  return color(nest [($+ d)] [0] .open); 

这与问题中的链接示例非常相似(除了美元符号之外)。






优化

与您最近的问题相关,此代码



var date =2017-01-02; var dateParse = d3.timeFormat(%Y-%m-%d); console.log(dateParse(new Date(date)));

< script src =https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js>< / script>

什么都不做。它接受一个表示日期的字符串并将其转换为日期对象,然后将其转换回与您开始的字符串相同的表示形式。您可以放弃这部分代码,它用于链接的示例中,因为它是从m / d / Y日期字符串转换为日期对象,然后转换为Y-m-d日期字符串。你的初始日期格式已经是你想要的格式,所以不需要修改它。使用:

pre $ code var nest = d3.nest()
.key(function(d){
返回d.date;
})
.map(data);

而不是:

 (函数(d){
d.dd = dateParse(d.date);
}); data.forEach

var nest = d3.nest()
.key(function(d){
return d.dd;
})
.map(数据);






结果



这些更改(我已经删除了文本以使示例更简单,删除外部文件引用等)导致:



var width = 960,height = 136,cellSize = 17; var color = d3.scaleQuantize().domain([ ([Blue,Red,Green,Yellow,Purple,Black]); var dateFormat = d3.timeFormat(%Y-%m-%d); var svg = d3.select(body).selectAll(svg).data(d3.range(2017,2018))。输入()。append(svg).attr(width,width).attr(height,height).append(g).attr(transform,translate(+( - cellSize * 53)/ 2)+,+(height - cellSize * 7 - 1)+)); var rect = svg.append(g).attr(fill,none) .attr(stroke,#ccc).selectAll(rect).data(function(d){return d3.timeDays(new Date(d,0,1),new Date(d + 1,0) ,1));}).enter()。append(rect).attr(width,cellSize).attr(height,cellSize).attr(x,function(d){return d3 .timeWeek.count(d3.timeYear(d),d)* cellSize;}).attr(y,function(d){return d.getDay()* cellSize;}).datum(dateFormat); svg。 append(g).attr(fill,none).attr(stroke,#000).selectAll(path).data(function(d){return d3.timeMonths(new Date(d,0,1),new Date(d + 1,0,1));}).enter()。append(path).attr(d,pathMonth); data = [{date:2017-01-04,open:10430.69},{date:2017-01-05,open:10584.56}]; var nest = d3.nest().key(function(d){return d.date;}).map(data); rect.filter(function(d){return($+ d)in nest;}).attr(fill,function(d){return color(nest [($+ d)] [0] .open);})function pathMonth(t0){var t1 = new Date(t0.getFullYear(),t0.getMonth()+ 1,0),d0 = t0.getDay(),w0 = d3.timeWeek.count (d3.timeYear(t0),t0),d1 = t1.getDay(),w1 = d3.timeWeek.count(d3.timeYear(t1),t1);返回M+(w0 + 1)* cellSize +V+ w1 * cellSize +V+ 7 * cellSize +H+ w1 * cellSize +V+( d1 + 1)* cellSize +H+(w1 + 1)* cellSize +V+0 +H+(w0 + 1)* cellSize +Z;}

< script src =https://cdnjs.cloudflare.com/ajax/libs/

I'm new to d3 charts and javascript, and this has been an uphill battle.

After a bunch a research, I was able to populate the chart with a CSV file. So now, I'm trying to populate the chart with json data.

This is my code. It's loosely based on this example. But I prefer using my code (ie. d3.v4):

var width = 960,
  height = 136,
  cellSize = 17;

var color = d3.scaleQuantize()
  .domain([9000, 12000])
  .range(["Blue", "Red", "Green", "Yellow", "Purple", "Black"]);
var dateParse = d3.timeFormat("%Y-%m-%d");
var svg = d3.select("body")
  .selectAll("svg")
  .data(d3.range(2017, 2018))
  .enter().append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");

svg.append("text")
  .attr("transform", "translate(-6," + cellSize * 3.5 + ")rotate(-90)")
  .attr("font-family", "sans-serif")
  .attr("font-size", 10)
  .attr("text-anchor", "middle")
  .text(function(d) {
    return d;
  });

var rect = svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#ccc")
  .selectAll("rect")
  .data(function(d) {
    return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("rect")
  .attr("width", cellSize)
  .attr("height", cellSize)
  .attr("x", function(d) {
    return d3.timeWeek.count(d3.timeYear(d), d) * cellSize;
  })
  .attr("y", function(d) {
    return d.getDay() * cellSize;
  })
  .datum(d3.timeFormat("%Y-%m-%d"));

svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#000")
  .selectAll("path")
  .data(function(d) {
    return d3.timeMonths(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("path")
  .attr("d", pathMonth);

d3.json("data3.json", function(error, data) {
  //populating data since i don't have the file
  data = [{
    "date": "2017-01-04",
    "open": 10430.69
  }, {
    "date": "2017-01-05",
    "open": 10584.56
  }];

  data.forEach(function(d) {
    d.dd = dateParse(new Date(d.date));
    console.log(d.dd);
  });

  var nest = d3.nest()
    .key(function(d) {
      return d.dd;
    })
    .map(data);

  rect.filter(function(d) {
      return d in data;
    })
    .attr("fill", function(d) {
      return color(data[d]);
    })
    .append("title")
    .text(function(d) {
      return d + ": " + data[d];
    });
});

function pathMonth(t0) {
  var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
    d0 = t0.getDay(),
    w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
    d1 = t1.getDay(),
    w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
  return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize +
    "H" + w0 * cellSize + "V" + 7 * cellSize +
    "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize +
    "H" + (w1 + 1) * cellSize + "V" + 0 +
    "H" + (w0 + 1) * cellSize + "Z";
}

<script src="http://d3js.org/d3.v4.min.js"></script>

解决方案

There are a few changes needed for your code to work. These are mostly related to the use of data instead of nest, and a minor change (for which I cannot find information on) in d3 v4 as compared with d3 v3.

Filter

Firstly, you are not filtering your data correctly:

You do not want to filter like this:

return d in data;

The in operator is for properties of an object, data is an array. You want to filter by your nest (as in the example):

return d in nest;

Secondly, at least in my brief testing, d3.nest behaves slightly differently in d3 v4 (this might be dependent on version, I've used 4.9.1 (min) in the snippet below). When using keys that begin with numbers, d3 seems to be appending a dollar sign at the beginning of each key when using d3.nest:

D3v4 example:

data = [{
    "date": "2017-01-04", "open": 10430.69
  }, {
    "date": "2017-01-05", "open": 10584.56
  }];

  var nest = d3.nest()
    .key(function(d) { return d.date; })
    .map(data);
	
	console.log(nest);

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>

Compared with D3v3:

data = [{
    "date": "2017-01-04", "open": 10430.69
  }, {
    "date": "2017-01-05", "open": 10584.56
  }];

  var nest = d3.nest()
    .key(function(d) { return d.date; })
    .map(data);
	
	console.log(nest);

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

If you are seeing this behaviour, you'll need to change your filter accordingly:

return ("$" + d) in nest;

Accessing Nest Properties

Thirdly, as data is just an array, data[d] is not likely to get desired results as d will be a date string, you need to access the nest object. Logging nest might help in finding the proper properties. Instead of:

return color(data[d]);

Try:

return color(nest[("$" + d)][0].open);

Which is very similar to the linked example in the question (with the exception of that dollar sign thing again).


Optimization

Related to your other recent question, this code

    var date = "2017-01-02";
    var dateParse = d3.timeFormat("%Y-%m-%d");
    console.log(dateParse(new Date(date)));

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>

does nothing. It takes a string representing a date and converts it to a date object, then converts it back into the same string representation you started with. You can drop this portion of the code, it was used in the linked example because it was converting from a m/d/Y date string to a date object, and then to a Y-m-d date string. Your initial date format is already in the format you want, so there is no need to modify it. Use just:

  var nest = d3.nest()
    .key(function(d) {
      return d.date;
    })
    .map(data);

Rather than:

  data.forEach(function(d) {
    d.dd = dateParse(d.date);
  });

  var nest = d3.nest()
    .key(function(d) {
      return d.dd;
    })
    .map(data);


Result

These changes (I've stripped out the text to make the example simpler, removed the external file reference, etc) result in:

var width = 960,
  height = 136,
  cellSize = 17;

var color = d3.scaleQuantize()
  .domain([9000, 12000])
  .range(["Blue", "Red", "Green", "Yellow", "Purple", "Black"]);
  
var dateFormat = d3.timeFormat("%Y-%m-%d");

var svg = d3.select("body")
  .selectAll("svg")
  .data(d3.range(2017, 2018))
  .enter().append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");

var rect = svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#ccc")
  .selectAll("rect")
  .data(function(d) {
    return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("rect")
  .attr("width", cellSize)
  .attr("height", cellSize)
  .attr("x", function(d) {
    return d3.timeWeek.count(d3.timeYear(d), d) * cellSize;
  })
  .attr("y", function(d) {
    return d.getDay() * cellSize;
  })
  .datum(dateFormat);

svg.append("g")
  .attr("fill", "none")
  .attr("stroke", "#000")
  .selectAll("path")
  .data(function(d) {
    return d3.timeMonths(new Date(d, 0, 1), new Date(d + 1, 0, 1));
  })
  .enter().append("path")
  .attr("d", pathMonth);

  data = [{
    "date": "2017-01-04",
    "open": 10430.69
  }, {
    "date": "2017-01-05",
    "open": 10584.56
  }];

  var nest = d3.nest()
    .key(function(d) {
      return d.date;
    })
    .map(data);

	rect.filter(function(d) {
      return ("$" + d) in nest;
    })
    .attr("fill", function(d) { 
      return color(nest[("$" + d)][0].open);
    })


function pathMonth(t0) {
  var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
    d0 = t0.getDay(),
    w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
    d1 = t1.getDay(),
    w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
  return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize +
    "H" + w0 * cellSize + "V" + 7 * cellSize +
    "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize +
    "H" + (w1 + 1) * cellSize + "V" + 0 +
    "H" + (w0 + 1) * cellSize + "Z";
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>

这篇关于在这个d3.js日历视图中包含json?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆