我是第一次进入D3并且试图创建一小部分条形图来想象一些关于食品消费的研究。在网上使用一些例子,我设法让区域图表工作得很好。但是条形图可以让我更好地理解数据。我觉得到目前为止我的代码已接近工作,但我显然遗漏了一些东西。任何提示或帮助都会很棒。
例如,这是我的.csv文件的片段:
group,date,totals
acid,1641,8438
bird,1641,12
cheese,1641,22
cured meat,1641,506
dried fish,1644,158
fresh fish,1644,1196
meat,1644,140
brined/pickled fish,1645,2844
salt,1645,4382
...
到目前为止的代码:
<script type="text/javascript">
var margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 500 - margin.right - margin.left,
height = 150 - margin.top - margin.bottom,
parse = d3.time.format("%Y").parse;
// scales
var x = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]);
// for the area charts example, an area generator
var area = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.totals); });
// for the area charts example, a line generator
var line = d3.svg.line()
.interpolate("monotone")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.totals); });
// load data
d3.csv("revised.csv", function(error, data) {
// nest values by group
var groups = d3.nest()
.key(function(d) { return d.group; })
.entries(data);
// parse dates and numbers, assume values are sorted by date
// compute the maximum totals per group
groups.forEach(function(s) {
s.values.forEach(function(d) { d.date = parse(d.date); d.totals = +d.totals; });
s.maxtotals = d3.max(s.values, function(d) { return d.totals; });
});
// compute the minimum and maximum date across groups
x.domain([
d3.min(groups, function(s) { return s.values[0].date; }),
d3.max(groups, function(s) { return s.values[s.values.length - 1].date; })
]);
y.domain([0, d3.max(data, function(d) { return d.totals; })]);
// add an SVG element for each group
var svg = d3.select("body").selectAll("g")
.data(groups)
.enter().append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// print x axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
// print y axis
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
// Trying here to render my bar charts.
// -----------------------------------
svg.selectAll(".bar")
.data(groups)
.enter().append("rect")
.attr("x", x)
.attr("y", function(d) { return d.maxtotals; })
.attr("width", width / groups.length)
.attr("height", function(d) { return d.maxtotals; });
// These are the area charts, that work. Commented out for now.
//svg.append("path")
// .attr("class", "area")
// .attr("d", function(d) { y.domain([0, d.maxtotals]); return area(d.values); });
//svg.append("path")
// .attr("class", "bar")
// .attr("d", function(d) { y.domain([0, d.maxtotals]); return line(d.values); });
// Add a small label for the group name.
svg.append("text")
.attr("x", width - 6)
.attr("y", height - 6)
.attr("text-anchor", "end")
.text(function(d) { return d.key; });
});
</script>
此时区域图表看起来像这样(上面的代码改变了这些外观,但它给了你一个想法):
任何指针?我在俯瞰什么?提前谢谢!
答案 0 :(得分:1)
对我而言,第一件事就是你没有在y
和d.maxtotals
属性中将"y"
比例应用于"height"
,也不是适当地缩放"width"
属性。由于您确定这些属性值的方式,它应该像将标度应用于您已经返回的值一样简单。请注意,将来这可能不会起作用。
另一个问题是,您可能并不意味着"y"
属性与您的数据完全相关。这是"height"
的工作。将它们"y"
属性设置为您为x轴提供的相同y坐标。
答案 1 :(得分:1)
感谢Elijah的一些惊人帮助,我们成功实现了这一目标。这是修订版:
<script type="text/javascript">
var margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 400 - margin.right - margin.left,
height = 150 - margin.top - margin.bottom,
parse = d3.time.format("%Y").parse;
// scales
var x = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([0, height]);
// load data
d3.csv("revised.csv", function(error, data) {
// nest values by group
var groups = d3.nest()
.key(function(d) { return d.group; })
.entries(data);
// parse dates and numbers, assume values are sorted by date
// compute the maximum totals per group
groups.forEach(function(s) {
s.values.forEach(function(d) { d.date = parse(d.date); d.totals = +d.totals; });
s.maxtotals = d3.max(s.values, function(d) { return d.totals; });
});
// compute the minimum and maximum date across groups
x.domain([
d3.min(groups, function(s) { return s.values[0].date; }),
d3.max(groups, function(s) { return s.values[s.values.length - 1].date; })
]);
y.domain([0, d3.max(data, function(d) { return d.totals; })]);
// add an SVG element for each group
var svg = d3.select("body").selectAll("g")
.data(groups)
.enter().append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.each(function(d) {
var g = d3.select(this);
g.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
y.domain([0, d3.max(d.values, function(r) { return r.totals; })]);
g.selectAll("rect.aevents")
.data(d.values)
.enter().append("rect")
.attr("height", function(p) {return y(p.totals)})
.attr("width", 5)
.attr("x", function(p, q) {return x(p.date)})
.attr("y", function(p) {return height - y(p.totals)})
.on("click", function(p) {console.log(p.date.year())})
// .attr("class", "bar")
})
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
// Add a small label for the group name.
svg.append("text")
.attr("x", width - 6)
.attr("y", height - 6)
.attr("text-anchor", "end")
.text(function(d) { return d.key; });
});
</script>
主要更改:.each()
函数作为g
元素添加到SVG,调用data.values
作为其数据。 y()
比例也已翻转(从0,h
到h,0
)。我的另一个疏忽是.each()
函数中包含d3.max()
函数,因此检查每个项目组的最大总数是针对单个组而不是所有组的整体。现在,我已经很好地渲染了显示每个食物组总量的条形图,而不是区域图。