D3.js版本3 scale.ordinal()没有按照我想要的方式读取我的数据



我正在用d3.js v3构建一个点图直方图,我正试图根据我从csv文件中读取的一个变量对我的数据进行颜色编码(它是城市,有10个(。问题是当我在浏览器中运行它时,每个点都是相同的颜色。

有人知道发生了什么事吗?

这是我的代码快照:

var data = d3.csv('happy.csv', function(data) {
data.forEach(function(d) {
d["index"] = d["index"];
d["name"] = d["name"];
d["city"] = d["city];
...
})
var colorScheme = d3.scale.ordinal()
.domain(data, (function(d) {
return d.city
}))
.range(["#FFADAF", "#FFC980", "#D9D9D9", "#9DACCB", "#95D1A5", 
"#F586C6", "#BFDD81", "#F18489", "#80BCEC", "#FEFEA9"]);
...
var dots = groups.selectAll("circle")
.data(function(d) {
return d3.range(1, +d.index + 1)
})
.enter().append("circle")
.attr("class", "dot")
.attr("r", 7.5)
.attr("cy", function(d) {
return y(d)
})
.style("fill", function (d) { return colorScheme(d.city); } )
})

将数据数组中的每个项绑定到groups,然后使用该数据创建一个数据数组以绑定到子循环:

return d.range(1, +d.index + 1);

问题是d3.range只是为指定的范围生成一个数字数组。这个绑定的数据没有city属性,它只是一个数字:没有绑定到父group的原始数据的踪迹,作为绑定到子数据的一部分。因此,每次尝试按d.city为圆着色时,都会将undefined传递给比例,因为这是传递给比例的唯一值,所以所有圆都是相同的颜色。

相反,您可以使用d3.rangearray.map()将对象数组绑定到继承city属性的子对象:

return d3.range(1, +d.index + 1).map(function(c) {
return {city: d.city, index: c}
})

现在,我们将城市财产结转到了各个圈子:

var data = [
{index: 5, city: "A"},
{index: 4, city: "B"},
{index: 6, city: "C"}
];
var colorScheme = d3.scale.ordinal()
.domain(data, (function(d) {
return d.city
}))
.range(["#FFADAF", "#FFC980", "#D9D9D9", "#9DACCB", "#95D1A5", 
"#F586C6", "#BFDD81", "#F18489", "#80BCEC", "#FEFEA9"]);
var svg = d3.select("body").append("svg");
var groups = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform",function(d,i) {
return "translate("+[0,i*20]+")";
})
var dots = groups.selectAll("circle")
.data(function(d) {
return d3.range(1, +d.index + 1).map(function(c) {
return {city: d.city, index: c}
})
})
.enter().append("circle")
.attr("class", "dot")
.attr("r", 7.5)
.attr("cx", function(d,i) {
return i*20+10;
})
.attr("cy", function(d,i) {
return 60;
})
.style("fill", function (d) { return colorScheme(d.city); } )
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

或者,我们可以在为圆着色时使用d3.select(this.parentNode).datum()访问父数据:

.style("fill", function (d) { return    colorScheme(d3.select(this.parentNode).datum().city); } )

如下:

var data = [
{index: 5, city: "A"},
{index: 4, city: "B"},
{index: 6, city: "C"}
];
var colorScheme = d3.scale.ordinal()
.domain(data, (function(d) {
return d.city
}))
.range(["#FFADAF", "#FFC980", "#D9D9D9", "#9DACCB", "#95D1A5", 
"#F586C6", "#BFDD81", "#F18489", "#80BCEC", "#FEFEA9"]);
var svg = d3.select("body").append("svg");
var groups = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform",function(d,i) {
return "translate("+[0,i*20]+")";
})
var dots = groups.selectAll("circle")
.data(function(d) {
return d3.range(1, +d.index + 1)
})
.enter().append("circle")
.attr("class", "dot")
.attr("r", 7.5)
.attr("cx", function(d,i) {
return i*20+10;
})
.attr("cy", function(d,i) {
return 60;
})
.style("fill", function (d) { return colorScheme(d3.select(this.parentNode).datum().city); } )
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

或者,我们可以在父级应用填充,而完全跳过为子级应用填充:

var data = [
{index: 5, city: "A"},
{index: 4, city: "B"},
{index: 6, city: "C"}
];
var colorScheme = d3.scale.ordinal()
.domain(data, (function(d) {
return d.city
}))
.range(["#FFADAF", "#FFC980", "#D9D9D9", "#9DACCB", "#95D1A5", 
"#F586C6", "#BFDD81", "#F18489", "#80BCEC", "#FEFEA9"]);
var svg = d3.select("body").append("svg");
var groups = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform",function(d,i) {
return "translate("+[0,i*20]+")";
})
.attr("fill", function(d) { return colorScheme(d.city); })
var dots = groups.selectAll("circle")
.data(function(d) {
return d3.range(1, +d.index + 1)
})
.enter().append("circle")
.attr("class", "dot")
.attr("r", 7.5)
.attr("cx", function(d,i) {
return i*20+10;
})
.attr("cy", function(d,i) {
return 60;
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

最新更新