admin管理员组

文章数量:1303413

I'm trying to do a simple line graph that has months Jan - Dec in the x axis and number of assignments posted on my pany's website for the y. I'm having a bit of trouble mapping the y domain... and basically understanding how this api is supposed to work. I find plenty of examples with parsing for date, or a numerical value x axis, but I can't seem to get it right with months.

I've been tweaking with this code for so long, I'm not even sure what I'm looking at.

Any help is greatly appreciated for a young noob.

Here is the gist:

my styling looks like:

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.axis text {
  font: 10px sans-serif;
}

.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 1.5px;
}

I'm trying to do a simple line graph that has months Jan - Dec in the x axis and number of assignments posted on my pany's website for the y. I'm having a bit of trouble mapping the y domain... and basically understanding how this api is supposed to work. I find plenty of examples with parsing for date, or a numerical value x axis, but I can't seem to get it right with months.

I've been tweaking with this code for so long, I'm not even sure what I'm looking at.

Any help is greatly appreciated for a young noob.

Here is the gist: https://gist.github./wiredsister/8148974

my styling looks like:

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.axis text {
  font: 10px sans-serif;
}

.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 1.5px;
}
Share Improve this question asked Dec 27, 2013 at 16:10 GinaGina 5802 gold badges5 silver badges20 bronze badges 2
  • 4 The CSS code doesn't add much to the question. It would be more useful if you copied (a) the section of the code where you define the axis, and (b) your sample data file. – AmeliaBR Commented Dec 27, 2013 at 17:11
  • @AmeliaBR, you're right, it doesn't. That's why I linked to my gist which has all the relevant material. Sorry for that confusion. – Gina Commented Dec 27, 2013 at 17:30
Add a ment  | 

2 Answers 2

Reset to default 5

The reason why the date/time axis functions aren't working for you is because your month data isn't actually stored as a date/time value: it is just a simple integer number. There are two ways you can work with this.

First option, if you will only ever want to graph one year at a time (so no duplicates of January 2013 versus January 2014) and don't need to do any time-based math, you can use an ordinal scale to map the month numbers to month names, and not worry about time scales at all.

Second option, if you want to store the month data as dates, you need to parse your input data into a date object. After that, the rest of your code should work as expected.

Currently, the first statement of your data-reading method is a data conversion routine, but it just stores everything as number:

data.forEach(function(d) {
    d.month = +d.month;
    d.work = +d.work;
  });

The +d.month tells the program to take the string of digits that it read in ("0" or "7" or "11") and replace it with the corresponding number. Instead, you want it to read that string of digits and interpret it as a month.

To do that, you need to create a time formatting object that expects to see a single number and read it as a month, and then use that formatting object's parse() method on the value read in. This is a little plicated because your month numbers are given in the range 0-11, and the expected numerical format for a date is in the range 1-12. (If you can change the data format without plicating other parts of your code, that would make this simpler).

var monthNumber = d3.time.format("%-m"); 
   //m is month number, '-' indicates no padding

data.forEach(function(d) {
    d.month = monthNumber("" + (+d.month + 1) );
      //convert the month to an integer and add one, 
      //then convert back to a string and parse
    d.work = +d.work;
  });

See this approach in action here: http://fiddle.jshell/eGTnB/

Note that, since your data doesn't have any information about what year is being specified, the browser will insert a "zero" year, such as 1900. If you wanted to hard-code a valid year, you would have to change the format like this:

var year = 2013;
var yearPlusMonthNumber = d3.time.format("%Y %-m"); 
    //Y is four digit year, m is month number, '-' indicates no padding

data.forEach(function(d) {
    d.month = yearPlusMonthNumber("" + year + " " + (+d.month + 1) );
      //convert the month to an integer, add one,  
      //then bine with year (and space) as a string and parse
    d.work = +d.work;
  });

I'd like to show how I actually ended up implementing this graph: per AmeliaBR's remendation and Mike Bostock's Month Axis example, I decided to make my line chart with x and y being linear scales, and a variable called xLabels, to be a formatted time scale for the xAxis. Like so,

var xLabels = d3.time.scale().domain([new Date(2013, 0, 1), new Date(2013, 11, 31)]).range([0, w]);
    var x = d3.scale.linear().domain([0, data.length]).range([0, w]);
    var y = d3.scale.linear().domain([0, d3.max(data)]).range([h, 0]);

I plotted my line like I would a normal linear scale, but for xAxis:

var xAxis = d3.svg.axis().scale(xLabels).ticks(d3.time.months).tickFormat(d3.time.format("%B")).tickSize(-h).tickSubdivide(true);
    graph.append("svg:g")
          .attr("class", "x axis") 
          .attr("transform", "translate(0," + h + ")")
          .call(xAxis);

I passed in my xLabels for the scale, and formatted my ticks to be months.

Here is the working example on a jsfidde: http://jsfiddle/vB5eW/

本文标签: javascriptLine Chart d3 js x axis monthsStack Overflow