1

I have a JSON file that looks like that:

EDIT: I am using dates as keys, not integers as I have previously typed.

"2005-12-01": 120,
"2005-10-01": 32,

Now I would need to use the first column as the X axis and the other column as the Y axis. In the examples, they refer to the value by the element name, like:

const line = d3.line()
    .x(d => x(d.date))
    .y(d => y(d.value));

which I cannot do here.

2 Answers 2

2

You've got to map the keys to an array of objects with key/value pairs and then use it to set the domains and draw the line.

// The number of datapoints
var json = {
  "2005-12-01": 120,
  "2005-10-01": 32,
  "2005-08-01": 20,
  "2005-06-01": 123
};

var data = Object.keys(json).map(function (k) { 
  return {date: new Date(k), value: +json[k]};
});

Rest of the code would be the same as drawing a simple line chart.

I created a fork of a sample d3 line chart using the JSON from your question as the input data. (had to hardly change any lines except data mapping)

<!DOCTYPE html>
<meta charset="utf-8">

<style type="text/css">
.line {
    fill: none;
    stroke: #ffab00;
    stroke-width: 3;
}
</style>
<body>
</body>

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

// 2. Use the margin convention practice 
var margin = {top: 50, right: 50, bottom: 50, left: 50}
  , width = window.innerWidth - margin.left - margin.right // Use the window's width 
  , height = window.innerHeight - margin.top - margin.bottom; // Use the window's height

// The number of datapoints
var json = {
"2005-12-01": 120,
"2005-10-01": 32,
"2005-08-01": 20,
"2005-06-01": 123
};

var data = Object.keys(json).map(function (k) { return {date: new Date(k), value: +json[k]};});

// 5. X scale will use the index of our data
var xScale = d3.scaleTime()
    .domain(d3.extent(data, d => d.date)) // input
    .range([0, width]); // output

// 6. Y scale will use the randomly generate number 
var yScale = d3.scaleLinear()
    .domain(d3.extent(data, d => d.value)) // input 
    .range([height, 0]); // output 

// 7. d3's line generator
var line = d3.line()
    .x(function(d, i) { return xScale(d.date); }) // set the x values for the line generator
    .y(function(d) { return yScale(d.value); }) // set the y values for the line generator 
    .curve(d3.curveMonotoneX) // apply smoothing to the line

// 1. Add the SVG to the page and employ #2
var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// 3. Call the x axis in a group tag
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(xScale)); // Create an axis component with d3.axisBottom

// 4. Call the y axis in a group tag
svg.append("g")
    .attr("class", "y axis")
    .call(d3.axisLeft(yScale)); // Create an axis component with d3.axisLeft

// 9. Append the path, bind the data, and call the line generator 
svg.append("path")
    .datum(data) // 10. Binds data to the line 
    .attr("class", "line") // Assign a class for styling 
    .attr("d", line); // 11. Calls the line generator 

</script>

6
  • Thanks, I am trying to figure out, where do you set the domains? Like x.domain(d3.extent...) something like that
    – John V
    Commented Nov 14, 2018 at 15:59
  • Yes, check out the code in the snippet. It has setting of the domains as .domain(d3.extent(data, d => d.date))
    – Shashank
    Commented Nov 14, 2018 at 16:00
  • @Ah, thanks, I am using another example and the code is a bit different :( Will need to play with it for a while
    – John V
    Commented Nov 14, 2018 at 16:05
  • I keep getting Error: <path> attribute d: Expected number, "MNaN,150CNaN,NaN,…" error, I guess it has to do with Date?
    – John V
    Commented Nov 14, 2018 at 16:15
  • 1
    I got it, it was a problem with Parsetime where I left my old format. Thanks a lot again!
    – John V
    Commented Nov 14, 2018 at 16:19
0

loop over the keys of your JSON and create new objects

data = Object.keys(data).map(k => { return {x:+k, value: data[k]}; });

Maybe you need to sort the array

data.sort( (a,b) => a.x - b.x );

var data = {"0": 120,
"1": 32,
"2": 234,
"3": 43};

data = Object.keys(data).map(k => { return {x:+k, value: data[k]}; });

console.log(data);

3
  • @JohnV not a NaN but a small syntax error, forgot a )
    – rioV8
    Commented Nov 14, 2018 at 14:49
  • Yeah that I fixed too but I still get NaN. Could be that my keys are YYYY-MM-DD formatted dates?
    – John V
    Commented Nov 14, 2018 at 14:54
  • Yes, I put it as an example, I did not know it could matter.
    – John V
    Commented Nov 14, 2018 at 14:59

Not the answer you're looking for? Browse other questions tagged or ask your own question.