D3.js - Updating Bar Chart Data with buttons - javascript

So I've been trying to get my d3.js bar chart to transition to different values when a button is pressed. Though, at the moment some elements seem to be adding, but extremely wide and all over the place, as well as the previous elements not being removed.
This is my code:
function updateData(time) {
timeValue = time;
// Get the data again
d3.tsv(timeValue + ".tsv", function(error, data) {
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
// Scale the range of the data again
x.domain(d3.extent(data, function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
//Selecting Data
var bars = svg.selectAll("rect")
.data(data);
//Removing
bars.exit().remove("rect");
//Changes
bars.enter().append('rect')
.attr("class", "bar")
bars.attr('x', function(d) { return x(d.letter); })
.attr('width', x.rangeBand())
.attr('y', function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); });
//var svg = d3.select("div.innerScreen2").transition();
});
Now I've looked at similar questions asked and tried to apply the solutions, but nothing seems to get removed or change :/ Maybe I have code in the wrong place? Any help would be much appreciated

There are two problems to solve in your question. The first issue is related to the update pattern that some elements are added and some not. Do you have an unique identifier in your data set? If yes, you can use a function within the update process:
// Join new data with old elements, if any.
var text = svg.selectAll("text")
.data(data, function(d) { return d.id; });
Source:http://bl.ocks.org/mbostock/3808234
The second issue is related to your x/y positions and may depend on your underlying data. An data excerpt or debugging information are required to solve this issue.

Related

d3.js: Rescale y axis of multiple svgs

I have multiple SVG created via d3.js, all containing simple line charts.
Their y.domain goes from 0 to the max value:
y.domain([0, d3.max(data, function (d) {
return d.value;
})]);
Now I want to rescale all of them. So I want to use
y.domain(d3.extent(data, function (d) {
return d.value;
}));
on all SVG charts by clicking one button.
I am pretty new to this. It would be awesome to get some advice, if this was understandable enough.

Data joins with d3.stack.layout()

I've created a plunk to demonstrate my problem.
The issue is that my .enter(),update(),exit() method is not working for my d3.chart.layout() visualization.
Instead, I get the classic "double post" problem. My keys are the same, however.
What I want to happen is for my d3 steam graph to update its data (such that the y values all go to 0, and the chart disappears). My data binding is coded normally:
var steam = svg.selectAll(".layer")
.data(layers, function(d){console.log(d); return d.key})
steam.enter().append("path")
steam.style("fill", function(d, i) { return z(i); }).style("opacity","0").transition().duration(400)
.style("opacity","1")
.attr("class", "layer")
.attr("d", function(d) { return area(d.values); })
steam.exit().transition().duration(500).remove()
What is happening/any ideas?
So I got it to work, though I'm still confused as to why it works this way. I needed to move the svg adding out of the update function and into the namespace (that was obvious).
But the update became this, with a transition() method. Can anyone help me understand where I went wrong?
test = svg.selectAll("path").data(layers, function(d){return d.key})
test.enter().append("path")
test.style("opacity",1).style("fill", function(d, i) { return z(i); })
.attr("class", "layer").transition()
.duration(2000)
.attr("d", function(d) { return area(d.values); });
test.exit().transition().duration(1500).style("opacity",0).remove();

Understanding Issues With CSV to Bubble Chart Using D3.js

So I've been picking up D3.js to visualize some data I have, and I need a bit of help understanding why certain things happen.
I took the code from this example on the D3 site, and modified it to read from a flat CSV rather than a flattened JSON file. Here's what it looks like:
d3.csv("top-brands.csv", function(csvData) {
var data = { name: "brand", children: csvData };
var node = svg.data([data]).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
node.append("title")
.text(function(d) { return d.brand; });
node.append("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return color(d.brand); });
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.brand; });
});
It seems to work quite well, in the sense that my bubbles all get drawn with the correct data, but there are two niggling issues that keep coming up:
It keeps drawing a large circle that encloses the other circles. It appears to be as large as the canvas allows (480px by 480px) but I have no idea how to make it go away. Is it because of how my data is processed?
If I try to do anything with "d.brand" in any way, it will tell me that d.brand is undefined. The example from the D3 site takes the title and gets the substring if the length is too long, but I can't seem to do that. Is it because of the way I'm pulling my data?
Appreciate any help! I can't really provide example CSVs because it's proprietary data, but it's just three columns: brand, count, and proportion, which is a string, an int, and a float (percentage) in that order. Dummy data would work just fine, I think.
Thanks SO!

enter() and exit() with D3 nested selections

I have a follow-up question to this question that I closed too hastily.
How/where would I put a .exit() or .transition() for the answers? In my original code, I'm saving the main chart in a variable (questions_chart), so I can say something like questions_chart.exit().remove(). However, if I put .exit().remove() after the .text() (last line in the code in Peter's answer), I get an error saying that object array has no method 'exit'
I have not tested this but will give it a shot...you would need to preserve the variable binding the data...like so:
var divs = d3.select("body").selectAll("div")
.data(data.questions);
divs
.enter().append("div") // this creates the question divs
.text(function(d) { return d.value; })
.selectAll("div")
.data(function(d) { return d.answers; })
.enter().append("div") // this creates the nested answer divs
.text(function(d) { return d.value; });
divs.exit().remove();
I am assuming you don't need to remove just the divs that are answers. Hope this helps.
UPDATE: giving it a shot at dealing with questions and answers...
var divs = d3.select("body").selectAll("div")
.data(data.questions);
var questionDivs = divs
.enter().append("div") // this creates the question divs
.text(function(d) { return d.value; });
divs.exit().remove();
var answerDivs = questionDivs
.selectAll("div")
.data(function(d) { return d.answers; });
answerDivs
.enter().append("div") // this creates the nested answer divs
.text(function(d) { return d.value; });
answerDivs.exit().remove();

d3 data constancy

This is a followup of this question on SO: D3 - issues on first transition after initialization.
I have studies and implemented the key functions as explained by Mike and Jason in their answers. I also found this blog post useful http://knowledgestockpile.blogspot.com/2012/01/understanding-selectall-data-enter.html
I have used a key like
.data(svg.chartData, function(d) { return d.idSeries;})
to map one-to-one data and index.
However, I do not get the expected result and data points swap on redraw. Please have a look at http://jsbin.com/avoced/8/edit, specifically to the following relevant functions:
Chart initialization:
svg.series = svg.selectAll(".series").data(svg.chartData, function(d) { return d.idSer;})
svg.series.enter().append("g").classed("series", true)
svg.rects = svg.series.selectAll("rect").data(Object, function(d) { return d.x;})
svg.rects.enter().append("rect")
Redraw:
svg.series = svg.selectAll(".series").data(svg.chartData, function(d) { return d.idSer;})
svg.series.enter().append("g").classed("series", true)
svg.series.exit().remove()
svg.rects = svg.series.selectAll("rect").data(Object, function(d) { return d.x;})
svg.rects.enter().append("rect")
svg.rects.exit().remove()
Scales:
x = d3.scale.ordinal()
.domain(svg.pointsNames, function(d) { return d;})
.rangeRoundBands([0,width], .1);
What am I missing here?
Many thanks

Categories