D3错误:<path>属性d:预期的数字,“MNaN,NaNLNaN,NaNL ......”

时间:2018-06-02 22:10:21

标签: d3.js

我觉得问题在于order_date格式。

通过区域功能的所有日志都可以正常工作但不会渲染,当我检查控制台时,我得到Error: <path> attribute d: Expected number, "MNaN,NaNLNaN,NaNL…"

如果我评论.attr('d', area)没有错误。

这也是在jsFiddle(https://jsfiddle.net/walkerl/8uxrxm0k/3/

const rawData = [{
    "agency_id": 541,
    "agency_name": "Store1",
    "order_date": "2018-01-01T00:00:00.000Z",
    "store_name": "Store1",
    "store_id": 1469,
    "orders": 3,
    "avg_order_size": 2,
    "revenue": 500
  },
  {
    "agency_id": 541,
    "agency_name": "Store2",
    "order_date": "2018-01-01T00:00:00.000Z",
    "store_name": "Store2",
    "store_id": 1468,
    "orders": 2,
    "avg_order_size": 1,
    "revenue": 81
  },
  {
    "agency_id": 541,
    "agency_name": "Store3",
    "order_date": "2018-01-01T00:00:00.000Z",
    "store_name": "Store3",
    "store_id": 1404,
    "orders": 14,
    "avg_order_size": 1,
    "revenue": 1348.26
  },
  {
    "agency_id": 541,
    "agency_name": "Store4",
    "order_date": "2018-01-01T00:00:00.000Z",
    "store_name": "Store4",
    "store_id": 1517,
    "orders": 41,
    "avg_order_size": 1,
    "revenue": 8115.6
  },
  {
    "agency_id": 541,
    "agency_name": "Store1",
    "order_date": "2018-01-02T00:00:00.000Z",
    "store_name": "Store1",
    "store_id": 1469,
    "orders": 7,
    "avg_order_size": 1,
    "revenue": 1522
  },
  {
    "agency_id": 541,
    "agency_name": "Store2",
    "order_date": "2018-01-02T00:00:00.000Z",
    "store_name": "Store2",
    "store_id": 1468,
    "orders": 3,
    "avg_order_size": 2,
    "revenue": 297.5
  },
  {
    "agency_id": 541,
    "agency_name": "Store3",
    "order_date": "2018-01-02T00:00:00.000Z",
    "store_name": "Store3",
    "store_id": 1404,
    "orders": 14,
    "avg_order_size": 2,
    "revenue": 1515.76
  },
  {
    "agency_id": 541,
    "agency_name": "Store4",
    "order_date": "2018-01-02T00:00:00.000Z",
    "store_name": "Store4",
    "store_id": 1517,
    "orders": 40,
    "avg_order_size": 1,
    "revenue": 7288.8
  }
];

/**
const cleanData = [
  {
    "order_date": "2017-12-31",
    "Store1": 500,
    "Store2": 81,
    "Store3": 1348.26,
    "Store4": 8115.6
  },
  {
    "order_date": "2018-01-01",
    "Store1": 1522,
    "Store2": 297.5,
    "Store3": 1515.76,
    "Store4": 7288.8
  }
]
*/


const parseTime = d3.timeParse('%Y-%m-%d');
const formatTime = d3.timeFormat('%Y-%m-%dT%H:%M:%S.%LZ');
const p = d3.precisionFixed('.01');
const formatNumber = d3.format(`.${p}f`);
const stores = rawData
  .map(d => ({
    name: d.store_name,
    id: d.store_id
  }))
  .reduce((acc, cur) => acc.find(s => s.id === cur.id) ? acc : [...acc, cur], []);
const storeNames = stores.map(s => s.name)

// This is to group the data as objects with the date and revenue for each store.  Also, the date has to be a js object
const stackData = rawData
  .map(d => ({ ...d,
    order_date: formatTime(new Date(d.order_date)),
    revenue: formatNumber(d.revenue)
  }))
  .reduce((acc, cur) => {
    let existing = acc.find(e => e.order_date === cur.order_date)
    if (existing) {
      existing[cur.store_name] = cur.revenue;
      return acc
    }
    return [...acc, {
      order_date: cur.order_date,
      [cur.store_name]: cur.revenue
    }]
  }, []);

const margin = {
  top: 50,
  right: 30,
  bottom: 70,
  left: 50
};
const width = 960 - margin.right - margin.left;
const height = 600 - margin.top - margin.bottom;

const color = d3.scaleOrdinal(d3.schemePastel1);

let g = d3.select('#stacked-area')
  .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})`)

let x = d3.scaleTime()
  .range([0, width])

let y = d3.scaleLinear()
  .range([height, 0]);

let xAxisCall = d3.axisBottom();
let yAxisCall = d3.axisLeft();

let xAxisGroup = g.append('g')
  .attr('class', 'x axis')
  .attr('transform', `translate(0, ${height})`)

let yAxisGroup = g.append('g')
  .attr('class', 'y axis')


let stack = d3.stack()
  .keys(stores.map(s => s.name))

stack.order(d3.stackOrderNone);
stack.offset(d3.stackOffsetNone);


var area = d3.area()
  .x(function(d) {
    console.log('Data in X: ', d)
    return x(d.data.order_date);
  })
  .y0(function(d) {
    console.log('Data in Y0: ', d)
    return y(d[0]);
  })
  .y1(function(d) {
    console.log('Data in Y1: ', d)
    return y(d[1]);
  });

// console.log('Area: ', area)
// console.log('StackData: ', stackData)
// console.log('Stack: ', stack(stackData))

// Will need to get max y-value */
const maxY = stackData.map(d => {
  const vals = d3.keys(d).map(k => k !== 'order_date' ? d[k] : 0);
  return d3.sum(vals);
});

// For any missing data, add a 0
const cleanData = stackData.map(d => {
  let existingStores = d3.keys(d);
  storeNames.forEach(n => {
    if (!existingStores.includes(n)) d[n] = 0
  })
  return d
});

// Update Scales
x.domain(d3.extent(rawData.map(d => new Date(d.order_date))));
// x.domain(d3.extent(stackData, function(d) {
//  return d.order_date;
// }));
y.domain([0, maxY]);

// Update axes
xAxisCall.scale(x);
xAxisGroup.call(xAxisCall)
yAxisCall.scale(y);
yAxisGroup.call(yAxisCall);

console.log('Data going to stack: ', cleanData);
const graph = g.selectAll('.store')
  .data(stack(cleanData));

console.log('CleanData: ', JSON.stringify(cleanData))
graph.enter().append('g')
  .attr('class', d => 'store')
  .append('path')
  .attr('class', 'area')
  .attr('d', area)
// .style('fill', d => color(d.key))
// .style('fill-opacity', 0.5)
/* } */
<script src="https://d3js.org/d3.v5.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">


<div class="container">
  <div class="row">
    <div id="left-charts" class="col-sm-12 col-md-8">
      <div id="stacked-area"></div>
    </div>
  </div>
</div>

1 个答案:

答案 0 :(得分:0)

这是一个部分答案,因为我无法让它显示但能够摆脱NaN。我发现的问题是你从来没有在许多地方调用order_date上的parseTime。这也是为什么x轴刻度不会出现在你的小提琴中的原因。此外,y轴刻度不会出现。这让我觉得y域也不对。我在maxY上做了一个console.log,但它显示了两个值而不是一个值。 data in maxY: 10044.86,10624.060000000001

我觉得情节没有出现,因为数据没有以适当的格式显示。这是一个小提琴,我已经能够摆脱NaN但获得价值。

这是编辑的小提琴。

https://jsfiddle.net/coolakul/cxsx8e41/5/

var area = d3.area()
  .x(function(d) {
    console.log('Data in X: ', parseTime(d.data.order_date))
    return parseTime(d.data.order_date);
  })
  .y0(function(d) {
    console.log('Data in Y0: ', d[0])
    return d[0];
  })
  .y1(function(d) {
    console.log('Data in Y1: ', d[1])
    return d[1];
  });

愿意讨论更多内容,但需要了解您是否尝试基于示例实施图表以及您正在寻找的最终输出信息。