Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<div id="container"></div>
<body>
<script>
d3.svg.survivalLineChart = function(id, rData){
/*
rData formation:
[
["name1", [month, survivalRate, marked], [x, y, 0], [x, y, 1], ... ],
["name2", [month, survivalRate, marked], [x, y, 0], [x, y, 1], ... ],
["name3", [month, survivalRate, marked], [x, y, 0], [x, y, 1], ... ]
]
*/
var svgWidth = 640,
svgHeight = 450,
margin = {top: 30, right: 100, bottom: 60, left: 70},
width = svgWidth - margin.left - margin.right,
height = svgHeight - margin.top - margin.bottom,
radius = 1,
legendRect = 12,
legendSpan = 23,
duration = 2000,
colors = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"];
if(!rData){
alert("data is empty"); return;
}
// data proccessing
var maxLifeSpan = 0,
data = rData.map(function(d, i){
maxLifeSpan = Math.max(d3.max(d[1].map(function(e){ return e[0]; })), maxLifeSpan);
return {
name: d[0],
points: d[1].map(function(e){return [ e[0], e[1], e[2], colors[i] ]; }),
color: colors[i]
};
}),
xScale = d3.scale.linear().domain([0, maxLifeSpan]).range([0, width]),
yScale = d3.scale.linear().domain([0, 1]).range([0, height]),
xAxis = d3.svg.axis().orient("bottom").scale(xScale),
yAxis = d3.svg.axis().orient("left").tickFormat(d3.format("%")).ticks(5).scale(yScale.copy().range([height, 0]));
var svg = d3.select("#" + id).html("")
.append("svg")
.style("font-size", "12px")
.attr({
width : svgWidth,
height : svgHeight,
"shape-rendering" : "crispEdges",
version : 1.1,
xmlns : "https://www.w3.org/2000/svg"
});
var use = "<line x1='" + (-5 - radius) + "' x2='" + (5 + radius) + "' y1='0' y2='0' />" +
"<line y1='" + (-5 - radius) + "' y2='" + (5 + radius) + "' x1='0' x2='0' />";
svg.append("defs").append("g").attr("id", "s-cross").html(use);
var plotMain = svg.append("g")
.attr({
class: "s-plot-main",
transform: "translate(" + [margin.left, margin.top] + ")"
}),
gLegend = plotMain.append("g")
.attr({
class: "legend",
transform: "translate(" + [width + 10, 0.5 * (height - ((data.length - 1) * legendSpan + legendRect))] + ")"
}),
gXAxis = plotMain.append("g")
.attr({
class: "s-axis xaxis",
transform: "translate(" + [0, height] + ")"
}),
gYAxis = plotMain.append("g").attr("class", "s-axis yaxis");
// axises generation & uniform all style
function uniformAxis(s){
s.select(".domain").attr({ fill: "none", stroke: "#333", "stroke-width": 1});
if(s.node().classList.contains("yaxis")){
s.selectAll(".tick line").each(function(d){
d3.select(this).attr({ x1: -6, x2: width, stroke: "#333", "stroke-width": 1, "stroke-dasharray": "6,6" });
});
}else{
s.selectAll(".tick line").attr({ stroke: "#333", "stroke-width": 1 });
}
}
gXAxis.call(xAxis).call(uniformAxis);
gYAxis.call(yAxis).call(uniformAxis);
// draw legend
gLegend.selectAll("g.legend-item")
.data(data)
.enter()
.append("g")
.attr("transform", function(d,i){ return "translate(0," + (i * legendSpan) + ")"; })
.each(function(d,i){
d3.select(this).append("rect").attr({ width: legendRect, height: legendRect, fill: colors[i] });
d3.select(this).append("text").text(d.name).attr({ dx: 18, dy: 10 });
});
gLegend.append("g")
.attr({"class": "cross", "transform": "translate(0," + -legendSpan + ")"})
.call(function(s){
s.append("use").attr({href: "#s-cross", stroke: "black", "transform": "translate(6,0)"});
s.append("text").text("CENSORED").attr({dx: 15, dy: 3});
});
// adding axis titles
gYAxis.append("text").text("Survival Rate")
.attr({ transform: "translate(" + [-45, 0.5 * height] + ")rotate(-90)", "text-anchor": "middle" });
gXAxis.append("text").text("Months")
.attr({ transform: "translate(" + [0.5 * width, 40] + ")", "text-anchor": "middle" });
// draw lines
// linear linear-closed step step-before step-after
var line = d3.svg.line()
.x(function(d){ return xScale(d[0]); })
.y(function(d){ return -yScale(d[1]); })
.interpolate("step-after");
var gLine = plotMain.selectAll("g.s-plot-item")
.data(data)
.enter()
.append("g")
.attr({
class: "s-plot-item",
transform: "translate(" + [0, height] + ")"
});
gLine.selectAll("g")
.data(function(d){ return d.points.filter(function(e){ return e[2]; }); })
.enter()
.append("g")
.attr("transform", function(d){ return "translate(" + [xScale(d[0]), -yScale(d[1])] + ")"; })
.append("use")
.attr({href: "#s-cross", stroke: "black"});
gLine.append("path")
.attr({
d: function(d){ return line(d.points.slice(0)); },
fill: "none",
"stroke-width": 2,
stroke: function(d){ return d.color; }
})
.transition()
.duration(duration)
.attrTween("d", function(d){
var i = d3.interpolate(1, d.points.length);
return function(t){ return line(d.points.slice(0, Math.ceil(i(t)))); };
});
/*
gLine.selectAll("circle")
.data(function(d){return d.points; })
.enter()
.append("circle")
.attr({
fill: function(d){ return d[3]; },
r: 0,
cx: function(d){ return xScale(d[0]); },
cy: 0
})
.transition()
.duration(duration)
.attr({ r: radius, cy: function(d){ return -yScale(d[1]); } });
*/
};
var acc = [
["MALE", [[0, 1.0, 0],[5, 0.9666666666666667, 0],[13, 0.9333333333333333, 0],[16, 0.9, 1],[17, 0.8666666666666667, 0],[19, 0.7666666666666667, 1],[20, 0.7333333333333334, 0],[23, 0.7000000000000001, 0],[25, 0.6666666666666667, 1],[26, 0.6333333333333334, 1],[28, 0.6000000000000001, 1],[29, 0.5666666666666668, 1],[40, 0.5333333333333334, 0],[41, 0.4666666666666668, 1],[44, 0.43333333333333346, 1],[46, 0.40000000000000013, 0],[50, 0.3666666666666668, 1],[53, 0.3333333333333335, 1],[59, 0.30000000000000016, 0],[62, 0.26666666666666683, 1],[68, 0.2333333333333335, 1],[74, 0.20000000000000018, 1],[78, 0.16666666666666685, 1],[85, 0.13333333333333353, 1],[92, 0.1000000000000002, 1],[110, 0.06666666666666687, 1],[116, 0.03333333333333354, 1],[121, 2.0816681711721685e-16, 1]]],
["FEMALE", [[0, 1.0, 0],[6, 0.9824561403508771, 0],[7, 0.9649122807017543, 0],[10, 0.9473684210526314, 0],[12, 0.9298245614035086, 0],[13, 0.9122807017543857, 0],[14, 0.8947368421052628, 0],[15, 0.8421052631578945, 0],[17, 0.8070175438596489, 0],[19, 0.7719298245614032, 0],[21, 0.7543859649122804, 1],[23, 0.7368421052631575, 1],[24, 0.7192982456140347, 1],[25, 0.7017543859649118, 1],[29, 0.6842105263157889, 1],[30, 0.6491228070175433, 1],[31, 0.6140350877192977, 1],[33, 0.5964912280701749, 1],[34, 0.578947368421052, 0],[37, 0.5087719298245608, 1],[40, 0.47368421052631515, 1],[44, 0.45614035087719235, 1],[46, 0.42105263157894673, 1],[48, 0.40350877192982393, 1],[50, 0.3859649122807011, 1],[54, 0.3684210526315783, 0],[56, 0.3508771929824555, 0],[60, 0.3333333333333327, 1],[62, 0.2982456140350871, 1],[68, 0.2807017543859643, 1],[69, 0.2631578947368415, 1],[70, 0.22807017543859587, 1],[71, 0.19298245614035026, 1],[79, 0.17543859649122745, 1],[80, 0.15789473684210464, 0],[81, 0.14035087719298184, 0],[90, 0.12280701754385903, 1],[91, 0.10526315789473623, 1],[93, 0.08771929824561342, 1],[97, 0.07017543859649061, 1],[102, 0.05263157894736781, 1],[130, 0.035087719298245, 1],[155, 0.017543859649122195, 1],[156, -6.106226635438361e-16, 1]]]
];
d3.svg.survivalLineChart("container", acc);
</script>
</body>
https://d3js.org/d3.v3.min.js