grouser
grouser

Reputation: 628

Error: <path> attribute d: Expected number, "M67,0L67,0LNaN,0LNaN,0L728"

I am trying to create a line chart but I get the error...

Error: attribute d: Expected number, "M67,0L67,0LNaN,0LNaN,0L728"

... every time I have three or more elements. I want to set the date with that format in the x-axis. I have tried scaling with times, but I just want to show the dates that the JSON file contains, not a range of dates.

This is the JSON file I am using:

[{"date": "20-Jun-19", "close": "5", "text": "Test"}, 
 {"date": "21-Jun-19", "close": "5", "text": "Test"}, 
 {"date": "25-Jun-19", "close": "5", "text": "Test"}]

This is the Javascript I am using.

var label = d3.select(".label");
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 1460 - margin.left - margin.right,
height = 870 - margin.top - margin.bottom;

var x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1);
var y = d3.scale.linear().range([height, 0]);

// Define the axes
var xAxis = d3.svg.axis().scale(x)
    .orient("bottom").ticks(20);

var yAxis = d3.svg.axis().scale(y)
    .orient("left").ticks(15);

// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });

// Adds the svg canvas
var svg = d3.select(".anxiety-graphic")
    .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 + 
")");

d3.json("data.json", function(error, data) {
    var categoriesNames = data.map(function (d) {
        return +d.date;
    });
x.domain(categoriesNames);
    // Scale the range of the data
x.domain(d3.extent(data, function(d) { console.log(d); return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);

// Add the valueline path.
svg.append("path")      // Add the valueline path.
    .attr("class", "line")
    .attr("d", valueline(data));

    // Add the valueline path.

    svg.selectAll("circle")
    .data(data)
    .enter()
    .append("circle")
    .attr("r", 10)
  .attr("cx", function(d) {
    return x(d.date)
  })
  .attr("cy", function(d) {
    return y(d.close)
  })
  .on("mouseover", function(d,i) {

   label.style("transform", "translate("+ x(d.date) +"px," + (y(d.close)) +"px)")
   label.text(d.close)

});

// Add the X Axis
svg.append("g")         // Add the X Axis
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

// Add the Y Axis
svg.append("g")         // Add the Y Axis
    .attr("class", "y axis")
    .call(yAxis);

});

Upvotes: 2

Views: 83

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

For whatever reason, you are replacing the correct domain...

x.domain(categoriesNames);

... for a wrong one in the very next line:

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

d3.extent returns an array with 2 values only, and that's why you're getting this issue when your data have three or more elements.

Also, the map for creating categoriesNames has an issue:

var categoriesNames = data.map(function (d) {
    return +d.date;
});

Since the date is a string containing letters, it's not clear why you're using the unary plus (which will return NaN). Drop that:

var categoriesNames = data.map(function (d) {
    return d.date;
});

Here is your code with those changes:

var label = d3.select(".label");
var margin = {
    top: 30,
    right: 20,
    bottom: 30,
    left: 50
  },
  width = 1460 - margin.left - margin.right,
  height = 870 - margin.top - margin.bottom;

var x = d3.scale.ordinal()
  .rangeRoundBands([0, width], .1);
var y = d3.scale.linear().range([height, 0]);

// Define the axes
var xAxis = d3.svg.axis().scale(x)
  .orient("bottom").ticks(20);

var yAxis = d3.svg.axis().scale(y)
  .orient("left").ticks(15);

// Define the line
var valueline = d3.svg.line()
  .x(function(d) {
    return x(d.date);
  })
  .y(function(d) {
    return y(d.close);
  });

// Adds the svg canvas
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 +
    ")");

var data = [{
    "date": "20-Jun-19",
    "close": "5",
    "text": "Test"
  },
  {
    "date": "21-Jun-19",
    "close": "5",
    "text": "Test"
  },
  {
    "date": "25-Jun-19",
    "close": "5",
    "text": "Test"
  }
];

var categoriesNames = data.map(function(d) {
  return d.date;
});
x.domain(categoriesNames);

y.domain([0, d3.max(data, function(d) {
  return d.close;
})]);

// Add the valueline path.
svg.append("path") // Add the valueline path.
  .attr("class", "line")
  .attr("d", valueline(data));

// Add the valueline path.

svg.selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("r", 10)
  .attr("cx", function(d) {
    return x(d.date)
  })
  .attr("cy", function(d) {
    return y(d.close)
  })
  .on("mouseover", function(d, i) {

    label.style("transform", "translate(" + x(d.date) + "px," + (y(d.close)) + "px)")
    label.text(d.close)

  });

// Add the X Axis
svg.append("g") // Add the X Axis
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);

// Add the Y Axis
svg.append("g") // Add the Y Axis
  .attr("class", "y axis")
  .call(yAxis);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

Upvotes: 2

Related Questions