d3.js 具有不同颜色和符号的散点图 - 遇到的问题
d3.js scatterplot with different colors and symbols - issues encountered
我正在尝试创建一个包含数百个数据点的散点图,每个数据点具有大约 5 个不同的属性。
数据作为对象数组从 .csv 加载,每个对象如下所示:
{hour: "02",yval: "63",foo: "33", goo:"0", bar:"1"},
我想显示具有以下属性的散点图:
bar
的形状:
-圆圈表示 bar=0
的所有点,三角形向下表示 bar=1
的点(这是一个虚拟变量)。
foo
和 goo
的颜色:
- 所有点都以灰色开始。
goo
是分类值 [0,1,2],而 foo
是定量值,范围为 0-50。 foo 和 goo 是互斥的,所以只有一个有值。换句话说,对于每个数据点 foo=0
或 goo=0
.
- 带有
goo=1
的点应该是橙色的; goo=2
的点应该是红色的。
foo
应该映射到从浅蓝色到深蓝色的线性色标上,即d3.scale.linear().domain([0, 50]).range(["#87CEFF", "#0000FF"]);
我可以单独完成其中的每一项,但是一起定义所有内容给我带来了问题。
我的可重现数据代码在这里:http://jsfiddle.net/qy5ohw0x/3/
问题
- 符号我试过了
.append("svg:path")
.attr("d", d3.svg.symbol())
这没有用。我完全尝试了一种不同的方法,但这并没有正确映射值:
var series = svg.selectAll("g.series")
.data(dataSet, function(d, i) { return d.bar; })
.enter()
.append("svg:g")
series.selectAll("g.point")
.data(dataSet)
.enter()
.append("svg:path")
.attr("transform", function(d, i) { return "translate(" + d.hour + "," + d.yval + ")"; })
.attr("d", function(d,i, j) { return d3.svg.symbol().type(symbolType[j])(); })
.attr("r", 2);
- 对于
goo
颜色 (grey/orange/red),我手动将值映射到 3 种颜色:
先定义var colors = ["grey", "orange", "red"];
然后在绘制数据点链的同时
.style("fill", function (d) { return colors[d.type]; })
它单独工作,但不能使用不同的符号。
- 最后,我可以为
foo
链接第二种颜色 .attr 吗?如果可能的话,d3.scale.linear().domain([0, 50]).range(["#87CEFF", "#0000FF"]);
可能会起作用。
同样,jsfiddle 在这里:http://jsfiddle.net/qy5ohw0x/3/
谢谢!!
使用nvd3.js
就简单多了
function prepareData (data) {
return [{
key: 'Group 1',
values: data.map(function (item) {
item.shape = item.bar == "0" ? 'circle' : 'triangle-down';
item.x = Number(item.hour);
item.y = Number(item.yval);
item.size = 0.1;
item.disabled = Math.random() > 0.4;
return item;
})
}]
}
nv.addGraph(function() {
var chart = nv.models.scatterChart()
.showDistX(false)
.showDistY(true)
.showLegend(false)
//Axis settings
chart.xAxis.tickFormat(d3.format('3.0f'));
chart.yAxis.tickFormat(d3.format('3.0f'));
d3.select('#chart svg')
.datum(prepareData(dataSet))
.call(chart)
// A bit hacky but works
var fooscale = d3.scale.linear().domain([0, 50]).range(["#87CEFF", "#0000FF"]);
function colorer(d) {
if (d.goo == '1')
return 'orange';
else if (d.goo == '2')
return 'red';
else if (d.goo == '0')
return fooscale(d.foo);
return 'gray';
}
d3.selectAll('.nv-point')
.attr({
'stroke': colorer,
'fill': colorer
})
nv.utils.windowResize(chart.update);
return chart;
});
见https://jsfiddle.net/qy5ohw0x/4/
PS 不幸的是 Nvd3 缺少文档,所以使用它 github 而不是
只需在 function(d)
中为每个属性执行所有逻辑和比较。
首先设置一些助手:
// symbol generators
var symbolTypes = {
"triangleDown": d3.svg.symbol().type("triangle-down"),
"circle": d3.svg.symbol().type("circle")
};
// colors for foo
var fooColors = d3.scale
.linear()
.domain([0, 50])
.range(["#87CEFF", "#0000FF"]);
然后为每个符号附加一个路径:
svg.selectAll("path")
.data(dataSet)
.enter().append("path")
.attr("class", "dot")
// position it, can't use x/y on path, so translate it
.attr("transform", function(d) {
return "translate(" + (x(d.hour) + (Math.random() * 12 - 6)) + "," + y(d.yval) + ")";
})
// assign d from our symbols
.attr("d", function(d,i){
if (d.bar === "0") // circle if bar === 0
return symbolTypes.circle();
else
return symbolTypes.triangleDown();
})
// fill based on goo and foo
.style("fill", function(d,i){
if (d.goo !== "0"){
if (d.goo === "1")
return "red";
else
return "orange";
}else{
return fooColors(d.foo);
}
});
已更新 fiddle。
顺便说一句,对于这种情况,我实际上认为直接 d3
比 nvd3
更直观。
我正在尝试创建一个包含数百个数据点的散点图,每个数据点具有大约 5 个不同的属性。 数据作为对象数组从 .csv 加载,每个对象如下所示:
{hour: "02",yval: "63",foo: "33", goo:"0", bar:"1"},
我想显示具有以下属性的散点图:
bar
的形状:
-圆圈表示 bar=0
的所有点,三角形向下表示 bar=1
的点(这是一个虚拟变量)。
foo
和 goo
的颜色:
- 所有点都以灰色开始。
goo
是分类值 [0,1,2],而foo
是定量值,范围为 0-50。 foo 和 goo 是互斥的,所以只有一个有值。换句话说,对于每个数据点foo=0
或goo=0
. - 带有
goo=1
的点应该是橙色的;goo=2
的点应该是红色的。 foo
应该映射到从浅蓝色到深蓝色的线性色标上,即d3.scale.linear().domain([0, 50]).range(["#87CEFF", "#0000FF"]);
我可以单独完成其中的每一项,但是一起定义所有内容给我带来了问题。
我的可重现数据代码在这里:http://jsfiddle.net/qy5ohw0x/3/
问题
- 符号我试过了
.append("svg:path")
.attr("d", d3.svg.symbol())
这没有用。我完全尝试了一种不同的方法,但这并没有正确映射值:
var series = svg.selectAll("g.series")
.data(dataSet, function(d, i) { return d.bar; })
.enter()
.append("svg:g")
series.selectAll("g.point")
.data(dataSet)
.enter()
.append("svg:path")
.attr("transform", function(d, i) { return "translate(" + d.hour + "," + d.yval + ")"; })
.attr("d", function(d,i, j) { return d3.svg.symbol().type(symbolType[j])(); })
.attr("r", 2);
- 对于
goo
颜色 (grey/orange/red),我手动将值映射到 3 种颜色:
先定义var colors = ["grey", "orange", "red"];
然后在绘制数据点链的同时
.style("fill", function (d) { return colors[d.type]; })
它单独工作,但不能使用不同的符号。
- 最后,我可以为
foo
链接第二种颜色 .attr 吗?如果可能的话,d3.scale.linear().domain([0, 50]).range(["#87CEFF", "#0000FF"]);
可能会起作用。
同样,jsfiddle 在这里:http://jsfiddle.net/qy5ohw0x/3/
谢谢!!
使用nvd3.js
就简单多了function prepareData (data) {
return [{
key: 'Group 1',
values: data.map(function (item) {
item.shape = item.bar == "0" ? 'circle' : 'triangle-down';
item.x = Number(item.hour);
item.y = Number(item.yval);
item.size = 0.1;
item.disabled = Math.random() > 0.4;
return item;
})
}]
}
nv.addGraph(function() {
var chart = nv.models.scatterChart()
.showDistX(false)
.showDistY(true)
.showLegend(false)
//Axis settings
chart.xAxis.tickFormat(d3.format('3.0f'));
chart.yAxis.tickFormat(d3.format('3.0f'));
d3.select('#chart svg')
.datum(prepareData(dataSet))
.call(chart)
// A bit hacky but works
var fooscale = d3.scale.linear().domain([0, 50]).range(["#87CEFF", "#0000FF"]);
function colorer(d) {
if (d.goo == '1')
return 'orange';
else if (d.goo == '2')
return 'red';
else if (d.goo == '0')
return fooscale(d.foo);
return 'gray';
}
d3.selectAll('.nv-point')
.attr({
'stroke': colorer,
'fill': colorer
})
nv.utils.windowResize(chart.update);
return chart;
});
见https://jsfiddle.net/qy5ohw0x/4/
PS 不幸的是 Nvd3 缺少文档,所以使用它 github 而不是
只需在 function(d)
中为每个属性执行所有逻辑和比较。
首先设置一些助手:
// symbol generators
var symbolTypes = {
"triangleDown": d3.svg.symbol().type("triangle-down"),
"circle": d3.svg.symbol().type("circle")
};
// colors for foo
var fooColors = d3.scale
.linear()
.domain([0, 50])
.range(["#87CEFF", "#0000FF"]);
然后为每个符号附加一个路径:
svg.selectAll("path")
.data(dataSet)
.enter().append("path")
.attr("class", "dot")
// position it, can't use x/y on path, so translate it
.attr("transform", function(d) {
return "translate(" + (x(d.hour) + (Math.random() * 12 - 6)) + "," + y(d.yval) + ")";
})
// assign d from our symbols
.attr("d", function(d,i){
if (d.bar === "0") // circle if bar === 0
return symbolTypes.circle();
else
return symbolTypes.triangleDown();
})
// fill based on goo and foo
.style("fill", function(d,i){
if (d.goo !== "0"){
if (d.goo === "1")
return "red";
else
return "orange";
}else{
return fooColors(d.foo);
}
});
已更新 fiddle。
顺便说一句,对于这种情况,我实际上认为直接 d3
比 nvd3
更直观。