Reputation: 317
I'm new to d3.js & html and I could not find an answer to my problem yet.
I have this Array I want to plot on a time graph. This is the CSV with marked countries i want to filter
This is an example of my plot right now
As you may see you can't recognize which circles belong to which country. I wanted to integrate some mousevents etc. to distinguish the circles.
body,
html {
margin: 0;
padding: 0;
font-family: "Arial", sans-serif;
font-size: 0.95em;
text-align: center;
}
#chart {
background-color: #F5F2EB;
border: 1px solid #CCC;
}
.bar {
fill: purple;
shape-rendering: crispEdges;
}
.bar-label {
fill: black;
text-anchor: middle;
font-size: 18px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.gridline path,
.gridline line {
fill: none;
stroke: #ccc;
shape-rendering: crispEdges;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Learning D3</title>
<link rel="stylesheet" href="main.css">
<script type="text/javascript" src="d3.min.js"></script>
</head>
<body>
<!--Place all DOM elements here -->
<script>
d3.csv("refugee_data.csv", function(d) {
return {
date: d.Year + "/" + d.Month,
origin: d.Origin,
asylum: d.Asylum,
value: +d.Value
};
}, function(error, rows) {
console.log(rows);
render(rows)
});
function render(data) {
var w = 800;
var h = 450;
var margin = {
top: 100,
bottom: 0,
left: 80,
right: 40
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("id", "chart")
.attr("width", w)
.attr("height", h)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var dateParser = d3.time.format("%Y/%B").parse;
var x = d3.time.scale()
.domain(d3.extent(data, function(d) {
var date = dateParser(d.date);
return date;
}))
.range([0 + margin.left, width]);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d) {
return d.value;
})])
.range([height, 0 + margin.top]);
//range([0, height]);
//enter()
svg.selectAll(".point")
.data(data)
.enter()
.append("circle")
.classed("point", true)
.attr("r", 2);
//Update
svg.selectAll(".point")
.attr("cx", function(d) {
var date = dateParser(d.date);
return x(date);
})
.attr("cy", function(d) {
return y(d.value);
})
//Exit()
svg.selectAll(".point")
.data(data)
.exit()
.remove();
}
</script>
</body>
</html>
Basically I want to achieve this kind of plot
var data = [{
glazed: 3.14,
jelly: 4.43,
powdered: 2.43,
sprinkles: 3.86,
age: 18,
responses: 7
}, {
glazed: 3.00,
jelly: 3.67,
powdered: 2.67,
sprinkles: 4.00,
age: 19,
responses: 3
}, {
glazed: 2.00,
jelly: 4.00,
powdered: 2.33,
sprinkles: 4.33,
age: 20,
responses: 3
}, {
glazed: 3.50,
jelly: 4.50,
powdered: 1.00,
sprinkles: 3.50,
age: 21,
responses: 2
}, {
glazed: 2.83,
jelly: 3.50,
powdered: 1.83,
sprinkles: 4.50,
age: 22,
responses: 6
}, {
glazed: 3.25,
jelly: 4.75,
powdered: 2.25,
sprinkles: 3.50,
age: 23,
responses: 4
}, {
glazed: 1.50,
jelly: 4.00,
powdered: 2.50,
sprinkles: 4.00,
age: 25,
responses: 2
}, {
glazed: 1.67,
jelly: 3.00,
powdered: 1.33,
sprinkles: 4.00,
age: 26,
responses: 3
}, {
glazed: 2.50,
jelly: 4.00,
powdered: 1.00,
sprinkles: 4.50,
age: 27,
responses: 2
}, {
glazed: 3.00,
jelly: 4.33,
powdered: 1.33,
sprinkles: 4.33,
age: 28,
responses: 3
}, {
glazed: 5.00,
jelly: 4.00,
powdered: 1.00,
sprinkles: 4.00,
age: 29,
responses: 1
}, {
glazed: 5.00,
jelly: 5.00,
powdered: 2.00,
sprinkles: 5.00,
age: 30,
responses: 1
}, {
glazed: 1.50,
jelly: 4.50,
powdered: 3.00,
sprinkles: 4.75,
age: 31,
responses: 4
}, {
glazed: 3.67,
jelly: 3.33,
powdered: 1.67,
sprinkles: 4.67,
age: 32,
responses: 3
}, {
glazed: 2.00,
jelly: 4.50,
powdered: 1.00,
sprinkles: 5.00,
age: 33,
responses: 2
}, {
glazed: 2.75,
jelly: 3.75,
powdered: 2.50,
sprinkles: 4.50,
age: 34,
responses: 4
}, {
glazed: 4.00,
jelly: 3.00,
powdered: 2.75,
sprinkles: 4.25,
age: 35,
responses: 4
}, {
glazed: 1.50,
jelly: 3.00,
powdered: 4.00,
sprinkles: 4.00,
age: 36,
responses: 2
}, {
glazed: 3.00,
jelly: 3.00,
powdered: 3.50,
sprinkles: 4.00,
age: 37,
responses: 2
}, {
glazed: 4.00,
jelly: 2.00,
powdered: 3.33,
sprinkles: 4.67,
age: 39,
responses: 3
}, {
glazed: 3.50,
jelly: 3.00,
powdered: 4.00,
sprinkles: 4.50,
age: 40,
responses: 2
}, {
glazed: 2.75,
jelly: 2.75,
powdered: 4.00,
sprinkles: 4.25,
age: 41,
responses: 4
}, {
glazed: 2.25,
jelly: 2.50,
powdered: 1.75,
sprinkles: 4.25,
age: 42,
responses: 4
}, {
glazed: 1.00,
jelly: 2.00,
powdered: 1.00,
sprinkles: 5.00,
age: 43,
responses: 1
}, {
glazed: 2.00,
jelly: 3.00,
powdered: 3.67,
sprinkles: 3.33,
age: 44,
responses: 3
}, {
glazed: 3.33,
jelly: 2.33,
powdered: 3.33,
sprinkles: 3.33,
age: 46,
responses: 3
}, {
glazed: 2.25,
jelly: 4.00,
powdered: 2.75,
sprinkles: 3.00,
age: 47,
responses: 4
}, {
glazed: 3.75,
jelly: 2.00,
powdered: 3.00,
sprinkles: 2.75,
age: 48,
responses: 4
}, {
glazed: 2.75,
jelly: 2.00,
powdered: 3.75,
sprinkles: 3.25,
age: 49,
responses: 4
}, {
glazed: 2.67,
jelly: 2.67,
powdered: 1.67,
sprinkles: 3.67,
age: 51,
responses: 3
}, {
glazed: 2.50,
jelly: 2.50,
powdered: 4.00,
sprinkles: 3.00,
age: 52,
responses: 2
}, {
glazed: 3.00,
jelly: 3.67,
powdered: 4.67,
sprinkles: 2.67,
age: 53,
responses: 3
}, {
glazed: 5.00,
jelly: 5.00,
powdered: 5.00,
sprinkles: 3.50,
age: 54,
responses: 2
}, {
glazed: 2.33,
jelly: 1.67,
powdered: 2.33,
sprinkles: 3.33,
age: 55,
responses: 3
}, {
glazed: 3.00,
jelly: 2.00,
powdered: 3.00,
sprinkles: 3.00,
age: 56,
responses: 1
}, {
glazed: 2.00,
jelly: 2.00,
powdered: 2.00,
sprinkles: 4.00,
age: 57,
responses: 1
}, {
glazed: 1.25,
jelly: 2.00,
powdered: 3.00,
sprinkles: 1.75,
age: 59,
responses: 4
}, {
glazed: 2.50,
jelly: 2.50,
powdered: 4.00,
sprinkles: 2.50,
age: 60,
responses: 2
}, {
glazed: 2.33,
jelly: 2.33,
powdered: 2.67,
sprinkles: 3.00,
age: 61,
responses: 3
}, {
glazed: 2.25,
jelly: 2.50,
powdered: 3.75,
sprinkles: 3.00,
age: 62,
responses: 4
}, {
glazed: 1.50,
jelly: 3.00,
powdered: 3.00,
sprinkles: 2.00,
age: 63,
responses: 2
}, {
glazed: 2.00,
jelly: 3.00,
powdered: 3.40,
sprinkles: 2.40,
age: 64,
responses: 5
}, {
glazed: 2.00,
jelly: 1.00,
powdered: 4.50,
sprinkles: 2.00,
age: 65,
responses: 2
}, {
glazed: 2.00,
jelly: 1.67,
powdered: 4.00,
sprinkles: 1.67,
age: 66,
responses: 3
}, {
glazed: 1.50,
jelly: 1.75,
powdered: 3.75,
sprinkles: 2.25,
age: 67,
responses: 4
}, {
glazed: 2.00,
jelly: 2.50,
powdered: 4.25,
sprinkles: 2.00,
age: 68,
responses: 4
}, {
glazed: 3.00,
jelly: 2.00,
powdered: 3.00,
sprinkles: 3.00,
age: 70,
responses: 1
}, {
glazed: 2.33,
jelly: 2.67,
powdered: 4.33,
sprinkles: 2.33,
age: 71,
responses: 3
}, {
glazed: 3.00,
jelly: 2.50,
powdered: 3.75,
sprinkles: 2.00,
age: 72,
responses: 4
}, {
glazed: 2.00,
jelly: 2.50,
powdered: 4.50,
sprinkles: 2.50,
age: 73,
responses: 2
}, {
glazed: 3.00,
jelly: 2.00,
powdered: 4.00,
sprinkles: 1.50,
age: 74,
responses: 2
}];
body,
html {
margin: 0;
padding: 0;
font-family: "Arial", sans-serif;
font-size: 0.95em;
text-align: center;
}
#chart {
background-color: #F5F2EB;
border: 1px solid #CCC;
}
.bar {
fill: purple;
shape-rendering: crispEdges;
}
.bar-label {
fill: black;
text-anchor: middle;
font-size: 18px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.gridline path,
.gridline line {
fill: none;
stroke: #ccc;
shape-rendering: crispEdges;
}
.trendline {
fill: none;
stroke: #ccc;
stroke-width: 4px;
}
.area {
opacity: 0.25;
fill: #ccc;
stroke: #ccc;
stroke-width: 1px;
}
.donut {
opacity: 0.1;
}
.highlight {
opacity: 1;
cursor: hand;
}
.axis-label {
text-anchor: middle;
}
.chart-header {
text-transform: capitalize;
font-size: 125%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Learning D3</title>
<link rel="stylesheet" href="main.css">
<script type="text/javascript" src="d3.min.js"></script>
</head>
<body>
<!--Place all DOM elements here -->
<script type="text/javascript" src="survey_data.js"></script>
<script>
var w = 800;
var h = 450;
var margin = {
top: 60,
bottom: 80,
left: 100,
right: 80
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("id", "chart")
.attr("width", w)
.attr("height", h);
var chart = svg.append("g")
.classed("display", true)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var tickValues = [18, 25, 32, 39, 46, 53, 60, 67, 74];
var colorScale = d3.scale.category10();
var x = d3.scale.linear()
.domain(d3.extent(data, function(d) {
return d.age;
}))
.range([0, width]);
var y = d3.scale.linear()
.domain([1, 5])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickValues(tickValues)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.ticks(5)
.tickSize(20)
.tickFormat(function(d) {
return d.toFixed(1);
})
.orient("left");
var xGridlines = d3.svg.axis()
.scale(x)
.tickValues(tickValues)
.tickSize(height, height)
.tickFormat("")
.orient("bottom");
var yGridlines = d3.svg.axis()
.scale(y)
.tickSize(-width, 0, 0)
.tickFormat("")
.orient("left");
var responseScale = d3.scale.linear()
.domain(d3.extent(data, function(d) {
return d.responses;
}))
.range([2, 15]);
var initialize = 1;
function drawAxis(params) {
if (initialize) {
this.append("g")
.call(params.gridlines.x)
.classed("gridline x", true)
.attr("transform", "translate(" + 0 + "," + 0 + ")");
this.append("g")
.call(params.gridlines.y)
.classed("gridline y", true)
.attr("transform", "translate(" + 0 + "," + 0 + ")");
this.append("g")
.call(params.axis.x)
.classed("axis x", true)
.attr("transform", "translate(" + 0 + "," + height + ")");
this.append("g")
.call(params.axis.y)
.classed("axis y", true)
.attr("transform", "translate(" + 0 + "," + 0 + ")");
this.select(".y.axis")
.append("text")
.classed("y axis-label", true)
.attr("transform", "translate(" + -56 + "," + height / 2 + ") rotate(-90)")
.text("Rating (1=Low, 5=High)");
this.select(".x.axis")
.append("text")
.classed("x axis-label", true)
.attr("transform", "translate(" + width / 2 + "," + 48 + ")")
.text("Customer age");
this.append("g")
.append("text")
.classed("chart-header", true)
.text("")
.attr("transform", "translate(0," + -24 + ")")
initialize = 0;
}
}
function plot(params) {
var self = this;
//Get each of the donut types
var donuts = d3.keys(params.data[0]).filter(function(d) {
return d !== "age" && d !== "responses";
});
drawAxis.call(this, params);
//Create a group for each type of donut
this.selectAll(".donut")
.data(donuts)
.enter()
.append("g")
.attr("class", function(d) {
return d;
})
.classed("donut", true);
this.selectAll(".donut")
.style("fill", function(d, i) {
return colorScale(i);
})
.on("mouseover", function(d, i) {
d3.select(this)
//.classed("highlight", true)
.transition()
.style("opacity", 1);
})
.on("mouseout", function(d, i) {
d3.select(this)
//.classed("highlight", false)
.transition()
.style("opacity", 0.1);
});
donuts.forEach(function(donut) {
var g = self.selectAll("g." + donut);
var arr = params.data.map(function(d) {
return {
key: donut,
value: d[donut],
age: d.age,
responses: d.responses
};
});
//Setup circles
g.selectAll(".response")
.data(arr)
.enter()
.append("circle")
.classed("response", true);
//Update circles
g.selectAll(".response")
.attr("r", function(d) {
return responseScale(d.responses);
})
.attr("cx", function(d) {
return x(d.age);
})
.attr("cy", function(d) {
return y(d.value);
})
.on("mouseover", function(d, i) {
var str = d.key + " Donut: ";
str += "Age: " + d.age + ", ";
str += "Responses: " + d.responses + ", ";
str += "Average Rating: " + d.value;
str += ""
d3.select(".chart-header").text(str);
})
.on("mouseout", function(d, i) {
d3.select(".chart-header").text("");
});
//Remove any unbound elements
g.selectAll(".response").data(arr).exit().remove();
});
}
plot.call(chart, {
data: data,
gridlines: {
x: xGridlines,
y: yGridlines
},
axis: {
x: xAxis,
y: yAxis
}
});
</script>
</body>
</html>
Upvotes: 2
Views: 387
Reputation: 6419
To filter your data so that you just have data from a specific origin, you can use the filter
function. This function takes one argument, which is another function that will return true for all data points you want to include and false for all data points you want to exclude. For instance, if you want the circles that have Germany as their origin, you could do this:
var germany = svg.selectAll(".point")
.filter(function(d) {return d.Origin == "Germany"});
As for setting color and opacity, it doesn't look like you're doing that anywhere (even in your stylesheet, you don't have any styles for "circle" elements or the ".point" class). Since you want to just change the color and opacity for a subset of your circles, your best bet is to use d3's style()
function, which lets you change the style of data points. For instance, if you wanted to make all of the circles representing data points with Germany as their origin be red and completely opaque, you could do this:
germany.style("fill", "red").style("opacity", 1);
Alternatively, if you wanted to color all circles based on their origin, you could skip the filtering step and use a color scale to color all of them at once:
//creates a scale to assign colors
var colorScale = d3.scale.category10();
//Then apply it to all points by assigning
// fill based on a callback function
svg.selectAll(".point")
.style("fill", function(d){return colorScale(d.Origin)});
Upvotes: 2