Last active
August 29, 2015 14:00
-
-
Save dukevis/11004937 to your computer and use it in GitHub Desktop.
chord diagram + multiline chart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Year | UNC | Duke | NCS | WF | MD | UVA | Clem | |
---|---|---|---|---|---|---|---|---|
1954 | 0 | 1 | 3 | 2 | 1 | 0 | 0 | |
1955 | 0 | 3 | 6 | 3 | 1 | 1 | 0 | |
1956 | 1 | 4 | 9 | 5 | 1 | 1 | 0 | |
1957 | 3 | 4 | 9 | 6 | 2 | 1 | 0 | |
1958 | 5 | 5 | 10 | 6 | 5 | 1 | 0 | |
1959 | 7 | 6 | 13 | 6 | 5 | 2 | 0 | |
1960 | 8 | 9 | 14 | 8 | 5 | 2 | 0 | |
1961 | 8 | 11 | 14 | 10 | 6 | 2 | 0 | |
1962 | 8 | 12 | 14 | 13 | 6 | 2 | 2 | |
1963 | 9 | 15 | 15 | 15 | 6 | 2 | 2 | |
1964 | 10 | 18 | 15 | 17 | 6 | 2 | 3 | |
1965 | 10 | 20 | 18 | 18 | 7 | 2 | 3 | |
1966 | 11 | 23 | 20 | 18 | 7 | 2 | 3 | |
1967 | 14 | 25 | 20 | 19 | 7 | 2 | 3 | |
1968 | 17 | 26 | 22 | 19 | 7 | 2 | 3 | |
1969 | 20 | 28 | 22 | 20 | 7 | 2 | 3 | |
1970 | 20 | 28 | 25 | 21 | 7 | 3 | 3 | |
1971 | 22 | 28 | 26 | 21 | 7 | 4 | 3 | |
1972 | 24 | 29 | 26 | 21 | 9 | 5 | 3 | |
1973 | 24 | 29 | 28 | 22 | 11 | 6 | 3 | |
1974 | 25 | 29 | 30 | 22 | 13 | 7 | 3 | |
1975 | 28 | 29 | 32 | 22 | 13 | 7 | 4 | |
1976 | 29 | 29 | 32 | 22 | 14 | 10 | 5 | |
1977 | 31 | 29 | 33 | 22 | 14 | 12 | 6 | |
1978 | 31 | 32 | 33 | 24 | 15 | 12 | 6 | |
1979 | 33 | 34 | 34 | 24 | 16 | 12 | 6 | |
1980 | 34 | 37 | 34 | 24 | 18 | 12 | 7 | |
1981 | 37 | 37 | 34 | 25 | 20 | 13 | 7 | |
1982 | 40 | 37 | 35 | 26 | 20 | 15 | 7 | |
1983 | 41 | 37 | 38 | 26 | 20 | 17 | 7 | |
1984 | 42 | 39 | 38 | 27 | 23 | 17 | 7 | |
1985 | 44 | 40 | 39 | 27 | 23 | 17 | 7 | |
1986 | 44 | 43 | 39 | 27 | 24 | 18 | 7 | |
1987 | 46 | 43 | 42 | 28 | 24 | 19 | 7 | |
1988 | 48 | 46 | 43 | 28 | 25 | 19 | 7 | |
1989 | 51 | 48 | 43 | 28 | 26 | 20 | 7 | |
1990 | 51 | 49 | 43 | 28 | 26 | 22 | 8 | |
1991 | 54 | 50 | 44 | 28 | 26 | 23 | 8 | |
1992 | 56 | 53 | 44 | 28 | 27 | 23 | 8 | |
1993 | 58 | 53 | 44 | 28 | 28 | 24 | 9 | |
1994 | 61 | 54 | 44 | 29 | 28 | 26 | 10 | |
1995 | 63 | 55 | 44 | 32 | 29 | 27 | 10 | |
1996 | 63 | 55 | 45 | 35 | 30 | 27 | 11 | |
1997 | 66 | 55 | 48 | 36 | 31 | 27 | 11 | |
1998 | 69 | 57 | 49 | 36 | 32 | 27 | 12 | |
1999 | 71 | 60 | 50 | 36 | 33 | 27 | 12 | |
2000 | 71 | 63 | 51 | 37 | 35 | 27 | 12 | |
2001 | 73 | 66 | 51 | 37 | 36 | 27 | 13 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
body{ | |
font: 10px sans-serif; | |
} | |
.axis path, | |
.axis line{ | |
fill:none; | |
stroke:#000; | |
shape-rendering: crispEdges; | |
} | |
.line { | |
fill: none; | |
stroke: black; | |
stroke-width: 3.5px; | |
} | |
.legend{ | |
padding: 5px; | |
font: 10px sans-serif; | |
border: .5em solid black; | |
} | |
.team line{ | |
stroke: black; | |
} | |
.chord path { | |
fill-opacity: .67; | |
stroke: #000; | |
stroke-width: .5px; | |
} | |
.ticks { | |
font-family: sans-serif; | |
} | |
</style> | |
<title>ACC Tournament, Cumulative Wins</title> | |
<body> | |
<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script> | |
</head> | |
<script type="text/javascript"> | |
var matrix = [ | |
[0,8,10,14,11,10,12], | |
[9,0,11,12,9,11,5], | |
[4,8,0,6,10,10,5], | |
[7,4,3,0,3,6,7], | |
[3,6,5,3,0,4,9], | |
[3,3,2,6,4,0,5], | |
[1,3,2,3,1,1,0], | |
]; | |
var max_scores = []; | |
var teams = ["North Carolina","Duke","NC State","Wake Forest","Maryland", | |
"Virginia","Clemson"]; | |
var colors = ["#99BADD","#00009C","#CE1126","#CFB53B","#FF0000","#0D3268","#FF6300"]; | |
var abbrDict={"Clem":"Clemson","Duke":"Duke","MD":"Maryland","UNC":"North Carolina", "NCS":"NC State", "UVA":"Virginia","WF":"Wake Forest"}; | |
var dataset=0; | |
var w=932; | |
var h=490; | |
var padding = 30; | |
var color = d3.scale.ordinal() //custom color scale for teams | |
.range(colors) | |
.domain(teams); | |
d3.csv("basketball_data.csv",function(data){ | |
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Year"; })); | |
data.forEach(function(d) { | |
d.Year = +d.Year; | |
d.Clem = +d.Clem; | |
d.Duke = +d.Duke; | |
d.MD = +d.MD; | |
d.UNC = +d.UNC; | |
d.NCS = +d.NCS; | |
d.UVA = +d.UVA; | |
d.WF = +d.WF; | |
}); | |
var teams = color.domain().map(function(name) { | |
return { | |
name: name, | |
sort_value: 0, | |
values: data.map(function(d) { | |
return {date: d.Year, wins: d[name]}; | |
}) | |
}; | |
}); | |
//teams in order of most cumulative wins | |
teams.sort(function(a,b){ | |
var last_b = b.values.length; | |
var last_a = a.values.length; | |
max_scores.push(abbrDict[b.name]); | |
max_scores.push(b.values[last_b-1].wins); | |
max_scores.push(abbrDict[a.name]); | |
max_scores.push(a.values[last_a-1].wins); | |
return parseFloat(b.values[last_b-1].wins)-parseFloat(a.values[last_a-1].wins); | |
}); | |
console.log(max_scores); | |
console.log(teams); | |
visualize(teams); | |
}); | |
var visualize = function(team_dict){ | |
var svg = d3.select("body").append("svg") | |
.attr("width",w+padding*2) | |
.attr("height",h + padding*2) | |
.append("g") | |
.attr("transform", "translate(" + padding + "," + padding + ")"); | |
var chord = d3.layout.chord() | |
.padding(.05) | |
.sortSubgroups(d3.descending) | |
.matrix(matrix); | |
var innerRadius = Math.min(w, h) * .41; | |
var outerRadius = innerRadius * 1.1; | |
var chord_fill = d3.scale.ordinal() | |
.domain(d3.range(10)) | |
.range(colors); | |
//line chart code | |
var xScale = d3.scale.linear().range([padding/2,(w-padding/2)/3]); | |
var yScale = d3.scale.linear().range([h,padding]); | |
var xAxis = d3.svg.axis() | |
.scale(xScale) | |
.orient("bottom") | |
.tickFormat(d3.format("04d")); | |
var yAxis = d3.svg.axis() | |
.scale(yScale) | |
.orient("left"); | |
var line = d3.svg.line() | |
.x(function(d){ | |
if(xScale(d.date)<0){ //quick fix to ensure Wake Forest wasn't extending into negatives | |
return padding; | |
} | |
else{ | |
return padding+xScale(d.date); | |
} | |
}) | |
.y(function(d){ | |
return yScale(d.wins); | |
}) | |
xScale.domain([1954,2001]); | |
yScale.domain([ | |
d3.min(team_dict, function(c) { return d3.min(c.values, function(v) { return v.wins; }); }), | |
d3.max(team_dict, function(c) { return d3.max(c.values, function(v) { return v.wins; }); }) | |
]); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate("+padding+"," + h + ")") | |
.call(xAxis) | |
.append("text") | |
.attr("y",30) | |
.attr("x",w/4) | |
.style("font-size",16+"px") | |
.text("Year"); | |
svg.append("g") | |
.attr("class", "y axis") | |
.attr("transform","translate("+padding/2+",0)") | |
.call(yAxis) | |
.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", -40) | |
.attr("dy", ".71em") | |
//.style("text-anchor", "end") | |
.attr("x",-h/1.4) | |
.style("font-size",16+"px") | |
.text("Cumulative Number of Wins"); | |
var team = svg.selectAll("g.team") | |
.data(team_dict) | |
.enter() | |
.append("g") | |
.attr("class", "team"); | |
team.append("path") | |
.attr("class", "team line") | |
.attr("d", function(d) { return line(d.values); }) | |
.style("stroke", function(d) { return color(d.name); }); | |
//border for legend | |
//not apart of the g group/legend class because Clemson's orange square disappears when I do that | |
svg.append("rect") | |
.attr("x",padding) | |
.attr("y",-15) | |
.attr("width",200) | |
.attr("height",100) | |
.attr("style","fill-opacity:0;stroke:black;stroke-width:1.5px"); | |
var legend = svg.append("g") | |
.attr("class","legend") | |
.attr("width",200) | |
.attr("height",100); | |
//create elements inside of the legend | |
var gs = legend.selectAll("g.keybox") | |
.data(team_dict).enter().append("g") | |
.attr("class","keybox").attr("width",80).attr("height",15).attr("x",function(d,i){ | |
if(i<4){return 65;} | |
else{return 150;} | |
}) | |
.attr("y",function(d,i){ | |
if(i<4){return i*20;} | |
else{return (i-4) * 20;} | |
}) | |
.attr("id",function(d){ | |
return ""+color(d.name); | |
}); | |
gs.append("text") | |
.attr("class","keybox").attr("x",function(d,i){ | |
if(i<4){return 80;} | |
else{return 163;} | |
}) | |
//alternate boxes between two columns | |
.attr("y",function(d,i){ | |
if(i<4){return i*20 +9;} | |
else{return (i-4)*20 +9;} | |
}) | |
.attr("stroke-width",0) | |
.attr("stroke",function(d){ | |
return color(d.name); | |
}) | |
.text(function(d){ | |
return abbrDict[d.name]; | |
}) | |
.on("mouseover", fade(.1)) | |
.on("mouseout", fade(1)); | |
gs.append("rect") | |
.attr("class","keybox") | |
.attr("x",function(d,i){ | |
if(i<4){return 65;} | |
else{return 150;} | |
}) | |
.attr("y",function(d,i){ | |
if(i<4){return i*20;} | |
else{return (i-4) * 20;} | |
}) | |
.attr("width",10) | |
.attr("height",10) | |
.style("fill",function(d){ | |
return color(d.name); | |
}) | |
.on("mouseover", fade(.1)) | |
.on("mouseout", fade(1)); | |
svg.selectAll("g.keybox").on("mouseover",function(){ | |
var keepName = this.textContent; | |
var id = this.id; | |
var selectedLine_box; | |
var team_color; | |
var team_wins; | |
svg.selectAll("path.team.line").style("stroke", function(d){ | |
if(abbrDict[d.name]!=keepName){ | |
return "#C0C0C0"; | |
} | |
else{ | |
selectedLine_box = d3.select(this); | |
team_color=color(d.name); | |
var last = d.values.length; | |
team_wins = d.values[last-1].wins; | |
return color(d.name); | |
} | |
}); | |
var pathNode = selectedLine_box.node(); | |
var node = selectedLine_box.node(); | |
//console.log(node); | |
var parent = node.parentNode; | |
var grandparent = node.parentNode.parentNode; | |
//console.log(parent); | |
//console.log(grandparent); | |
//console.log(parent.childNodes); | |
grandparent.removeChild(parent); | |
grandparent.appendChild(parent); | |
/* | |
var offset = (.75*w -(w/3))/3; | |
var center = offset+(w/3); | |
var center_label = svg.append("text") | |
.attr("id","center_label") | |
.attr("x",center) | |
.attr("y",h/2) | |
.style("text-anchor","middle") | |
.style("font-size",30+"px") | |
.style("font-family","sans-serif") | |
.text(keepName); | |
var score = svg.append("text") | |
.attr("id","score") | |
.attr("x",center) | |
.attr("y",h/2+40) | |
.style("text-anchor","middle") | |
.style("font-size",35+"px") | |
.text(""+team_wins);*/ | |
}); | |
svg.selectAll("g.keybox").on("mouseout",function(){ | |
d3.select("#tooltip").remove(); | |
d3.select("#center_label").remove(); | |
d3.select("#score").remove(); | |
svg.selectAll("path.team.line").style("stroke",function(d){ | |
return color(d.name); | |
}); | |
svg.selectAll("path.rim").style("opacity", 1); | |
}); | |
svg.selectAll("g.team") | |
.on("mouseover",function(d){ | |
var lineName; | |
var label_color; | |
var team_wins; | |
svg.selectAll("path.team.line").style("stroke","#C0C0C0"); //set all to gray | |
var selectedGroup = d3.select(this); | |
//console.log(this); | |
var selectedLine = selectedGroup.select("path.team.line"); | |
selectedLine.style("stroke",function(d){ //let active keep color | |
lineName = abbrDict[d.name]; //full name to be at end of line | |
label_color=color(d.name); | |
var last = d.values.length; | |
team_wins = d.values[last-1].wins; | |
return color(d.name); | |
}); | |
this.parentNode.appendChild(this); //brings team to front, must select the path's g parent to reorder it | |
var offset = (.75*w -(w/3))/3; | |
//console.log(offset); | |
var center = offset+(w/3); | |
var center_label = svg.append("text") | |
.attr("id","center_label") | |
.attr("x",center-padding) | |
.attr("y",h/2) | |
.style("text-anchor","middle") | |
.style("font-size",30+"px") | |
.style("font-family","sans-serif") | |
.text(lineName); | |
var score = svg.append("text") | |
.attr("id","score") | |
.attr("x",center-padding) | |
.attr("y",h/2+40) | |
.style("text-anchor","middle") | |
.style("font-size",35+"px") | |
.text(""+team_wins); | |
}) | |
.on("mouseout",function(){ | |
d3.select("#tooltip").remove(); | |
d3.select("#center_label").remove(); | |
d3.select("#score").remove(); | |
d3.selectAll("path.team").transition().style("stroke",function(d){ | |
return color(d.name); | |
}); | |
}); | |
//chord code | |
svg.append("g") | |
.attr("class","groups") | |
.attr("transform","translate("+.75*w+","+h/2+")") | |
.selectAll("path") | |
.data(chord.groups) | |
.enter().append("path") | |
.attr("class","rim") | |
.style("fill", function(d) { return chord_fill(d.index); }) | |
.style("stroke", function(d) { return chord_fill(d.index); }) | |
.attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius)) | |
.on("mouseover", fade(.1)) | |
.on("mouseout", fade(1)); | |
var ticks = svg.append("g") | |
.attr("transform","translate("+.75*w+","+h/2+")") | |
.attr("class","ticks") | |
.selectAll("g") | |
.data(chord.groups) | |
.enter().append("g").selectAll("g") | |
.data(groupTicks) | |
.enter().append("g") | |
.attr("transform", function(d) { | |
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" | |
+ "translate(" + outerRadius + ",0)"; | |
}); | |
// Append tick lines | |
ticks.append("line") | |
.attr("x1", 1) | |
.attr("y1", 0) | |
.attr("x2", 5) | |
.attr("y2", 0) | |
.style("stroke", "#000"); | |
// Append tick labels | |
ticks.append("text") | |
.attr("x", 8) | |
.attr("dy", ".35em") | |
.attr("transform", function(d) { return d.angle > Math.PI ? "rotate(180)translate(-16)" : null; }) | |
.style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) | |
.text(function(d) { return d.label; }); | |
// Append chords | |
svg.append("g") | |
.attr("class", "chord") | |
.attr("transform","translate("+.75*w+","+h/2+")") | |
.selectAll("path") | |
.data(chord.chords) | |
.enter().append("path") | |
.attr("class","inner") | |
.attr("d", d3.svg.chord().radius(innerRadius)) | |
.style("fill", function(d) { return d.source.value == d.target.value ? chord_fill(chord_fill.range().length-1) : chord_fill(d.source.index); }) | |
.style("opacity", 1); | |
// Returns an array of tick angles and labels, given a group. | |
function groupTicks(d) { | |
var k = (d.endAngle - d.startAngle) / d.value; | |
return d3.range(0, d.value, 1).map(function(v, i) { | |
return { | |
angle: v * k + d.startAngle, | |
label: i % 5 ? null : v / 1 | |
}; | |
}); | |
} | |
function fade(opacity){ | |
return function(g,i){ | |
var target_team; | |
var goal_index; | |
svg.selectAll(".chord path") | |
.filter(function(d){ | |
console.log(chord_fill(i)); | |
target_team_index = colors.indexOf(chord_fill(i)); | |
goal_index = i; | |
target_team = teams[i]; | |
return d.source.index != i && d.target.index !=i; | |
}) | |
.transition() | |
.style("opacity",opacity); | |
var offset = (.75*w -(w/3))/3; | |
var center = offset+(w/3); | |
if(opacity==.1){ | |
var center_label = svg.append("text") | |
.attr("id","center_label") | |
.attr("x",center) | |
.attr("y",h/2) | |
.style("text-anchor","middle") | |
.style("font-size",30+"px") | |
.style("font-family","sans-serif") | |
.text(target_team); | |
var target_ind = max_scores.indexOf(target_team); | |
console.log(target_ind); | |
var target_wins = max_scores[target_ind+1]; | |
var center_score = svg.append("text") | |
.attr("id","score") | |
.attr("x",center) | |
.attr("y",h/2+40) | |
.style("text-anchor","middle") | |
.style("font-size",35+"px") | |
.text(""+target_wins); | |
} | |
if(opacity==1){ | |
d3.select("#center_label").remove(); | |
d3.select("#score").remove(); | |
} | |
//update scores | |
d3.selectAll(".logo_score") | |
.filter(function(d, j) { return j != i; }) | |
.text(function(d, j) { | |
var target = j < i ? j : j + 1; | |
return matrix[i][target] + "-" + matrix[target][i]; }) | |
.style("opacity", function() { return opacity == 1 ? 0 : 1; }) | |
.style("border-color", function(d, j) { | |
var target = j < i ? j : j + 1; | |
if (matrix[i][target] > matrix[target][i]) return "#090"; | |
else if (matrix[i][target] < matrix[target][i]) return "#930"; | |
else return d3.select("body").style("color"); }); | |
} | |
} | |
} | |
</script> | |
</body> | |
</html> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment