0

I'm a newbie to d3 and dc.js and am trying to make a timeseries chart of stock prices.

For some reason, I can't get my time Dimension to work. I have a feeling it has something to do with the way my dates are formatted, and I've tried experimenting with this but have not been able to solve the problem.

My code is as follows

//create global variable 'stockpricedata' to store CSV data;  
var stockpricedata = [];

//create global variable to enable parsing of dateFormat
var dateFormat = d3.time.format('%d/%m/%Y');


//create function that will input CSV data and draw a timechart.
//this function is called in a seperate piece of code using queue.js
//the code that loads the CSV data is also executed separately to this code

function makeChart(error, data) {

  //First lets create a nested function that converts 'Test_Score' variable 
  //from char to numeric

  function convData(data) {

    stockpricedata = data;
    stockpricedata.forEach(function(d){ 
      d['Open'] = +d['Open']; 
      d['High'] = +d['High']; 
      d['Low'] = +d['Low']; 
      d['Close'] = +d['Close']; 
      d['Volume'] = +d['Volume'];    
      d['Adj Close'] = +d['Adj Close']; 
      d['Adj Close'] = +d['Adj Close'];
      d.daydate = dateFormat.parse(d.Date);


    });

    };

  //Call the function
  convData(data);


  //initiate crossfilter

  var ndx = crossfilter(stockpricedata);
  var all = ndx.groupAll();

  //test ndx object to ensure that it initiated correctly
  var n = ndx.groupAll().reduceCount().value();
  console.log(stockpricedata);
  console.log("Lets say there are " + n + " datapoints in my file"); //yes, this is showing a valid number, so this is working.


  //Create 'Date' dimension that returns the DAY.
  var DateDim = ndx.dimension(function(d) 
    {return d.daydate;}
    );
  console.log(DateDim.top(5))



  //Create 'Sum' grouping to Sum the price (there will only be 1 for each day, so should just show the stockprice) to calculate y-axis

  var PriceGroup = DateDim.group().reduceSum(function(d){return d.Close;}); //d.Close is the 'closing price' datapoint


  //create chart object and link it to HTML element
  var StockPriceChart  = dc.barChart('#histprice-line-chart');


  //create minDate and maxDate variables so that we can set the x-axis scale.

  var minDate = DateDim.bottom(1)[0].date;
  var maxDate = DateDim.top(1)[0].date;
  console.log("min date is " + minDate + " and max date is " + maxDate);

  //chart attributes
   StockPriceChart
      .width(600)
      .height(180)
      .dimension(DateDim) //x-axis (range of scores)
      .group(PriceGroup) //y-axis 
      .x(d3.time.scale().domain([minDate,maxDate]))
      .elasticY(true)
      .xAxisLabel('Time')
      .yAxisLabel('Price')
     //.xAxis();
     // .margins({top: 10, right: 20, bottom: 50, left: 50});

     // showtime!
    dc.renderAll();


};

The data seems to be loading and showing up in the console just fine. My original 'Date' field is formatted to D3 format in my 'daydate' variable. An example datapoint in the console is as follows:

200: Object Adj Close: 90.22737 Close: 93.8913 Date: "3/04/15" High: 93.8913 Low: 93.8913 Open: 93.8913 Volume: 0 daydate: Fri Apr 03 15 00:00:00 GMT+1100 (AEDT)

But for some reason the following code doesn't seem to be working.

var DateDim = ndx.dimension(function(d) 
{return d.daydate;}
);
console.log(DateDim).top(5); // ?!?!? why is this not working ?!?!?!?

I also get the following error in the console: 'Uncaught TypeError: Cannot read property 'top' of undefined', when I try log DateDim to the console.

Any help on this would be much appreciated!

Thanks,

J

Ethan Jewett
  • 6,002
  • 16
  • 25
TheBlake
  • 267
  • 1
  • 5
  • 12
  • Sorry, I also realised there is a syntax error - I have changed console.log(DateDim).top(5) to console.log(DateDim.top(5)); to correct for this. – TheBlake Jan 09 '16 at 03:41
  • Nevertheless I'm still getting the following message in the console: "min date is undefined and max date is undefined" – TheBlake Jan 09 '16 at 03:41

2 Answers2

2

You have the code

var minDate = DateDim.bottom(1)[0].date;
var maxDate = DateDim.top(1)[0].date;

Your data records contain the properties daydate and Date, but not date. So DateDim.bottom(1)[0].date and DateDim.top(1)[0].date are undefined. Change it to:

var minDate = DateDim.bottom(1)[0].daydate;
var maxDate = DateDim.top(1)[0].daydate;
Ethan Jewett
  • 6,002
  • 16
  • 25
  • Thanks Ethan! That has solved 1 problem, and the values are no longer shower up as 'undefined'. I am however still running into 2 problems. (A) the min/max dates don't seem to reflect actuals dates. My actual data has dates ranging from 04/01/1999 to 08/01/2016, however the log is showing min date is Tue Jan 04 0 00:00:00 GMT+1100 (AEDT) and max date is Wed Dec 30 99 00:00:00 GMT+1100 (AEDT) – TheBlake Jan 09 '16 at 23:31
  • Look at DateDim.top(Infinity). Is it sorted properly? I'd guess not because your accessor for DateDim returns an object rather than just returning d.daydate. – Ethan Jewett Jan 09 '16 at 23:36
  • Secondly, (B) while the chart is being drawn, it has no values (i.e. just an x and y axis with no actual line showing), so it still seems to be having issues interpreting the data. I have tried experimenting by changing var DateDim = ndx.dimension(function(d) {return d.daydate;}); --> specifically changing return d.daydate to return d3.time.day(d.daydate) but this hasn't worked... – TheBlake Jan 09 '16 at 23:38
  • Ah, sorry. I was wrong. Was thrown off by curly braces and a mobile device. Could you share some of your data in the question? Or better yet, put together a working example on jsFiddle or a similar site? – Ethan Jewett Jan 09 '16 at 23:40
  • Thanks for the super quick response Ethan :) I'm really new to this - how can I look at the sorting? – TheBlake Jan 09 '16 at 23:42
  • Just throw in a console.log(DateDim.top(Infinity)) :-) I'm pretty sure your accessor isn't the problem, but it sounds like a sorting issue. Maybe in your parsing. – Ethan Jewett Jan 09 '16 at 23:43
  • It's also possible it is rendered but there are too many bars so they are invisible. Don't know off the top of my head and on a mobile so can't test. Sorry. – Ethan Jewett Jan 09 '16 at 23:46
  • Hi Ethan - Will quickly run the console.log above. Also, I have uploaded my CSV file using File Dropper (I haven't used JS Fiddle before but will look into this for future reference). Link is here --> http://www.filedropper.com/stockpricecba – TheBlake Jan 09 '16 at 23:48
  • Whoa. Yeah, definitely too many groups. It's going to result in 1000s of bars. I'd suggest trying to get it working with a small subset (a couple months) and then think about how to aggregate the data so that you'll have a number of bars that can be displayed. You can implement this aggregation (like d3.time.month) in the dimension accessor. – Ethan Jewett Jan 09 '16 at 23:52
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/100260/discussion-between-theblake-and-ethan-jewett). – TheBlake Jan 09 '16 at 23:54
0

The problem ended up being caused by too many datapoints being rendered in a barChart. Reducing the # of data points in 1 chart, as well as changing from .barChart to .lineChart solved this. Huge thanks @Ethan for helping troubleshoot this and solve a number of additional issues!

TheBlake
  • 267
  • 1
  • 5
  • 12