Reputation: 3
I made a scatterplot that changes dynamically based on the variable for the Y axis that is selected in a dropdown box (the x axis is fixed). However the Y axis isn’t scaling/changing based on which variable is selected in the dropdown box.
// select svg canvas
var m = [20, 20, 30, 20], // margins
w = 1100-m[1]-m[3], // width
h = 650-m[0]-m[2], // height
xcol = 0, // active x column
ycol = 1; // active y column
// create svg element, adjusted by margins
var svg = d3.select('#chart')
.append("g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
// add the tooltip area to the webpage
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// load data from csv file
d3.csv('nbaWins.csv', function(data) {
// get columns of csv, mark excluded columns
var columns = d3.keys( data[0] ),
excluded = ['Team'];
// get quantitative dimensions
var dimensions = _(columns)
.difference(excluded);
// extents for each dimension
var extents = _(dimensions)
.map(function(col) {
return [0, d3.max(data, function(d) { return parseFloat(d[col]) })]
});
// x & y variables
var x = d3.scale.linear().domain(extents[xcol]).range([0, w - 50]),
y = d3.scale.linear().domain(extents[ycol]).range([h, 0]),
xAxis = d3.svg.axis().scale(x).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");
// color scale (change colors later)
var color = {
"ATL": '#ff9896',
"BOS": '#ff9896',
"BKN": '#ff9896',
"CHA": '#ff9896',
"CHI": '#ff9896',
"CLE": '#ff9896',
"DAL": '#ff9896',
"DEN": '#ff9896',
"DET": '#ff9896',
"GSW": '#ff9896',
"HOU": '#ff9896',
"IND": '#ff9896',
"LAC": '#ff9896',
"LAL": '#ff9896',
"MEM": '#ff9896',
"MIA": "#ff9896",
"MIL": '#ff9896',
"MIN": '#ff9896',
"NO" : '#ff9896',
"NYK": '#ff9896',
"OKC": '#ff9896',
"ORL": '#ff9896',
"PHI": '#ff9896',
"PHO": '#ff9896',
"POR": '#ff9896',
"SAC": '#ff9896',
"SAS": '#ff9896',
"TOR": '#ff9896',
"UTA": '#ff9896',
"WAS": '#ff9896'
};
// create x axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", w - 40)
.attr("y", -6)
.style("text-anchor", "end")
.text("Wins");
// create y axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// bind data to chart
svg.selectAll('circle')
.data(data)
.enter().append('circle')
.attr("fill", function(d) { return color[d.Team]; })
.attr("cx", function(d) { return x(d[dimensions[xcol]]); })
.attr("cy", function(d) { return y(d[dimensions[ycol]]); })
.attr("r", 5) //backup
.on("mouseover", function(d) {
tooltip.transition().duration(200).style("opacity", .9);
tooltip.html(d["Team"] + "<br/> (" + d[dimensions[xcol]]
+ ", " + d[dimensions[ycol]] + ")")
.style("left", d + "px")
.style("top", d + "px");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
// change x axis data (may not need: x axis is static)
function xaxis(i) {
xcol = i;
x.domain(extents[i]);
svg.selectAll('circle')
.transition()
.ease('linear')
.duration(1000)
.attr("cx", function(d) { return x(d[dimensions[0]]); })
.attr("cy", function(d) { return y(d[dimensions[ycol]]); });
};
// change y axis data
function yaxis(i) {
ycol = i;
y.domain(extents[i]);
svg.selectAll('circle')
.transition()
.ease('linear')
.duration(1000)
.attr("cx", function(d) { return x(d[dimensions[0]]); })
.attr("cy", function(d) { return y(d[dimensions[i]]); });
};
// create dropdowns to change y axes
d3.select("#yaxis")
.selectAll("option")
.data(dimensions)
.enter().append("option")
.attr("value", function(d,i) { return i; })
.text(function(d) { return d; })
.each(function(d,i) {
if (i == ycol) d3.select(this).attr("selected", "yes");
});
d3.select("#yaxis")
.on("change", function() { yaxis(this.selectedIndex) });
window.data = data;
});
Here is the console error I get when I try to change the Y variable:
NotFoundError: DOM Exception 8: An attempt was made to reference a Node in a context where it does not exist.
Any ideas on how to fix this? Any help would be much appreciated.
Upvotes: 0
Views: 467
Reputation: 108512
You've set the domain of the y
but haven't redrawn the axis with it:
// change y axis data
function yaxis(i) {
ycol = i;
y.domain(extents[i]);
// update y axis
svg.selectAll("g.y.axis")
.call(yAxis);
svg.selectAll('circle')
.transition()
.ease('linear')
.duration(1000)
.attr("cx", function(d) { return x(d[dimensions[0]]); })
.attr("cy", function(d) { return y(d[dimensions[i]]); });
};
Example here.
Upvotes: 1