我有一个从CSV文件加载的两个系列。我想在x轴上按照其中一个的y值来订购这两个系列,但我的订单例程不起作用。有人知道如何订购这些系列吗?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Teste Template</title>
<script type="text/javascript" src="d3/d3.js"></script>
<style type="text/css">
div.bar {
display: inline-block;
width: 20px;
height: 75px; /* We'll override height later */
background-color: teal;
margin-right: 2px;
}
</style>
</head>
<body>
<p>Click to sort!!</p>
<script type="text/javascript">
var w = 800;
var h = 500;
var padding = 30;
//Define scale
var x = d3.scaleLinear().range([padding, w-padding*2]);
var y = d3.scaleLinear().range([h-padding, padding]);
var z = d3.scaleOrdinal(d3.schemeCategory10);
var xAxis = d3.axisBottom().scale(x).ticks(10);
var yAxis = d3.axisLeft().scale(y).ticks(5);
//Define Canvas
var svg = d3.select("body").append("svg")
.attr("width",w).attr("height", h)
//Define clipping path
svg.append("clipPath").attr("id", "chart-area").append("rect")
.attr("x", padding).attr("y", padding)
.attr("width", w - padding*3).attr("height", h - padding*2);
//Loading CSV
d3.csv("eval_silver_standard.csv", function(error, data){
if (error) throw error;
// Extract yn using key
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x"; })
.sort();
// Map data to cartesian tuple {x,y}
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +d.x, y: +d[series]};
});
});
// Compute domains
x.domain(d3.extent(d3.merge(series), function(d) {
return d.x; })).nice();
y.domain(d3.extent(d3.merge(series), function(d) {
return d.y; })).nice();
// X axis.
svg.append("g").attr("class", "axis").attr("transform",
"translate(0," + (h - padding) + ")").call(xAxis)
// Y axis.
svg.append("g").attr("class", "axis").attr("transform",
"translate(" + padding + ",0)").call(yAxis)
// Append circles
svg.selectAll(".series")
.data(series)
.enter().append("g")
.attr("class", "series")
.style("fill", function(d, i) { return z(i); })
.selectAll(".point")
.data(function(d) { return d; })
.enter().append("circle")
.attr("class", "point")
.attr("cx", function(d) { return x(d.x); })
.attr("cy", function(d) { return y(d.y); })
.attr("r", 4);
//On click, update order
d3.select("p").on("click", function() {
// Order circles
// Code goes here
});
});
</script>
</body>
</html>
CSV文件:
x,y1,y2
0,0.85337,0.10198
1,0,0.30274
2,0.85311,0.08623
3,0.82759,0.08711
4,0.89602,0.03472
5,0.8,0.16295
6,0,0.27028
7,0.76167,0.2155
8,0.75,0.08359
9,0.81775,0.16535
10,0,0.2311
我的排序功能没有运行,我不知道为什么呢
答案 0 :(得分:0)
嗯,如果您有一个用于在x轴上定位圆的点刻度,这可能会更容易。由于你有线性刻度,我写的函数有一些繁琐的部分......
首先要做的事情是:您必须创建一个重新绘制SVG中元素的函数。在下面的演示中,它名为draw
,我们将series
数组传递给该函数。
然而,最重要的部分是对series
数组进行排序。例如,这是对蓝点进行分类并相应地重新排列橙色点的功能:
d3.select("#button1").on("click", function() {
series[0] = series[0].sort(function(a, b) {
return d3.ascending(a.y, b.y)
}).map(function(e, i) {
return {
x: i,
fx: e.fx,
y: e.y,
u: e.u
}
});
series[1].forEach(function(d, i, arr) {
d.x = order0.indexOf(d.fx)
});
draw(series);
});
正如您所看到的,单独排序不会起作用,因为x
属性将被排序在一起。因此,我们必须根据y
进行排序,然后将x
从0重新分配到10。
为了保持对象的持久性,我使用u
创建了一个名为Math.random()
的属性。两个属性具有相同值的可能性很小。但是,我建议您在每个对象中创建自己的唯一属性(否则您无法保持对象的持久性)。 fx
属性只是为了跟踪原始序列,order0
/ order1
是具有每个序列的有序序列的数组。
以下是演示,使用大部分代码但创建draw
并缩小SVG大小,以便更好地适应Stack片段。单击按钮进行排序:
var data = d3.csvParse(d3.select("#csv").text());
var w = 600;
var h = 200;
var padding = 30;
//Define scale
var x = d3.scaleLinear().range([padding, w - padding * 2]);
var y = d3.scaleLinear().range([h - padding, padding]);
var z = d3.scaleOrdinal(d3.schemeCategory10);
var xAxis = d3.axisBottom().scale(x).ticks(10);
var yAxis = d3.axisLeft().scale(y).ticks(5);
//Define Canvas
var svg = d3.select("body").append("svg")
.attr("width", w).attr("height", h)
//Define clipping path
svg.append("clipPath").attr("id", "chart-area").append("rect")
.attr("x", padding).attr("y", padding)
.attr("width", w - padding * 3).attr("height", h - padding * 2);
// Extract yn using key
var seriesNames = d3.keys(data[0])
.filter(function(d) {
return d !== "x";
})
.sort();
// Map data to cartesian tuple {x,y}
var series = seriesNames.map(function(series) {
return data.map(function(d, i) {
return {
x: +d.x,
fx: +d.x,
y: +d[series],
u: Math.random()
};
});
});
var order0 = series[0].sort(function(a, b) {
return d3.ascending(a.y, b.y)
}).map(function(e) {
return e.x
});
var order1 = series[1].sort(function(a, b) {
return d3.ascending(a.y, b.y)
}).map(function(e) {
return e.x
});
// Compute domains
x.domain(d3.extent(d3.merge(series), function(d) {
return d.x;
})).nice();
y.domain(d3.extent(d3.merge(series), function(d) {
return d.y;
})).nice();
// X axis.
svg.append("g").attr("class", "axis").attr("transform",
"translate(0," + (h - padding) + ")").call(xAxis)
// Y axis.
svg.append("g").attr("class", "axis").attr("transform",
"translate(" + padding + ",0)").call(yAxis);
draw(series);
function draw(data) {
// Append circles
var groups = svg.selectAll(".series")
.data(data);
var groupsEnter = groups.enter()
.append("g")
.attr("class", "series")
.style("fill", function(d, i) {
return z(i);
});
var circlesEnter = groupsEnter.selectAll(".point")
.data(function(d) {
return d;
}, function(e) {
return e.u
}).enter().append("circle")
.attr("class", "point")
.attr("cx", function(d) {
return x(d.x);
})
.attr("cy", function(d) {
return y(d.y);
})
.attr("r", 4);
groups.selectAll(".point").data(function(d) {
return d;
}, function(e) {
return e.u
})
.transition()
.duration(2500)
.attr("cx", function(d) {
return x(d.x);
})
.attr("cy", function(d) {
return y(d.y);
})
.attr("r", 4);
}
//On click, update order
d3.select("#button1").on("click", function() {
series[0] = series[0].sort(function(a, b) {
return d3.ascending(a.y, b.y)
}).map(function(e, i) {
return {
x: i,
fx: e.fx,
y: e.y,
u: e.u
}
});
series[1].forEach(function(d, i, arr) {
d.x = order0.indexOf(d.fx)
});
draw(series);
});
d3.select("#button2").on("click", function() {
series[1] = series[1].sort(function(a, b) {
return d3.ascending(a.y, b.y)
}).map(function(e, i) {
return {
x: i,
fx: e.fx,
y: e.y,
u: e.u
}
});
series[0].forEach(function(d, i, arr) {
d.x = order1.indexOf(d.fx)
});
draw(series);
});
&#13;
pre {
display: none;
}
button {
margin-right: 5px;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<button id="button1">Click to sort by Blue</button><button id="button2">Click to sort by Orange</button>
<pre id="csv">x,y1,y2
0,0.85337,0.10198
1,0,0.30274
2,0.85311,0.08623
3,0.82759,0.08711
4,0.89602,0.03472
5,0.8,0.16295
6,0,0.27028
7,0.76167,0.2155
8,0.75,0.08359
9,0.81775,0.16535
10,0,0.2311</pre>
&#13;