不管在哪个月图形开始,都在年轴上显示第一个值 [英] Show first value in year axis, regardless of what month graph starts on

查看:43
本文介绍了不管在哪个月图形开始,都在年轴上显示第一个值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

test_data.csv :

date,col_1,col_2
11/1/2012,1977652,1802851
12/1/2012,1128739,948687
1/1/2013,1201944,1514667
2/1/2013,1863148,1834006
3/1/2013,1314851,1906060
4/1/2013,1283943,1978702
5/1/2013,1127964,1195606
6/1/2013,1773254,977214
7/1/2013,1929574,1127450
8/1/2013,1980411,1808161
9/1/2013,1405691,1182788
10/1/2013,1336790,937890
11/1/2013,1851053,1358400
12/1/2013,1472623,1214610
1/1/2014,1155116,1757052
2/1/2014,1571611,1935038
3/1/2014,1898348,1320348
4/1/2014,1444838,1934789
5/1/2014,1235087,950194
6/1/2014,1272040,1580656
7/1/2014,980781,1680164
8/1/2014,1391291,1115999
9/1/2014,1211125,1542148
10/1/2014,1020824,1782795
11/1/2014,1685081,926612
12/1/2014,1469254,1767071
1/1/2015,1168523,935897
2/1/2015,1602610,1450541
3/1/2015,1830278,1354876
4/1/2015,1275158,1412555
5/1/2015,1560961,1839718
6/1/2015,949948,1587130
7/1/2015,1413765,1494446
8/1/2015,1166141,1305105
9/1/2015,958975,1202219
10/1/2015,902696,1023987
11/1/2015,961441,1865628
12/1/2015,1363145,1954046
1/1/2016,1862878,1470741
2/1/2016,1723891,1042760
3/1/2016,1906747,1169012
4/1/2016,1963364,1927063
5/1/2016,1899735,1936915
6/1/2016,1300369,1430697
7/1/2016,1777108,1401210
8/1/2016,1597045,1566763
9/1/2016,1558287,1140057
10/1/2016,1965665,1953595
11/1/2016,1800438,937551
12/1/2016,1689152,1221895
1/1/2017,1607824,1963282
2/1/2017,1878431,1415658
3/1/2017,1730296,1947106
4/1/2017,1956756,1696780
5/1/2017,1746673,1662892
6/1/2017,989702,1537646
7/1/2017,1098812,1592064
8/1/2017,1861973,1892987
9/1/2017,1129596,1406514
10/1/2017,1528632,1725020
11/1/2017,925850,1795575

page.html :

<!DOCTYPE html>
<!-- https://bl.ocks.org/mbostock/3886208 -->
<style>

</style>
<script src="https://d3js.org/d3.v4.js"></script>
<body>

<script>
var margin = {top: 20, right: 20, bottom: 50, left: 40},
    width = 1300 - margin.left - margin.right,
    height = 700 - margin.top - margin.bottom;

var svg = d3.select("body").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom);

var g = svg.append("g")
           .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// parse the date / time
// look at the .csv in Notepad! DO NOT LOOK AT EXCEL!
var parseDate = d3.timeParse("%m/%d/%Y");


var x = d3.scaleTime()
          .range([0, width - margin.left - margin.right]);
var y = d3.scaleLinear().range([height, 0]);
var z = d3.scaleOrdinal()
          .range(["#CE1126", "#00B6D0"]); // red and blue 

var xAxis = d3.axisBottom(x)
              .ticks(d3.timeMonth.every(1))
              .tickFormat(d3.timeFormat("%b")); // label every month

var xYearAxis = d3.axisBottom(x)
                  .ticks(d3.timeYear.every(1))
                  .tickFormat(d3.timeFormat("%Y")); // label every year

// load .csv file
d3.csv("test_data.csv", function(d, i, columns) {
  for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
  d.total = t;
  return d;
}, function(error, data){
    if (error) throw error;

    data.forEach(function(d) {
        //console.log(parseDate(d.date));
        d.date = parseDate(d.date);
    });

    var keys = data.columns.slice(1);
    var barWidth = (width - margin.right- margin.left)/(data.length+1);     

    data.sort(function(a, b) { return b.date - a.date; });


    x.domain(d3.extent( data, function(d){ return d.date }) );

    var max = x.domain()[1];
    var min = x.domain()[0];
    var datePlusOneMonth = d3.timeDay.offset(d3.timeMonth.offset(max, 1), -1); // last day of current month: move up one month, back one day 

    x.domain([min,datePlusOneMonth]);

    y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
    z.domain(keys);


    // the bars 
    g.append("g")
     .selectAll("g")
     .data(d3.stack().keys(keys)(data))
     .enter().append("g")
     .attr("fill", function(d) { return z(d.key); })
     .selectAll("rect")
     .data(function(d) { return d; })
     .enter()
     .append("rect")
     .attr("x", function(d) { return x(d.data.date); })
     .attr("y", function(d) { return y(d[1]); })
     .attr("height", function(d) { return y(d[0]) - y(d[1]); })
     .attr("width", barWidth);


    // x-axis
    var axis = g.append("g")
      .attr("class", "axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

    var yearAxis = g.append("g")
                     .attr("class", "axis")
                     .attr("transform", "translate(0," + (height + 25) + ")")
                     .call(xYearAxis);

    axis.selectAll("g").select("text")
      .attr("transform","translate(" + barWidth/2 + ",0)");

});
</script>

</body>

当前输出:

我要寻找的是将2012添加到年份轴的第一个刻度.更笼统地说,我正在考虑最终在这个项目中基于滑块构建一个过滤器-因此,我想解决的更一般的问题是:无论图表的最左端出现哪个月,我都希望在图表下方的刻度中显示的年份.我该怎么办?

What I am looking for is to add 2012 to the very first tick in the year axis. More generally, I am looking into eventually building a filter based on a slider into this project - so the more general problem I'd like to solve is this: regardless of what month appears at the very left of the graph, I would like for the year to appear in the tick under the graph. How can I do this?

查看 scaleTime文档 ,看来scaleTime刻度线主要是做成均匀间隔的.

Looking at the scaleTime documentation, it appears that scaleTime ticks are primarily made to be uniformly spaced.

推荐答案

您可以简单地将这两个字符串添加到yearAxis变量之前:

You can do it simply, add this two strings before your yearAxis variable:

const firstDataYear = x.domain()[0]; 
xYearAxis.tickValues([firstDataYear].concat(x.ticks()));

var yearAxis = g.append("g") // ...

它是第一个字符串,我们将第一个日期项存储到firstDataYear变量中.在第二个步骤中,您可以使用x.ticks()方法获得的默认刻度集来连接此变量.在下面的隐藏代码段中检查工作演示(我将ajax请求重写为d3.csvParse以简化示例):

It the first string we store the first date item to firstDataYear variable. And in the second you concat this variable with default set of ticks that you can get with x.ticks() method. Check working demo in the hidden snippet below (I rewrote ajax request to d3.csvParse to simplify the example):

var dataAsCsv = `date,col_1,col_2
11/1/2012,1977652,1802851
12/1/2012,1128739,948687
1/1/2013,1201944,1514667
2/1/2013,1863148,1834006
3/1/2013,1314851,1906060
4/1/2013,1283943,1978702
5/1/2013,1127964,1195606
6/1/2013,1773254,977214
7/1/2013,1929574,1127450
8/1/2013,1980411,1808161
9/1/2013,1405691,1182788
10/1/2013,1336790,937890
11/1/2013,1851053,1358400
12/1/2013,1472623,1214610
1/1/2014,1155116,1757052
2/1/2014,1571611,1935038
3/1/2014,1898348,1320348
4/1/2014,1444838,1934789
5/1/2014,1235087,950194
6/1/2014,1272040,1580656
7/1/2014,980781,1680164
8/1/2014,1391291,1115999
9/1/2014,1211125,1542148
10/1/2014,1020824,1782795
11/1/2014,1685081,926612
12/1/2014,1469254,1767071
1/1/2015,1168523,935897
2/1/2015,1602610,1450541
3/1/2015,1830278,1354876
4/1/2015,1275158,1412555
5/1/2015,1560961,1839718
6/1/2015,949948,1587130
7/1/2015,1413765,1494446
8/1/2015,1166141,1305105
9/1/2015,958975,1202219
10/1/2015,902696,1023987
11/1/2015,961441,1865628
12/1/2015,1363145,1954046
1/1/2016,1862878,1470741
2/1/2016,1723891,1042760
3/1/2016,1906747,1169012
4/1/2016,1963364,1927063
5/1/2016,1899735,1936915
6/1/2016,1300369,1430697
7/1/2016,1777108,1401210
8/1/2016,1597045,1566763
9/1/2016,1558287,1140057
10/1/2016,1965665,1953595
11/1/2016,1800438,937551
12/1/2016,1689152,1221895
1/1/2017,1607824,1963282
2/1/2017,1878431,1415658
3/1/2017,1730296,1947106
4/1/2017,1956756,1696780
5/1/2017,1746673,1662892
6/1/2017,989702,1537646
7/1/2017,1098812,1592064
8/1/2017,1861973,1892987
9/1/2017,1129596,1406514
10/1/2017,1528632,1725020
11/1/2017,925850,1795575`;

var margin = {top: 20, right: 20, bottom: 50, left: 40},
    width = 1300 - margin.left - margin.right,
    height = 700 - margin.top - margin.bottom;

var svg = d3.select("body").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom);

var g = svg.append("g")
           .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// parse the date / time
// look at the .csv in Notepad! DO NOT LOOK AT EXCEL!
var parseDate = d3.timeParse("%m/%d/%Y");


var x = d3.scaleTime()
          .range([0, width - margin.left - margin.right]);
var y = d3.scaleLinear().range([height, 0]);
var z = d3.scaleOrdinal()
          .range(["#CE1126", "#00B6D0"]); // red and blue 

var xAxis = d3.axisBottom(x)
              .ticks(d3.timeMonth.every(1))
              .tickFormat(d3.timeFormat("%b")); // label every month

var xYearAxis = d3.axisBottom(x)
                  .ticks(d3.timeYear.every(1))
                  .tickValues(x.ticks())
                  .tickFormat(d3.timeFormat("%Y")); // label every year



var data = d3.csvParse(dataAsCsv, function(d, i, columns) {
	  for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
  d.total = t;
  return d;
})

data.forEach(function(d) {
  //console.log(parseDate(d.date));
  d.date = parseDate(d.date);
});

var keys = data.columns.slice(1);
var barWidth = (width - margin.right- margin.left)/(data.length+1);     

data.sort(function(a, b) { return b.date - a.date; });


x.domain(d3.extent( data, function(d){ return d.date }) );

var max = x.domain()[1];
var min = x.domain()[0];
var datePlusOneMonth = d3.timeDay.offset(d3.timeMonth.offset(max, 1), -1); // last day of current month: move up one month, back one day 

x.domain([min,datePlusOneMonth]);

y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
z.domain(keys);


// the bars 
g.append("g")
  .selectAll("g")
  .data(d3.stack().keys(keys)(data))
  .enter().append("g")
  .attr("fill", function(d) { return z(d.key); })
  .selectAll("rect")
  .data(function(d) { return d; })
  .enter()
  .append("rect")
  .attr("x", function(d) { return x(d.data.date); })
  .attr("y", function(d) { return y(d[1]); })
  .attr("height", function(d) { return y(d[0]) - y(d[1]); })
  .attr("width", barWidth);


// x-axis
var axis = g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);

const firstDataYear = x.domain()[0]
xYearAxis.tickValues([firstDataYear].concat(x.ticks()));

var yearAxis = g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (height + 25) + ")")
.call(xYearAxis);

axis.selectAll("g").select("text")
  .attr("transform","translate(" + barWidth/2 + ",0)");

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

这篇关于不管在哪个月图形开始,都在年轴上显示第一个值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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