D3 exit() not functioning as expected in grouped bar chart












1















I'm having trouble understanding how the exit() selection works in my grouped bar chart. My example has only empty exit() selections, and thus nothing is removed from the chart when it's updated.



This is similar to the problem posted here: d3 grouped bar chart update pattern not working. But since I append an 'g' to the chartArea object I don't think the solution is applicable.



I am loosely following the grouped/stacked bar chart example from here: https://bl.ocks.org/aholachek/fb0c1cd7ea9707bc8ff55a82402c54b1



The full jsfiddle https://jsfiddle.net/fg_ti/ka306sjc/68/ and the code:



var data1 = [
{
"sex": "female",
"n_patients": 5,
"grouping":"A"
},
{
"sex": "male",
"n_patients": 10,
"grouping": "A"
},
{
"sex": "female",
"n_patients": 25,
"grouping":"B"
},
{
"sex": "male",
"n_patients": 10,
"grouping":"B"
}];
var data2 = [
{
"sex": "female",
"n_patients": 62,
"grouping":"A"
},
{
"sex": "male",
"n_patients": 55,
"grouping":"A"
},
{
"sex": "female",
"n_patients": 25,
"grouping": "B"
},
{
"sex": "male",
"n_patients": 83,
"grouping":"B"
},
{
"sex": "female",
"n_patients": 25,
"grouping": "D"},
{
"sex": "male",
"n_patients": 83,
"grouping": "D"
}];

width = 350;
height = 450;

var initData = d3.nest().key(d => d.grouping).entries(data1)
var margin = ({top:10, right:10, bottom:10, left:30});
var Gwidth = width - margin.left - margin.right
var Gheight = height - margin.top - margin.bottom
var barPadding = 0.1;

var colors = ['#ffe1e1', '#d1ecfd']
svg = d3.select('body').append('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var topG = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top +')')


// Initial scale

// Scale between the keys (i.e. b/w age groups, edu, etc`)
var scaleX = d3.scaleBand()
.domain(initData.map(d => d.key))
.range([0, Gwidth])
.padding(barPadding);

var scaleColors = d3.scaleOrdinal()
.range(colors)

// Initial axis
var yAxis = topG.append('g')
.attr("class", "y axis")

var xAxis = topG.append('g')
.attr("class", "x axis")

xAxis.call(d3.axisBottom(scaleX))
.attr("transform", 'translate(' + 0 + "," + Gheight + ')');

var chartArea = topG.append("g")
.attr("class", "chartArea");



// UPDATE FUNCTION - will be called by r2d3.onRender()
function update(inData) {

// Reshape data
var newData = d3.nest()
.key(d => d.grouping)
.entries(inData);


var maxY = d3.max(newData, d => d3.max(d.values, k => k.n_patients));
grouping1Names = newData.map(d => d.key);
grouping2Names = newData[0].values.map(d => d.sex);
var t = 1000;

// Scales used in updates
var scaleY = d3.scaleLinear()
.domain([0, maxY])
.range([Gheight, 0]);

var scaleX = d3.scaleBand()
.domain(grouping1Names)
.range([0, Gwidth])
.padding(barPadding);

var scaleX1 = d3.scaleBand()
.domain(grouping2Names)
.rangeRound([0, scaleX.bandwidth()]);


// Perform the data join

var barGroupWithData = chartArea
.selectAll('.barGroup')
.data(newData);

barGroupWithData.exit().remove();

// Join rect elements with data - specified with keys
var bars = barGroupWithData.enter()
.append("g")
.attr("transform", d => "translate(" + scaleX(d.key) + ",0)")
.attr("fill", "steelblue")
.merge(barGroupWithData)
.selectAll("rect")
.data(d => Object.keys(d.values)
.map(k => ({ keyL2: grouping2Names[k], value: d.values[k].n_patients }) ));



console.log(bars)

// Remove rect elements joined with data that is no longer present
bars.exit().remove()

bars.enter()
.append("rect")
.attr("fill", d => scaleColors(d.keyL2))
.attr("y", d => scaleY(0))
.merge(bars)
.attr("x", (d) => scaleX1(d.keyL2))
.attr("width", scaleX1.bandwidth())
.transition()
.duration(t)
.ease(d3.easeLinear)
.attr('y', d => scaleY(d.value))
.attr("height", d => scaleY(0) - scaleY(d.value));

console.log(bars)

// Udpate axes
yAxis.transition()
.duration(t)
.call(d3.axisLeft(scaleY))

xAxis.transition()
.duration(t)
.call(d3.axisBottom(scaleX))

}

//


update(data1);

// Update the data
setInterval(function (newDat) {

if(Math.random()>0.5) {
d = data1
} else {
d = data2
}


return update(d);
}, 3000);


I suspect I am not joining the data correctly, but cannot pinpoint where this goes wrong. The first posted answer to this questions seems close, but does not work for my solution: Exit() is not working for d3 group bar chart.



Any advice to properly removing the old data from the chart?



==================== EDIT =============



To clarify, I modified the data to highlight the problem better (updated jsfidlde). The data seems to join to the rect elements fine - with each update, new bars are appended. However the old rect elements are not removed.
Since the keys for joining data to the rects are specified as such:



(.data(d => Object.keys(d.values)
.map(k => ({ keyL2: grouping2Names[k], value: d.values[k].n_patients }) ));` `.enter()`


I therefore expected the .data() to match the incoming data against the data in the existing rect elements. If incoming data has different values for n_patients or grouping, I would think d3 would recognize the new data as "entering" and append, and conversely, already existing data whose n_patient or grouping values are not matched with the new data as "exiting" and remove. This is based on the responses to this question: D3 Key Function; and an old blog post from Mike Bostock



Since new rects are appended in each .enter() call, it seems d3 is recognizing the "entering" data, but not recognizing the "exiting" data in the way I have written my code. Can anyone shed light on this?










share|improve this question




















  • 1





    Both your data sets have the same number of entries for each groups, so the bars/scale will just transition to the new domain but bars won't be added or removed.

    – pmkro
    Nov 20 '18 at 15:34











  • have a look at your svg DOM with DevTools. There is something wrong in your code. Or is the chart animating what you want?

    – rioV8
    Nov 20 '18 at 16:06











  • @pmkro thanks, I edited the post to better highlight the issue. Since the data join is keyed (i.e. not keyed on index), even if the number of elements are the same, changes should be entered and exited, right?

    – rove
    Nov 21 '18 at 8:49











  • @rioV8, thanks, from examining the svg I can see new elements are joined and append, but none are removed. The new jsfiddle better highlights the issue

    – rove
    Nov 21 '18 at 8:52











  • read the docs (d3-select) about select(All) and the Data join

    – rioV8
    Nov 21 '18 at 10:40
















1















I'm having trouble understanding how the exit() selection works in my grouped bar chart. My example has only empty exit() selections, and thus nothing is removed from the chart when it's updated.



This is similar to the problem posted here: d3 grouped bar chart update pattern not working. But since I append an 'g' to the chartArea object I don't think the solution is applicable.



I am loosely following the grouped/stacked bar chart example from here: https://bl.ocks.org/aholachek/fb0c1cd7ea9707bc8ff55a82402c54b1



The full jsfiddle https://jsfiddle.net/fg_ti/ka306sjc/68/ and the code:



var data1 = [
{
"sex": "female",
"n_patients": 5,
"grouping":"A"
},
{
"sex": "male",
"n_patients": 10,
"grouping": "A"
},
{
"sex": "female",
"n_patients": 25,
"grouping":"B"
},
{
"sex": "male",
"n_patients": 10,
"grouping":"B"
}];
var data2 = [
{
"sex": "female",
"n_patients": 62,
"grouping":"A"
},
{
"sex": "male",
"n_patients": 55,
"grouping":"A"
},
{
"sex": "female",
"n_patients": 25,
"grouping": "B"
},
{
"sex": "male",
"n_patients": 83,
"grouping":"B"
},
{
"sex": "female",
"n_patients": 25,
"grouping": "D"},
{
"sex": "male",
"n_patients": 83,
"grouping": "D"
}];

width = 350;
height = 450;

var initData = d3.nest().key(d => d.grouping).entries(data1)
var margin = ({top:10, right:10, bottom:10, left:30});
var Gwidth = width - margin.left - margin.right
var Gheight = height - margin.top - margin.bottom
var barPadding = 0.1;

var colors = ['#ffe1e1', '#d1ecfd']
svg = d3.select('body').append('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var topG = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top +')')


// Initial scale

// Scale between the keys (i.e. b/w age groups, edu, etc`)
var scaleX = d3.scaleBand()
.domain(initData.map(d => d.key))
.range([0, Gwidth])
.padding(barPadding);

var scaleColors = d3.scaleOrdinal()
.range(colors)

// Initial axis
var yAxis = topG.append('g')
.attr("class", "y axis")

var xAxis = topG.append('g')
.attr("class", "x axis")

xAxis.call(d3.axisBottom(scaleX))
.attr("transform", 'translate(' + 0 + "," + Gheight + ')');

var chartArea = topG.append("g")
.attr("class", "chartArea");



// UPDATE FUNCTION - will be called by r2d3.onRender()
function update(inData) {

// Reshape data
var newData = d3.nest()
.key(d => d.grouping)
.entries(inData);


var maxY = d3.max(newData, d => d3.max(d.values, k => k.n_patients));
grouping1Names = newData.map(d => d.key);
grouping2Names = newData[0].values.map(d => d.sex);
var t = 1000;

// Scales used in updates
var scaleY = d3.scaleLinear()
.domain([0, maxY])
.range([Gheight, 0]);

var scaleX = d3.scaleBand()
.domain(grouping1Names)
.range([0, Gwidth])
.padding(barPadding);

var scaleX1 = d3.scaleBand()
.domain(grouping2Names)
.rangeRound([0, scaleX.bandwidth()]);


// Perform the data join

var barGroupWithData = chartArea
.selectAll('.barGroup')
.data(newData);

barGroupWithData.exit().remove();

// Join rect elements with data - specified with keys
var bars = barGroupWithData.enter()
.append("g")
.attr("transform", d => "translate(" + scaleX(d.key) + ",0)")
.attr("fill", "steelblue")
.merge(barGroupWithData)
.selectAll("rect")
.data(d => Object.keys(d.values)
.map(k => ({ keyL2: grouping2Names[k], value: d.values[k].n_patients }) ));



console.log(bars)

// Remove rect elements joined with data that is no longer present
bars.exit().remove()

bars.enter()
.append("rect")
.attr("fill", d => scaleColors(d.keyL2))
.attr("y", d => scaleY(0))
.merge(bars)
.attr("x", (d) => scaleX1(d.keyL2))
.attr("width", scaleX1.bandwidth())
.transition()
.duration(t)
.ease(d3.easeLinear)
.attr('y', d => scaleY(d.value))
.attr("height", d => scaleY(0) - scaleY(d.value));

console.log(bars)

// Udpate axes
yAxis.transition()
.duration(t)
.call(d3.axisLeft(scaleY))

xAxis.transition()
.duration(t)
.call(d3.axisBottom(scaleX))

}

//


update(data1);

// Update the data
setInterval(function (newDat) {

if(Math.random()>0.5) {
d = data1
} else {
d = data2
}


return update(d);
}, 3000);


I suspect I am not joining the data correctly, but cannot pinpoint where this goes wrong. The first posted answer to this questions seems close, but does not work for my solution: Exit() is not working for d3 group bar chart.



Any advice to properly removing the old data from the chart?



==================== EDIT =============



To clarify, I modified the data to highlight the problem better (updated jsfidlde). The data seems to join to the rect elements fine - with each update, new bars are appended. However the old rect elements are not removed.
Since the keys for joining data to the rects are specified as such:



(.data(d => Object.keys(d.values)
.map(k => ({ keyL2: grouping2Names[k], value: d.values[k].n_patients }) ));` `.enter()`


I therefore expected the .data() to match the incoming data against the data in the existing rect elements. If incoming data has different values for n_patients or grouping, I would think d3 would recognize the new data as "entering" and append, and conversely, already existing data whose n_patient or grouping values are not matched with the new data as "exiting" and remove. This is based on the responses to this question: D3 Key Function; and an old blog post from Mike Bostock



Since new rects are appended in each .enter() call, it seems d3 is recognizing the "entering" data, but not recognizing the "exiting" data in the way I have written my code. Can anyone shed light on this?










share|improve this question




















  • 1





    Both your data sets have the same number of entries for each groups, so the bars/scale will just transition to the new domain but bars won't be added or removed.

    – pmkro
    Nov 20 '18 at 15:34











  • have a look at your svg DOM with DevTools. There is something wrong in your code. Or is the chart animating what you want?

    – rioV8
    Nov 20 '18 at 16:06











  • @pmkro thanks, I edited the post to better highlight the issue. Since the data join is keyed (i.e. not keyed on index), even if the number of elements are the same, changes should be entered and exited, right?

    – rove
    Nov 21 '18 at 8:49











  • @rioV8, thanks, from examining the svg I can see new elements are joined and append, but none are removed. The new jsfiddle better highlights the issue

    – rove
    Nov 21 '18 at 8:52











  • read the docs (d3-select) about select(All) and the Data join

    – rioV8
    Nov 21 '18 at 10:40














1












1








1








I'm having trouble understanding how the exit() selection works in my grouped bar chart. My example has only empty exit() selections, and thus nothing is removed from the chart when it's updated.



This is similar to the problem posted here: d3 grouped bar chart update pattern not working. But since I append an 'g' to the chartArea object I don't think the solution is applicable.



I am loosely following the grouped/stacked bar chart example from here: https://bl.ocks.org/aholachek/fb0c1cd7ea9707bc8ff55a82402c54b1



The full jsfiddle https://jsfiddle.net/fg_ti/ka306sjc/68/ and the code:



var data1 = [
{
"sex": "female",
"n_patients": 5,
"grouping":"A"
},
{
"sex": "male",
"n_patients": 10,
"grouping": "A"
},
{
"sex": "female",
"n_patients": 25,
"grouping":"B"
},
{
"sex": "male",
"n_patients": 10,
"grouping":"B"
}];
var data2 = [
{
"sex": "female",
"n_patients": 62,
"grouping":"A"
},
{
"sex": "male",
"n_patients": 55,
"grouping":"A"
},
{
"sex": "female",
"n_patients": 25,
"grouping": "B"
},
{
"sex": "male",
"n_patients": 83,
"grouping":"B"
},
{
"sex": "female",
"n_patients": 25,
"grouping": "D"},
{
"sex": "male",
"n_patients": 83,
"grouping": "D"
}];

width = 350;
height = 450;

var initData = d3.nest().key(d => d.grouping).entries(data1)
var margin = ({top:10, right:10, bottom:10, left:30});
var Gwidth = width - margin.left - margin.right
var Gheight = height - margin.top - margin.bottom
var barPadding = 0.1;

var colors = ['#ffe1e1', '#d1ecfd']
svg = d3.select('body').append('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var topG = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top +')')


// Initial scale

// Scale between the keys (i.e. b/w age groups, edu, etc`)
var scaleX = d3.scaleBand()
.domain(initData.map(d => d.key))
.range([0, Gwidth])
.padding(barPadding);

var scaleColors = d3.scaleOrdinal()
.range(colors)

// Initial axis
var yAxis = topG.append('g')
.attr("class", "y axis")

var xAxis = topG.append('g')
.attr("class", "x axis")

xAxis.call(d3.axisBottom(scaleX))
.attr("transform", 'translate(' + 0 + "," + Gheight + ')');

var chartArea = topG.append("g")
.attr("class", "chartArea");



// UPDATE FUNCTION - will be called by r2d3.onRender()
function update(inData) {

// Reshape data
var newData = d3.nest()
.key(d => d.grouping)
.entries(inData);


var maxY = d3.max(newData, d => d3.max(d.values, k => k.n_patients));
grouping1Names = newData.map(d => d.key);
grouping2Names = newData[0].values.map(d => d.sex);
var t = 1000;

// Scales used in updates
var scaleY = d3.scaleLinear()
.domain([0, maxY])
.range([Gheight, 0]);

var scaleX = d3.scaleBand()
.domain(grouping1Names)
.range([0, Gwidth])
.padding(barPadding);

var scaleX1 = d3.scaleBand()
.domain(grouping2Names)
.rangeRound([0, scaleX.bandwidth()]);


// Perform the data join

var barGroupWithData = chartArea
.selectAll('.barGroup')
.data(newData);

barGroupWithData.exit().remove();

// Join rect elements with data - specified with keys
var bars = barGroupWithData.enter()
.append("g")
.attr("transform", d => "translate(" + scaleX(d.key) + ",0)")
.attr("fill", "steelblue")
.merge(barGroupWithData)
.selectAll("rect")
.data(d => Object.keys(d.values)
.map(k => ({ keyL2: grouping2Names[k], value: d.values[k].n_patients }) ));



console.log(bars)

// Remove rect elements joined with data that is no longer present
bars.exit().remove()

bars.enter()
.append("rect")
.attr("fill", d => scaleColors(d.keyL2))
.attr("y", d => scaleY(0))
.merge(bars)
.attr("x", (d) => scaleX1(d.keyL2))
.attr("width", scaleX1.bandwidth())
.transition()
.duration(t)
.ease(d3.easeLinear)
.attr('y', d => scaleY(d.value))
.attr("height", d => scaleY(0) - scaleY(d.value));

console.log(bars)

// Udpate axes
yAxis.transition()
.duration(t)
.call(d3.axisLeft(scaleY))

xAxis.transition()
.duration(t)
.call(d3.axisBottom(scaleX))

}

//


update(data1);

// Update the data
setInterval(function (newDat) {

if(Math.random()>0.5) {
d = data1
} else {
d = data2
}


return update(d);
}, 3000);


I suspect I am not joining the data correctly, but cannot pinpoint where this goes wrong. The first posted answer to this questions seems close, but does not work for my solution: Exit() is not working for d3 group bar chart.



Any advice to properly removing the old data from the chart?



==================== EDIT =============



To clarify, I modified the data to highlight the problem better (updated jsfidlde). The data seems to join to the rect elements fine - with each update, new bars are appended. However the old rect elements are not removed.
Since the keys for joining data to the rects are specified as such:



(.data(d => Object.keys(d.values)
.map(k => ({ keyL2: grouping2Names[k], value: d.values[k].n_patients }) ));` `.enter()`


I therefore expected the .data() to match the incoming data against the data in the existing rect elements. If incoming data has different values for n_patients or grouping, I would think d3 would recognize the new data as "entering" and append, and conversely, already existing data whose n_patient or grouping values are not matched with the new data as "exiting" and remove. This is based on the responses to this question: D3 Key Function; and an old blog post from Mike Bostock



Since new rects are appended in each .enter() call, it seems d3 is recognizing the "entering" data, but not recognizing the "exiting" data in the way I have written my code. Can anyone shed light on this?










share|improve this question
















I'm having trouble understanding how the exit() selection works in my grouped bar chart. My example has only empty exit() selections, and thus nothing is removed from the chart when it's updated.



This is similar to the problem posted here: d3 grouped bar chart update pattern not working. But since I append an 'g' to the chartArea object I don't think the solution is applicable.



I am loosely following the grouped/stacked bar chart example from here: https://bl.ocks.org/aholachek/fb0c1cd7ea9707bc8ff55a82402c54b1



The full jsfiddle https://jsfiddle.net/fg_ti/ka306sjc/68/ and the code:



var data1 = [
{
"sex": "female",
"n_patients": 5,
"grouping":"A"
},
{
"sex": "male",
"n_patients": 10,
"grouping": "A"
},
{
"sex": "female",
"n_patients": 25,
"grouping":"B"
},
{
"sex": "male",
"n_patients": 10,
"grouping":"B"
}];
var data2 = [
{
"sex": "female",
"n_patients": 62,
"grouping":"A"
},
{
"sex": "male",
"n_patients": 55,
"grouping":"A"
},
{
"sex": "female",
"n_patients": 25,
"grouping": "B"
},
{
"sex": "male",
"n_patients": 83,
"grouping":"B"
},
{
"sex": "female",
"n_patients": 25,
"grouping": "D"},
{
"sex": "male",
"n_patients": 83,
"grouping": "D"
}];

width = 350;
height = 450;

var initData = d3.nest().key(d => d.grouping).entries(data1)
var margin = ({top:10, right:10, bottom:10, left:30});
var Gwidth = width - margin.left - margin.right
var Gheight = height - margin.top - margin.bottom
var barPadding = 0.1;

var colors = ['#ffe1e1', '#d1ecfd']
svg = d3.select('body').append('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var topG = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top +')')


// Initial scale

// Scale between the keys (i.e. b/w age groups, edu, etc`)
var scaleX = d3.scaleBand()
.domain(initData.map(d => d.key))
.range([0, Gwidth])
.padding(barPadding);

var scaleColors = d3.scaleOrdinal()
.range(colors)

// Initial axis
var yAxis = topG.append('g')
.attr("class", "y axis")

var xAxis = topG.append('g')
.attr("class", "x axis")

xAxis.call(d3.axisBottom(scaleX))
.attr("transform", 'translate(' + 0 + "," + Gheight + ')');

var chartArea = topG.append("g")
.attr("class", "chartArea");



// UPDATE FUNCTION - will be called by r2d3.onRender()
function update(inData) {

// Reshape data
var newData = d3.nest()
.key(d => d.grouping)
.entries(inData);


var maxY = d3.max(newData, d => d3.max(d.values, k => k.n_patients));
grouping1Names = newData.map(d => d.key);
grouping2Names = newData[0].values.map(d => d.sex);
var t = 1000;

// Scales used in updates
var scaleY = d3.scaleLinear()
.domain([0, maxY])
.range([Gheight, 0]);

var scaleX = d3.scaleBand()
.domain(grouping1Names)
.range([0, Gwidth])
.padding(barPadding);

var scaleX1 = d3.scaleBand()
.domain(grouping2Names)
.rangeRound([0, scaleX.bandwidth()]);


// Perform the data join

var barGroupWithData = chartArea
.selectAll('.barGroup')
.data(newData);

barGroupWithData.exit().remove();

// Join rect elements with data - specified with keys
var bars = barGroupWithData.enter()
.append("g")
.attr("transform", d => "translate(" + scaleX(d.key) + ",0)")
.attr("fill", "steelblue")
.merge(barGroupWithData)
.selectAll("rect")
.data(d => Object.keys(d.values)
.map(k => ({ keyL2: grouping2Names[k], value: d.values[k].n_patients }) ));



console.log(bars)

// Remove rect elements joined with data that is no longer present
bars.exit().remove()

bars.enter()
.append("rect")
.attr("fill", d => scaleColors(d.keyL2))
.attr("y", d => scaleY(0))
.merge(bars)
.attr("x", (d) => scaleX1(d.keyL2))
.attr("width", scaleX1.bandwidth())
.transition()
.duration(t)
.ease(d3.easeLinear)
.attr('y', d => scaleY(d.value))
.attr("height", d => scaleY(0) - scaleY(d.value));

console.log(bars)

// Udpate axes
yAxis.transition()
.duration(t)
.call(d3.axisLeft(scaleY))

xAxis.transition()
.duration(t)
.call(d3.axisBottom(scaleX))

}

//


update(data1);

// Update the data
setInterval(function (newDat) {

if(Math.random()>0.5) {
d = data1
} else {
d = data2
}


return update(d);
}, 3000);


I suspect I am not joining the data correctly, but cannot pinpoint where this goes wrong. The first posted answer to this questions seems close, but does not work for my solution: Exit() is not working for d3 group bar chart.



Any advice to properly removing the old data from the chart?



==================== EDIT =============



To clarify, I modified the data to highlight the problem better (updated jsfidlde). The data seems to join to the rect elements fine - with each update, new bars are appended. However the old rect elements are not removed.
Since the keys for joining data to the rects are specified as such:



(.data(d => Object.keys(d.values)
.map(k => ({ keyL2: grouping2Names[k], value: d.values[k].n_patients }) ));` `.enter()`


I therefore expected the .data() to match the incoming data against the data in the existing rect elements. If incoming data has different values for n_patients or grouping, I would think d3 would recognize the new data as "entering" and append, and conversely, already existing data whose n_patient or grouping values are not matched with the new data as "exiting" and remove. This is based on the responses to this question: D3 Key Function; and an old blog post from Mike Bostock



Since new rects are appended in each .enter() call, it seems d3 is recognizing the "entering" data, but not recognizing the "exiting" data in the way I have written my code. Can anyone shed light on this?







javascript d3.js






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 9:02







rove

















asked Nov 20 '18 at 15:31









roverove

415




415








  • 1





    Both your data sets have the same number of entries for each groups, so the bars/scale will just transition to the new domain but bars won't be added or removed.

    – pmkro
    Nov 20 '18 at 15:34











  • have a look at your svg DOM with DevTools. There is something wrong in your code. Or is the chart animating what you want?

    – rioV8
    Nov 20 '18 at 16:06











  • @pmkro thanks, I edited the post to better highlight the issue. Since the data join is keyed (i.e. not keyed on index), even if the number of elements are the same, changes should be entered and exited, right?

    – rove
    Nov 21 '18 at 8:49











  • @rioV8, thanks, from examining the svg I can see new elements are joined and append, but none are removed. The new jsfiddle better highlights the issue

    – rove
    Nov 21 '18 at 8:52











  • read the docs (d3-select) about select(All) and the Data join

    – rioV8
    Nov 21 '18 at 10:40














  • 1





    Both your data sets have the same number of entries for each groups, so the bars/scale will just transition to the new domain but bars won't be added or removed.

    – pmkro
    Nov 20 '18 at 15:34











  • have a look at your svg DOM with DevTools. There is something wrong in your code. Or is the chart animating what you want?

    – rioV8
    Nov 20 '18 at 16:06











  • @pmkro thanks, I edited the post to better highlight the issue. Since the data join is keyed (i.e. not keyed on index), even if the number of elements are the same, changes should be entered and exited, right?

    – rove
    Nov 21 '18 at 8:49











  • @rioV8, thanks, from examining the svg I can see new elements are joined and append, but none are removed. The new jsfiddle better highlights the issue

    – rove
    Nov 21 '18 at 8:52











  • read the docs (d3-select) about select(All) and the Data join

    – rioV8
    Nov 21 '18 at 10:40








1




1





Both your data sets have the same number of entries for each groups, so the bars/scale will just transition to the new domain but bars won't be added or removed.

– pmkro
Nov 20 '18 at 15:34





Both your data sets have the same number of entries for each groups, so the bars/scale will just transition to the new domain but bars won't be added or removed.

– pmkro
Nov 20 '18 at 15:34













have a look at your svg DOM with DevTools. There is something wrong in your code. Or is the chart animating what you want?

– rioV8
Nov 20 '18 at 16:06





have a look at your svg DOM with DevTools. There is something wrong in your code. Or is the chart animating what you want?

– rioV8
Nov 20 '18 at 16:06













@pmkro thanks, I edited the post to better highlight the issue. Since the data join is keyed (i.e. not keyed on index), even if the number of elements are the same, changes should be entered and exited, right?

– rove
Nov 21 '18 at 8:49





@pmkro thanks, I edited the post to better highlight the issue. Since the data join is keyed (i.e. not keyed on index), even if the number of elements are the same, changes should be entered and exited, right?

– rove
Nov 21 '18 at 8:49













@rioV8, thanks, from examining the svg I can see new elements are joined and append, but none are removed. The new jsfiddle better highlights the issue

– rove
Nov 21 '18 at 8:52





@rioV8, thanks, from examining the svg I can see new elements are joined and append, but none are removed. The new jsfiddle better highlights the issue

– rove
Nov 21 '18 at 8:52













read the docs (d3-select) about select(All) and the Data join

– rioV8
Nov 21 '18 at 10:40





read the docs (d3-select) about select(All) and the Data join

– rioV8
Nov 21 '18 at 10:40












0






active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53396369%2fd3-exit-not-functioning-as-expected-in-grouped-bar-chart%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53396369%2fd3-exit-not-functioning-as-expected-in-grouped-bar-chart%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Xamarin.form Move up view when keyboard appear

Post-Redirect-Get with Spring WebFlux and Thymeleaf

Anylogic : not able to use stopDelay()