|
<!DOCTYPE html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>Rob's Scatter Plot</title> |
|
<style> |
|
body{font-family: sans-serif;} |
|
|
|
//.circles{fill:"red";} |
|
|
|
|
|
.legendCells, text { |
|
fill: #8E8883; |
|
font-size: 10pt; |
|
font-family: sans-serif; |
|
} |
|
|
|
|
|
.axis-label, .legend-label |
|
{ |
|
fill: #635F5D; |
|
font-size: 20pt; |
|
font-family: sans-serif; |
|
} |
|
|
|
.annotation |
|
{ |
|
font-size:20pt; |
|
} |
|
|
|
</style> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js"></script> |
|
|
|
</head> |
|
|
|
<body> |
|
|
|
<h1>Diastolic vs. Systolic Blood Pessure</h1> |
|
<script> |
|
|
|
|
|
|
|
//var pointRadius = 6; |
|
var margin = {left: 100, right: 20, top: 20, bottom: 180}; |
|
var outerWidth = 940; |
|
var innerWidth = outerWidth - margin["left"] - margin["right"]; |
|
var outerHeight = 500; |
|
var innerHeight = outerHeight - margin["top"] - margin["bottom"]; |
|
|
|
|
|
var svg = d3.select("body").append("svg").attr("width", outerWidth).attr("height", outerHeight); |
|
var g = svg.append("g").attr("transform", "translate(" + margin["left"] + "," + margin["top"] +")"); |
|
|
|
g.append('text') |
|
.text('Circle area encodes Age') |
|
.attr('class', 'annotation') |
|
.attr('x', 500) |
|
.attr('y', 250); |
|
|
|
var xAxisG = g.append("g").attr("transform", "translate(0," + innerHeight + ")"); |
|
|
|
|
|
var yAxisG = g.append("g"); |
|
|
|
|
|
|
|
var colorLegendG = g.append("g").attr("transform", "translate(50, 40)"); |
|
|
|
|
|
|
|
function render(data |
|
, x_input |
|
, y_input |
|
, color_input){ |
|
|
|
var colorValue = d => d[color_input]; |
|
var max_x = d3.max(data, function(d){return d[x_input];}); |
|
var max_y = d3.max(data, function(d){return d[y_input];}); |
|
var xScale = d3.scaleLinear().range([0,innerWidth]).domain([0,max_x]); |
|
var yScale = d3.scaleLinear().range([innerHeight,0]).domain([0,max_y]); |
|
var colorScale = d3.scaleOrdinal().range(d3.schemeCategory10); |
|
|
|
var xAxis = d3.axisBottom().scale(xScale).tickPadding(2); |
|
var yAxis = d3.axisLeft().scale(yScale).tickPadding(2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
xAxisG |
|
.append("text") |
|
.attr('class', 'axis-label') |
|
.attr("x", innerWidth/2) |
|
.attr("y", margin["bottom"]/4) |
|
.text(x_input + " (Diastolic)"); |
|
|
|
yAxisG |
|
.append("text") |
|
.attr("x", -innerHeight/5) |
|
.attr('class', 'axis-label') |
|
.attr("y", -margin["left"]/2) |
|
.attr("transform", `rotate(-90)`) |
|
.text(y_input + "(Systolic)"); |
|
|
|
|
|
colorLegendG |
|
.append('text') |
|
.attr('class', 'legend-label') |
|
.attr('x', -10) |
|
.attr('y', -15) |
|
.text(color_input); |
|
|
|
|
|
const colorLegend = d3.legendColor() |
|
.scale(colorScale) |
|
.shape('circle'); |
|
|
|
xScale.domain([0, max_x]); |
|
yScale.domain([0,max_y]); |
|
|
|
xAxisG.call(xAxis); |
|
yAxisG.call(yAxis); |
|
|
|
|
|
|
|
var circs = g.selectAll("circle").data(data); |
|
|
|
circs.enter().append("circle") |
|
.attr("r",function(d){return(Math.sqrt(d.Age));}) |
|
.attr("stroke", d => colorScale(colorValue(d))) |
|
.attr("fill","none") |
|
.attr("cx", function(d){return(xScale(d[x_input]));}) |
|
.attr("cy", function(d){return(yScale(d[y_input]));}); |
|
|
|
circs.exit().remove(); |
|
|
|
|
|
colorLegendG.call(colorLegend) //Has to come after the rendering of the circle since |
|
.selectAll('.cell text') //colordomain is automatically filled and legend needs color domain |
|
.attr('dy', '0.1em'); |
|
|
|
|
|
|
|
}; |
|
|
|
const row = d =>{ |
|
d.Age = +d.Age; |
|
d.SBP = +d.SBP; |
|
d.DBP = +d.DBP |
|
d.Gender = d.Gender; |
|
return(d); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
d3.csv("DominicanHTD.csv",row, function(array){render(array, "DBP", "SBP", "Gender");}); |
|
|
|
|
|
</script> |
|
</body> |