我有一些要可视化为“分组折线图”的数据,其中重复绘制了我的三个增长时间段(离散地,仅连接了3个数据点,没有一条连续线),与分组条形图的方式相同功能。我也兜了好几圈。我的数据结构是这样的:
var data = [
{'fmc':'fmc1', 'values':[{'growth':12, 'period':'t1'},{'growth':7,'period':'t2'},{'growth':4, 'period':'t3'}]},
{'fmc':'fmc2', 'values':[{'growth':15, 'period':'t1'},{'growth':8,'period':'t2'},{'growth':4, 'period':'t3'}]},
...
]
下面的完整代码段:
var margins = {top: 20, right: 20, bottom: 30, left: 40},
width = 960,
height = 500;
var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;
var x0 = d3.scaleBand()
.rangeRound([0, width]).padding(.1);
var x1 = d3.scaleBand().padding(.05);
var y = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom(x0)
.tickSize(0);
var yAxis = d3.axisRight(y);
var color = d3.scaleOrdinal()
.range(["#003366","#366092","#4f81b9","#b8cce4","#f6d18b"]);
var svg = d3.select('body').append("svg")
.attr("width", totalWidth)
.attr("height", totalHeight);
var graphGroup = svg.append("g")
.attr("transform", "translate(" + margins.left + "," + margins.top + ")");
//var jsonData = d3.json('11-insti-data.json');
//jsonData.then(function(data) {
var data = [{'fmc': 'fmc1',
'values': [{'growth': 19.58, 'period': 't1'},
{'growth': 4.12, 'period': 't2'},
{'growth': 6.09, 'period': 't3'}]},
{'fmc': 'fmc2',
'values': [{'growth': 36.35, 'period': 't1'},
{'growth': 20.9, 'period': 't2'},
{'growth': 9.21, 'period': 't3'}]},
{'fmc': 'fmc3',
'values': [{'growth': 30.69, 'period': 't1'},
{'growth': 14.72, 'period': 't2'},
{'growth': 5.66, 'period': 't3'}]},
{'fmc': 'fmc4',
'values': [{'growth': 100.66, 'period': 't1'},
{'growth': 58.55, 'period': 't2'},
{'growth': 32.71, 'period': 't3'}]},
{'fmc': 'fmc5',
'values': [{'growth': 27.8, 'period': 't1'},
{'growth': 6.97, 'period': 't2'},
{'growth': 12.55, 'period': 't3'}]},
{'fmc': 'fmc6',
'values': [{'growth': 32.8, 'period': 't1'},
{'growth': -0.46, 'period': 't2'},
{'growth': 11.54, 'period': 't3'}]},
{'fmc': 'fmc7',
'values': [{'growth': -3.83, 'period': 't1'},
{'growth': 11.32, 'period': 't2'},
{'growth': 7.9, 'period': 't3'}]},
{'fmc': 'fmc8',
'values': [{'growth': 2.93, 'period': 't1'},
{'growth': -13.87, 'period': 't2'},
{'growth': 2.6, 'period': 't3'}]},
{'fmc': 'fmc9',
'values': [{'growth': 85.53, 'period': 't1'},
{'growth': 42.83, 'period': 't2'},
{'growth': 71.27, 'period': 't3'}]},
{'fmc': 'fmc10',
'values': [{'growth': 44.02, 'period': 't1'},
{'growth': 36.0, 'period': 't2'},
{'growth': 9.76, 'period': 't3'}]}];
var categoriesNames = data.map(function(d) { return d.fmc; });
var rateNames = data[0].values.map(function(d) { return d.period; });
x0.domain(categoriesNames);
x1.domain(rateNames).rangeRound([0, x0.bandwidth()]);
y.domain([0, 100]);
graphGroup.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
graphGroup.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style('font-weight','bold')
.text("Value");
var line = d3.line()
.x(function(d) { return x1(d.period); })
.y(function(d) { return y(d.growth); })
.curve(d3.curveCardinal);
var slice = graphGroup.selectAll(".slice")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform",function(d) { return "translate(" + x0(d.fmc) + ",0)"; });
slice.selectAll('path')
.data(function(d) { return d.values; })
.enter().append('path')
.attr("d", line(data.growth))
.attr("stroke", "#366092")
.attr("stroke-width", 3)
.attr("fill", "none");
slice.selectAll('circle')
.data(function(d) { return d.values; })
.enter().append('circle')
.attr('cx', function(d) {return x1(d.period)})
.style("fill", function(d) { return color(d.period) })
.attr("cy", function(d) { return y(d.growth); })
.attr('r', 3);
<script src="https://d3js.org/d3.v5.min.js"></script>
我在D3v5的第2行出现错误:
未捕获的TypeError:无法读取未定义的属性长度
当我将数据硬编码到其中时,这有点困惑。
我猜我的线路访问器功能未达到标准水平:
slice.selectAll('path')
.data(function(d) { return d.values; })
.enter().append('path')
.attr("d", line(data.growth))
.attr("stroke", "#366092")
.attr("stroke-width", 3)
.attr("fill", "none");
我也尝试了不同的组合,例如:attr("d", line(data.values.growth))
,但仍然没有超出错误范围。
到底是什么问题?最佳解决方案是什么?
答案 0 :(得分:2)
两个小变化:
将数据括在方括号中(即,使其成为包含另一个数组的数组),否则传递的数据将是内部对象:
slice.selectAll('path')
.data(function(d) {
return [d.values];//instead of return d.values
});
您的路径的d
属性(line(data.growth)
)毫无意义,您只需要将已经绑定的数据传递给行生成器即可:
.attr("d", line)
这是您的代码,其中有两项更改:
var margins = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = 960,
height = 500;
var totalWidth = width + margins.left + margins.right;
var totalHeight = height + margins.top + margins.bottom;
var x0 = d3.scaleBand()
.rangeRound([0, width]).padding(.1);
var x1 = d3.scaleBand().padding(.05);
var y = d3.scaleLinear()
.range([height, 0]);
var xAxis = d3.axisBottom(x0)
.tickSize(0);
var yAxis = d3.axisRight(y);
var color = d3.scaleOrdinal()
.range(["#003366", "#366092", "#4f81b9", "#b8cce4", "#f6d18b"]);
var svg = d3.select('body').append("svg")
.attr("width", totalWidth)
.attr("height", totalHeight);
var graphGroup = svg.append("g")
.attr("transform", "translate(" + margins.left + "," + margins.top + ")");
//var jsonData = d3.json('11-insti-data.json');
//jsonData.then(function(data) {
var data = [{
'fmc': 'fmc1',
'values': [{
'growth': 19.58,
'period': 't1'
},
{
'growth': 4.12,
'period': 't2'
},
{
'growth': 6.09,
'period': 't3'
}
]
},
{
'fmc': 'fmc2',
'values': [{
'growth': 36.35,
'period': 't1'
},
{
'growth': 20.9,
'period': 't2'
},
{
'growth': 9.21,
'period': 't3'
}
]
},
{
'fmc': 'fmc3',
'values': [{
'growth': 30.69,
'period': 't1'
},
{
'growth': 14.72,
'period': 't2'
},
{
'growth': 5.66,
'period': 't3'
}
]
},
{
'fmc': 'fmc4',
'values': [{
'growth': 100.66,
'period': 't1'
},
{
'growth': 58.55,
'period': 't2'
},
{
'growth': 32.71,
'period': 't3'
}
]
},
{
'fmc': 'fmc5',
'values': [{
'growth': 27.8,
'period': 't1'
},
{
'growth': 6.97,
'period': 't2'
},
{
'growth': 12.55,
'period': 't3'
}
]
},
{
'fmc': 'fmc6',
'values': [{
'growth': 32.8,
'period': 't1'
},
{
'growth': -0.46,
'period': 't2'
},
{
'growth': 11.54,
'period': 't3'
}
]
},
{
'fmc': 'fmc7',
'values': [{
'growth': -3.83,
'period': 't1'
},
{
'growth': 11.32,
'period': 't2'
},
{
'growth': 7.9,
'period': 't3'
}
]
},
{
'fmc': 'fmc8',
'values': [{
'growth': 2.93,
'period': 't1'
},
{
'growth': -13.87,
'period': 't2'
},
{
'growth': 2.6,
'period': 't3'
}
]
},
{
'fmc': 'fmc9',
'values': [{
'growth': 85.53,
'period': 't1'
},
{
'growth': 42.83,
'period': 't2'
},
{
'growth': 71.27,
'period': 't3'
}
]
},
{
'fmc': 'fmc10',
'values': [{
'growth': 44.02,
'period': 't1'
},
{
'growth': 36.0,
'period': 't2'
},
{
'growth': 9.76,
'period': 't3'
}
]
}
];
var categoriesNames = data.map(function(d) {
return d.fmc;
});
var rateNames = data[0].values.map(function(d) {
return d.period;
});
x0.domain(categoriesNames);
x1.domain(rateNames).rangeRound([0, x0.bandwidth()]);
y.domain([0, 100]);
graphGroup.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
graphGroup.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style('font-weight', 'bold')
.text("Value");
var line = d3.line()
.x(function(d) {
return x1(d.period);
})
.y(function(d) {
return y(d.growth);
})
.curve(d3.curveCardinal);
var slice = graphGroup.selectAll(".slice")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) {
return "translate(" + x0(d.fmc) + ",0)";
});
slice.selectAll('path')
.data(function(d) {
return [d.values];
})
.enter()
.append('path')
.attr("d", line)
.attr("stroke", "#366092")
.attr("stroke-width", 3)
.attr("fill", "none");
slice.selectAll('circle')
.data(function(d) {
return d.values;
})
.enter().append('circle')
.attr('cx', function(d) {
return x1(d.period)
})
.style("fill", function(d) {
return color(d.period)
})
.attr("cy", function(d) {
return y(d.growth);
})
.attr('r', 3);
<script src="https://d3js.org/d3.v5.min.js"></script>