d3.js - D3 Error: attribute d: Expected number, "MNaN,NaNLNaN,NaNL…"
问题描述
I have a feeling that the issue is with the order_date format.
All the logs through the area function work but it doesn't render and when I check the console, I get Error: <path> attribute d: Expected number, "MNaN,NaNLNaN,NaNL…"
If I comment out the .attr('d', area)
no errors.
This is also on 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>
解决方案
这是部分答案,因为我仍然无法显示它,但能够摆脱 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];
});
很想讨论更多,但需要有关您是否尝试基于示例实现图表以及您正在寻找的最终输出的信息。
推荐阅读
- javascript - Animation doesn't work when adding a property transition effect
- java - Arguments of methods
- java - How to wrap Jpa @Query placeholder in single quotes
- redux - How to change all hidden values to false in each state object?
- javascript - How to pass the variable in python to the JavaScript
- python - prettier seems to not working in VScode (python)
- python - Wait_for and buttons not working for discord bot
- django - 跨域请求被阻止:同源策略不允许读取远程资源...(原因:CORS 未成功)
- sql - 从表中选择具有最大日期的行
- git - 将 Homestead Vagrant VM 上的项目上传到 Github