[D3.js并行绘图]错误:属性d:预期数量,"M0,NaNL122.5,NaNL24…".

我试图用D3.js来可视化一个平行的绘图,并使用这个虹膜数据集的例子:

https://d3-graph-gallery.com/graph/parallel_custom.html

我的CSV文件的 struct 如下:

City,GreenAreaDensity,LowEmission,AutobusStopDensity,CirculatingVehicles,ExposedNoisePollution
Torino,7.46,17.3,24.4,277.0,14.9
Vercelli,1.28,11.2,2.1,77.0,8.8
Novara,1.22,11.9,3.8,246.0,14.7
Biella,33.56,10.1,4.1,189.0,9.3
Cuneo,6.82,10.4,6.3,85.0,3.6
Asti,17.14,11.0,1.9,139.0,36.5
Aosta,0.42,8.3,19.0,42.0,6.0
Imperia,1.11,5.4,8.2,191.0,16.7
Savona,7.82,7.7,6.1,183.0,5.1
[...]

在控制台中,对于数据集中的每一行,我都会收到以下错误:

Error: <path> attribute d: Expected number, "M0,NaNL122.5,NaNL24…".

这让我认为PATH函数的y坐标有问题,所以我添加了各种打印函数,以了解为什么有NaN作为第二个坐标.

下面是parallelplot.js文件:

// set the dimensions and margins of the graph
var margin = {top: 30, right: 30, bottom: 10, left: 40},
  width = 560 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

// append the svg object to the body of the page
var svgParallel = d3.select("#parallelPlot")
.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 + ")");

// Parse the Data
d3.csv("../../data/processed/ParallelPlotData.csv", function(data) {

  // Here I set the list of dimension manually to control the order of axis:
  dimensions = ["GreenAreaDensity","LowEmission","AutobusStopDensity","CirculatingVehicles","ExposedNoisePollution"]

  // For each dimension, I build a linear scale. I store all in a y object
  var y = {}
  var name;
  for (i in dimensions) {
    name = dimensions[i]
    //console.log(name);
    y[name] = d3.scaleLinear()
    // .domain( [0,150] ) // --> Same axis range for each group
     .domain( [d3.extent(data, function(d) { 
        //console.log(+d[name] + " is of type: " + typeof(+d[name])) // print the value and the type
           return +d[name];   // --> Different axis range for each group
      })] )
      .range([height, 0])
  }

  // Build the X scale -> it find the best position for each Y axis
  x = d3.scalePoint()
    .range([0, width])
    .domain(dimensions);

  // The path function take a row of the csv as input, and return x and y coordinates of the line to draw for this raw.
  function path(d) {
    return d3.line()(dimensions.map(function(column) {
      console.log(y[column](d[column]));
       return [x(column), y[column](d[column])]; 
      })); 
  }

  // Draw the lines
  svgParallel
    .selectAll("myPath")
    .data(data)
    .enter()
    .append("path")
      .attr("d",  path)
      .style("fill", "none" )
      .style("stroke", function(){ return("#AAA")} )
      .style("opacity", 0.5)
 
  // Draw the axis:
  svgParallel.selectAll("myAxis")
    // For each dimension of the dataset I add a 'g' element:
    .data(dimensions).enter()
    .append("g")
    .attr("class", "axis")
    // I translate this element to its right position on the x axis
    .attr("transform", function(d) { return "translate(" + x(d) + ")"; })
    // And I build the axis with the call function
    .each(function(d) { d3.select(this).call(d3.axisLeft().ticks(5).scale(y[d])); })
    // Add axis title
    .append("text")
      .style("text-anchor", "middle")
      .attr("y", -9)
      .text(function(d) { return d; })
      .style("fill", "black")

})

实际上,yColumn值返回NaN,但如果我在这里打印d[Column],则返回的正是我想要的该轴上的值.

如果我 for each 参数 Select 固定轴,则此问题无关紧要,但我需要轴的不同范围:

// For each dimension, I build a linear scale. I store all in a y object
  var y = {}
  var name;
  for (i in dimensions) {
    name = dimensions[i]
    //console.log(name);
    y[name] = d3.scaleLinear()
    // .domain( [0,150] ) // --> Same axis range for each group
      .domain( [d3.extent(data, function(d) { 
        //console.log(+d[name] + " is of type: " + typeof(+d[name])) // print the value and the type
           return +d[name];   // --> Different axis range for each group
      })] )
      .range([height, 0])
  }

问题也可能出在这里,因为显然它没有读取正确的坐标值,所以在可视化中没有路径.

The parallel plot is like this: enter image description here

可以看到,每个功能的范围值必须不同,因为有不同的度量.

有没有人能帮我想办法解决这个问题?

推荐答案

你的窃听器出在d3.extent()电话上.此函数本身返回一个数组,因此您应该将其直接传递给d3.scaleLinear().domain(...). 以下是固定代码:

  var y = {}
  var name;
  for (i in dimensions) {
    name = dimensions[i]
    y[name] = d3.scaleLinear()
      .domain(
        d3.extent(data, function (d) {  // Note d3.extent result is used as is
          return +d[name];
        })
      )
      .range([height, 0])
  }

Working StackBlitz

Javascript相关问答推荐

输入有关HTML复选框的已判断属性的信息

Mongodb拥有5亿个文档,我想根据JavaScript驱动程序中的两个字段使用regEx进行搜索,而不是模式

如何在加载的元数据上使用juserc和await中获得同步负载?

布局样式在刷新时不持续

如何编辑代码FlipDown.js倒计时?

有什么(最佳)方法可以从模块中获取脚本模块的多姆元素吗?

Vega中的模运算符

硬币兑换运行超时

判断表格单元格中是否存在文本框

使搜索栏更改语言

react—router v6:路由没有路径

无法读取未定义错误的属性路径名''

在Java中寻找三次Bezier曲线上的点及其Angular

映射类型定义,其中值对应于键

在数组中查找重叠对象并仅返回那些重叠对象

为什么客户端没有收到来自服务器的响应消息?

如何在FastAPI中为通过file:/URL加载的本地HTML文件启用CORS?

匹配一个或多个可选重复的特定模式

MongoDB中的嵌套搜索

为什么当雪碧的S在另一个函数中时,Phaser不能加载它?