当我使用虚拟数据作为日期时,即当我仅使用年数时,我成功地使这种可视化(小倍数的堆积区域图表)工作,形式略有不同。但是,当我使用这样的实际日期时,它会出现问题:
Record,Code,2008-1-1,2008-2-1,2008-3-1,2008-4-1,2008-5-1,2008-6-1,2008-7-1...
代替这个虚拟数据,工作正常
Record,Code,1895,1896,1897,1898,1899,1900,1901...
当我使用完整日期时,浏览器会挂起;没有错误消息。我以前修复了解析错误,但这个似乎超出了我的能力范围。
这是非工作的Plunker:https://plnkr.co/edit/fOlpxo648OyCSM7Sq8ak?p=preview 另一个Plunker,一个实际加载,但使用虚拟数据,在这个问题的底部。
这段代码似乎特别成问题:
function createDatesArr(start, end) {
var arr = [];
for (var i = start; i <= end; i++ ) {
arr.push((i)); // arr.push(String(i));
}
return arr;
}
稍微不同的形式,我会收到一条错误消息,&#34; date&#34;尚未定义。我已尝试使用以下代码解决此问题:
var dateFormat = d3.time.format("%Y-%m-%d");
var startDate = new Date('2008-1-1');
var endDate = new Date ('2017-12-1');
var dates = createDatesArr(startDate, endDate);
或者像这样:
var dateFormat = d3.time.format("%Y-%m-%d");
var startYear = "2008-1-1";
var endYear = "2017-12-1";
var dates = createYearsArr(startYear, endYear);
或者像这样:
var dateFormat = d3.time.format("%Y-%m-%d");
var startDate = d3.min(dataset, function(d) { return d.Date; });
var endDate = d3.max(dataset, function(d) { return d.Date; });
var dates = createDatesArr(startDate, endDate);
或者,通过定义&#34;日期&#34;像这样:
d3.csv(dataPath, function(data) {
var dates = d3.keys(data[0]).slice(1);
data = data.filter(function(d) {
return true;
});
var dates = d3.keys(data[0]).slice(1);
这些都没有奏效,但我希望有人可以帮我解决这个问题。
这是另一个真正有用的Plunker,它展示了我最终想要实现的目标,尽管使用虚拟数据(仅限年份)来表示日期:http://plnkr.co/edit/jRC8iQg2kdtlZWtGE020?p=preview
请帮忙。
答案 0 :(得分:4)
你是对的,你在这段代码中的问题
function createDatesArr(start, end) {
var arr = [];
for (var i = start; i <= end; i++ ) {
arr.push((i)); // arr.push(String(i));
}
return arr;
}
更准确地说 - i++
;
请看下面的图片,变量i
它是一个以毫秒为单位的日期。在每次循环迭代后,将它增加一毫秒。但是,我可以看到你的数据点之间是一个月。
Record,Code,2008-1-1,2008-2-1,2008-3-1,2008-4-1,2008-5-1,2008-6-1,2008-7-1...
所以你应该在每次循环迭代后增加i
一个月来解决你的问题。
您可以使用d3.time.month.offset
:
for (var i = start; i <= end; i = d3.time.month.offset(i, 1)) {
arr.push((i));
}
之后,你应该删除dateFormat(...)
因为数据项是完全有效的javascript日期并稍微重写transformData
函数,看看我的fork of you plnkr(看起来不正确应用颜色,我认为你可以解决它,但除此之外它有效。)
答案 1 :(得分:2)
首先在这个片段中:
function createDatesArr(start, end) {
var arr = [];
for (var i = start; i <= end; i++ ) {
arr.push((i)); // arr.push(String(i));
}
return arr;
}
使用i ++将无法正常工作,因为您尝试在有效表达式上使用后缀操作。你不能用这个来跳过这几天:
( Fri Dec 01 2017 00:00:00 GMT+0400 (+04) ) ++
如果你想在整个过程中得到所有月份,你可以使用下面这个简单的片段:
function createDatesArr(startDate, endDate) {
var _start = new Date(startDate),
_end = new Date(endDate),
_result = [];
while(_start < _end){
_result.push(_start);
// going next
var _newDate = _start.setDate(_start.getDate() + 1);
_start = new Date(_newDate);
}
return _result;
}
答案 2 :(得分:2)
只是为了提供这个问题的其他信息,已经有两个好的答案:你不需要那个可怕的createDatesArr
函数(这是你问题的原因)。
您可以使用time.ticks([interval])
轻松获取时间刻度的开始日期和结束日期之间的日期数组,其中包含:
从比例的域中返回代表日期。返回的刻度值均匀分布(大部分),具有合理的值(例如每天午夜),并且保证在域的范围内。
不仅比你的功能更安全,而且它也是惯用 D3,这意味着其目的很容易被其他D3程序员理解。
以下是使用v3的演示,这是您的版本。我将结束日期更改为2009而不是2017,因此我们在控制台中的日期会更少。检查一下:
var startDate = new Date('2008-1-1');
var endDate = new Date('2009-6-1');
var dates = d3.time.scale()
.domain([startDate, endDate])
.ticks(d3.time.months, 1);
console.log(dates)
<script src="https://d3js.org/d3.v3.min.js"></script>
实际上,这可能更短,只需一行,缩短时间范围,只使用d3.time.months
或d3.time.month.range
:
var dates = d3.time.month.range(new Date('2008-1-1'), new Date('2009-6-1'), 1)
console.log(dates)
<script src="https://d3js.org/d3.v3.min.js"></script>