D3.js D3 v5:多行图表,无法绘制多行
感谢您提前提供的任何帮助,我是D3新手,很难理解我在网上看到的多行图表示例。我有如下数据:D3.js D3 v5:多行图表,无法绘制多行,d3.js,D3.js,感谢您提前提供的任何帮助,我是D3新手,很难理解我在网上看到的多行图表示例。我有如下数据: country,year,average United States,1970,51 United States,1971,50 United States,1972,54 United States,1973,56 United States,1974,53 United States,1975,57 United States,1976,60 Brazil,1970,23 Brazil,1971,25
country,year,average
United States,1970,51
United States,1971,50
United States,1972,54
United States,1973,56
United States,1974,53
United States,1975,57
United States,1976,60
Brazil,1970,23
Brazil,1971,25
Brazil,1972,24
Brazil,1973,21
Brazil,1974,25
Brazil,1975,26
Brazil,1976,24
对于多个国家,我想为它们中的每一个列一行
var margin = {top: 10, right: 40, bottom: 150, left: 70},
width = 760 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var w = width + margin.left + margin.right;
var h = height + margin.top + margin.bottom;
var svg = d3.select("body").append("svg") // this appends a new SVG element to body
.attr("width", w) // set the width
.attr("height", h) // set the height
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// x scale will handle time
var xScale = d3.scaleBand().range([0, width]).padding(0.1);
// y scale will handle energy consumption values
var yScale = d3.scaleLinear().range([height,0]);
// Define X and Y AXIS
var yAxis = d3.axisLeft(yScale).ticks(5);
var xAxis = d3.axisBottom(xScale);
function rowConverter(data) {
return {
country : data.country,
year : +data.year,
average : +data.average // the + operator parses strings into numbers
};
}
// line generator function
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d) { return xScale(d.year); })
.y(function(d) { return yScale(d.average); })
d3.csv("EvenMore.csv", rowConverter).then(function(data) {
var countries = d3.nest()
.key(function (d) { return d.country; })
.entries(data);
console.log(countries);
yScale.domain([0,d3.max(data, function(d) {return d.average; } )]);
xScale.domain(d3.extent(data, function(d) { return d.year; } ));
// Draw xAxis
svg.append("g") // add a new svg group element
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis)
.selectAll("text")
.attr("dx", "-.8em")
.attr("dy", ".25em")
.attr("text-anchor", "end");
// Draw yAxis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.selectAll("text")
.attr("dx", "-.8em")
.attr("dy", ".25em")
.attr("text-anchor", "end");
svg.selectAll("path")
.data(countries)
.enter()
.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.values);
});
});
我不知道这些错误是什么意思,错误:属性d:预期数字,“…3333 4LNAN,114.27777777…”
问题 你没有正确使用波段刻度。波段标度不是定量标度,因此没有上限和下限。相反,需要指定域的每个值: 域中的第一个元素将映射到第一个频带,即 将第二个域值转换为第二个频带,依此类推。域值是 内部存储在从字符串化值到索引的映射中;这个 然后使用生成的索引确定波段() 这就解释了您的错误,您为域指定了两个值,第一年和最后一年。在查看比例时,我们可以从几个方面看到域仅为这两个值(默认情况下,波段比例的轴包括所有刻度,但即使在这里,如果1970和1976是起始值和结束值,我们也会看到间距非常奇怪): 错误消息还有助于查找错误:如果第一个坐标的x值为NaN,则在检查路径
d
属性时(尤其是在没有应用任何曲线的情况下),消息将显示“预期数字”,MNan,1234…”
,我们可以看到每个坐标的x值,但第一个和最后一个是NaN
解决方案
您需要提供范围内的所有值。我们可以通过以下方式获取所有值:
xScale.domain(data.map(function(d) { return d.year; }))
设置域时,缩放将清除重复项
var margin={top:10,right:40,bottom:150,left:70},
宽度=760-边距.左-边距.右,
高度=500-margin.top-margin.bottom;
var w=宽度+边距.left+边距.right;
var h=高度+边距.top+边距.bottom;
var svg=d3.select(“body”).append(“svg”)//这将向body追加一个新的svg元素
.attr(“宽度”,w)//设置宽度
.attr(“高度”,h)//设置高度
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
//x刻度将处理时间
var xScale=d3.scaleBand().range([0,width]).padding(0.1);
//y刻度将处理能耗值
var yScale=d3.scaleLinear().range([height,0]);
//定义X和Y轴
var yAxis=d3.axisLeft(yScale).ticks(5);
var xAxis=d3.axisBottom(xScale);
函数行转换器(数据){
返回{
国家:data.country,
年份:+data.year,
average:+data.average//+运算符将字符串解析为数字
};
}
//线路发生器功能
var line=d3.line()
.曲线(d3.曲线基)
.x(函数(d){return xScale(d.year);})
.y(函数(d){返回yScale(d.平均值);})
var data=d3.csvParse(d3.select(“pre”).remove().text())
data=data.map(行转换器);
var countries=d3.nest()
.key(函数(d){返回d.country;})
.条目(数据);
域([0,d3.max(数据,函数(d){返回d.average;})];
域(国家[0].values.map(函数(d){return d.year;}));
//画X轴
append(“g”)//添加新的svg组元素
.attr(“类”、“x轴”)
.attr(“变换”、“平移(0)”、“高度+”)
.呼叫(xAxis)
.selectAll(“文本”)
.attr(“dx”,“-.8em”)
.attr(“dy”,“.25em”)
.attr(“文本锚定”、“结束”);
//画雅克西斯
svg.append(“g”)
.attr(“类”、“y轴”)
.呼叫(yAxis)
.selectAll(“文本”)
.attr(“dx”,“-.8em”)
.attr(“dy”,“.25em”)
.attr(“文本锚定”、“结束”);
svg.selectAll(空)
.数据(国家)
.输入()
.append(“路径”)
.attr(“类”、“行”)
.attr(“d”,函数(d){
返回线(d值);
});
.line{
笔画宽度:2px;
填充:无;
笔画:黑色;
}
国家、年份、平均数
美国,1970年,51
美国,1971年,50
美国,1972年,54
美国,1973年,56
美国,1974年,53
美国,1975年,57
美国,1976年,60
巴西,1970年,23
巴西,1971年,25
巴西,1972年,24
巴西,1973年,21
巴西,1974年,25
巴西,1975年,26
巴西,1976年,24
哇!谢谢你,这真的很有帮助,现在正在画线(耶!!)但有趣的是,只有4条线被绘制出来,但实际上我有6个国家的数据。下面是现在的输出结果:。对此有什么想法吗?我非常感谢你的帮助是的,这是预期的行为。你使用selectAll(“路径”)
创建行,但轴中已经存在两条路径-因此前两个系列的数据绑定到这些行,其余的则被输入(enter创建一个元素,其中数据数组中的每个项都不存在一个元素)。您可以更改select all语句,使其创建一个空选择:selectAll(null)
或者由于您对行进行了分类并可能希望更新它们:selectAll(“.line”)
。我在上面的代码片段中选择了第一个选项(以及从HTML元素解析CSV所需的一些其他更改)