Skip to content

Instantly share code, notes, and snippets.

@avrasgoldman
Last active May 2, 2019 08:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save avrasgoldman/82ccf0788ce17640550e5f5c2d4eb74e to your computer and use it in GitHub Desktop.
Save avrasgoldman/82ccf0788ce17640550e5f5c2d4eb74e to your computer and use it in GitHub Desktop.
how i met my friends
license: mit
We can make this file beautiful and searchable if this error is corrected: No commas found in this CSV file in line 0.
id
me
me.Meetup
me.Meetup.Stan
me.Meetup.Heather
me.Meetup.Baolin
me.Meetup.Ahn
me.Meetup.Nate
me.Meetup.Julien
me.Meetup.Michael S
me.Transportation
me.Transportation.Chris B
me.Transportation.Jessica
me.Craigslist
me.Craigslist.Pierre
me.Craigslist.Y3
me.Craigslist.Y3.Fatima
me.Craigslist.Y3.Becky
me.Craigslist.Y3.Betty
me.Craigslist.Y3.Han Chyi
me.Craigslist.Y3.Hwee
me.Craigslist.Y3.Jeremy
me.Craigslist.Y3.Wafaa
me.Craigslist.Y3.Marie
me.Craigslist.Y3.Jeremy
me.Craigslist.Y3.Wafaa
me.Craigslist.Sam
me.Craigslist.Sam.Sue
me.Craigslist.Andrew
me.Craigslist.Chris L
me.Craigslist.Litia
me.Craigslist.Diana
me.Work
me.Work.Joe
me.Work.Michael N
me.Work.Simrun
me.Work.Stephen
me.Work.Geraldina
me.Work.Patrick
me.Work.Stacy
me.Work.Scott
me.Work.Claudia
me.Work.Claudia.Adriana
me.Work.Claudia.Silvia
me.Work.Claudia.Flavia
me.Work.Claudia.Robson
me.Work.Heni
me.Work.Rebekah
me.Work.Natasha
me.Work.Maria
me.Work.Caitlin
me.Dancing
me.Dancing.Brian
me.Dancing.Brian.Anna L
me.Dancing.Brian.Peter
me.Dancing.Brian.Tamae
me.Dancing.Brian.Charlotte
me.Dancing.Brian.Janet
me.Dancing.Katya
me.Dancing.Sandy
me.Dancing.Sandy.Klay
me.Dancing.Michael T
me.Dancing.Michael T.Ron
me.Dancing.Michael T.Tomer
me.Dancing.Michael T.Camille
me.Dancing.Michael T.David
me.Dancing.Chiara
me.Dancing.Chris Br
me.Dancing.Ricardo
me.Dancing.Weidong
me.Dancing.Soyoung
me.Dancing.Serene
me.Dancing.John Y
me.Dancing.Juliette
me.Dancing.Liz
me.Dancing.John
me.Dancing.Sanj
me.Dancing.Sanj.Claudine W
me.Dancing.Hong
me.Dancing.Mila
me.Dancing.Rob
me.Dancing.Janice
me.Dancing.Mica
me.Dancing.Umeh
me.Dancing.Dmitri
me.Travel
me.Travel.Claudine O
me.Travel.Brenda
me.Travel.Vanya
me.Travel.Vanya.Jade S
me.Travel.Vanya.Jade S.Rachel K
me.Travel.Vanya.Nina
me.Travel.Vanya.Chris A
me.Travel.Mia
me.Travel.Jade B
me.School
me.School.Amy
me.School.Amy.Mandar
me.School.Amy.Josh
me.School.Amy.Josh.Kristen
me.School.Amy.Josh.Kristen.Catherine
me.School.Amy.Josh.Alan
me.School.Amy.Josh.Pam
me.School.Amy.Josh.Matt C
me.School.Amy.Josh.Elaine+Martie
me.School.Erin
me.School.Steph
me.School.Joanne
me.School.Jamie B
me.Dating
me.Dating.Jesse
me.Dating.Jesse.Anna W
me.Dating.James
me.Family
me.Family.Shandoah
me.Family.Shandoah.Sundew
me.Family.Shandoah.Romina
me.Family.Jonah
me.Family.Jonah.Trang
me.Family.Mom
me.Family.Moria
me.Family.Aaron
me.Family.Marjorie
me.Personal Growth
me.Personal Growth.Ben
me.Personal Growth.Ben.Liz M
me.Personal Growth.Alex
me.Personal Growth.Liz Mc
me.Personal Growth.Brittany W
me.Personal Growth.Brittany S
me.Personal Growth.Trent S
me.Personal Growth.Ben.Ken
me.Personal Growth.Rhada
me.Personal Growth.Jasmine
me.Personal Growth.Leszek
me.Personal Growth.Myori
me.Personal Growth.Lukas
me.Personal Growth.Natalie
me.Personal Growth.Paul
me.Personal Growth.Rafael
me.Personal Growth.Diego
me.Personal Growth.Julian
me.Personal Growth.Derek
me.Personal Growth.Hyun
me.Personal Growth.Gabi
me.Personal Growth.Harmony
me.Personal Growth.Rich
me.Personal Growth.Taylor
me.Personal Growth.Andrew
me.Personal Growth.Shannon
me.Facebook
me.Facebook.Avraham
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"/>
<link href='https://fonts.googleapis.com/css?family=Raleway:100,300' rel='stylesheet' type='text/css'>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://rawgit.com/susielu/d3-annotation/master/d3-annotation.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
<style>
body {
background: black;
font-family: raleway;
}
h1 {
color: white;
}
.node circle {
fill: #999;
opacity: 0.8;
}
.node text {
font: 10px sans-serif;
opacity: 0.8;
}
.node--internal circle {
fill: #555;
}
.node--internal text {
}
.link {
fill: none;
stroke: white;
stroke-opacity: 0.8;
stroke-width: 1.5px;
}
.annotation path {
stroke: white;
fill: none;
}
.annotation path
.connector-arrow,
.title text,
.annotation text,
.annotation.callout.circle
.annotation-subject path {
fill: white;
}
.annotation-note-bg {
fill: white;
}
.annotation-note-title {
font-family: Lato;
font-weight: bold;
font-size: 16px;
}
.annotation.xythreshold {
cursor: move;
}
.hidden {
display: none;
}
text.hover {
font-size: .7em;
}
text.title {
font-size: 1.1em;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-xs-12 text-center">
<h1>HOW I MET MY FRIENDS<h1>
</div>
</div>
<div class="row">
<div class="col-xs-12 chart text-center">
</div>
</div>
<br>
</div>
<script>
//set width, height, and append svg
var margin = { top: 20, right: 20, bottom: 20, left: 20};
var width = 960 - margin.left - margin.right; //1200-20-20 = 1160
var height = 900 - margin.top - margin.bottom; //900-20-20 = 860
var fontSize = [24,9,9,9, 9];
var svg = d3.select('.chart')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.attr("transform", "translate(" + -120 + "," + 0 + ")");
//append group element to svg
var g = svg.append("g")
.attr('width', width)
.attr('height', height)
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
//append separate groups for the visualization and the legend to the group element
var gViz = g.append("g")
.attr("class", "vizualization")
.attr("transform", "translate(0, -70)");
var gLegend = g.append("g")
.attr("class", "legend")
.attr('width', width)
.attr('height', height)
.attr("transform", "translate(-1300, -400)");
//create the color scale
var color = d3.scaleOrdinal()
.range(d3.schemePaired
.map(function(d) { c = d3.rgb(d); c.opacity = 0.9; return d; }));
//stratify data and make it into the tree format
var stratify = d3.stratify()
.parentId(function(d) { return d.id.substring(0, d.id.lastIndexOf(".")); });
var tree = d3.tree()
.size([2 * Math.PI, 500])
.separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
//load csv
d3.csv("friends2.csv", function(error, flatData) {
if (error) throw error;
var root = tree(stratify(flatData));
//create links
var link = gViz.selectAll(".link")
.data(root.links())
.enter().append("path")
.attr("class", "link")
.attr("d", d3.linkRadial()
.angle(function(d) { return d.x; })
.radius(function(d) { return d.y; }))
.style("stroke", function(d) {var activity = d.target.id.split(".")[1]; return color(activity); });
//create node placeholders and append data
var node = gViz.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("transform", function(d) {return "translate(" + radialPoint(d.x, d.y) + ")"; });
node.append("circle")
.attr("r", 3)
.style("fill", function(d) {while (d.depth > 1) d = d.parent; return color(d.id.split(".")[1]); });
//append labels to viz
node.append("text")
.attr("dy", "0.31em")
.attr("x", function(d) { return d.x < Math.PI === !d.children ? 6 : -6; })
.attr("text-anchor", function (d){
if(d.height === 0){ return (d.x > Math.PI) ? "end" : "start"; }
else if(d.height === 1) {return d.x < Math.PI === !d.children ? "start" : "end";}
else { return "middle"; } })
.attr("dx", function (d){
if(d.depth === 3){ return (d.x > Math.PI) ? "-2px" : "2px"; }
else { return "0px"; } })
.attr("transform", function(d) { return "rotate(" + textRotation(d) + ")" })
.text(function(d) { if(d.depth != 1) return d.id.substring(d.id.lastIndexOf(".") + 1); })
.attr("font-size", function (d){ return fontSize[d.depth] + "pt"; })
.style("fill", function(d) { while (d.id === 'me') return 'white'; while (d.depth > 1) d = d.parent; return color(d.id.split(".")[1]); })
.classed("glow", function (d){return d.height !== 5; });
//create legend
var legend = gLegend.selectAll("g")
.data(root.children)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + i * 80 + "," + 0 + ")"; });
legend.append("circle")
.attr("cx", width - 20)
.attr("cy", 9.5)
.attr("r", 5)
.style("fill", function(d) {var activity = d.id.split(".")[1]; return color(activity);});
legend.append("text")
.attr("x", width - 10)
.attr("y", 9.5)
.attr("dy", "0.32em")
.attr("font-family", "Raleway")
.attr("font-size", 12)
.attr("text-anchor", "right")
.text(function(d) { return d.id.split(".")[1]; })
.style("fill", function(d) {var activity = d.id.split(".")[1]; return color(activity); });
});
//create the text rotation
function textRotation(d) {
var angle = d.x / Math.PI * 180 + 90;
if (d.depth < 2) { return 0;}
else if (angle <= 270) { return angle - 180;}
else { return angle;}
}
function radialPoint(x, y) {
return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];
}
//annotations
const labels = [
{
data: { Title: "Pierre", Story: "In-between graduate school and starting a full-time job, I started a private chef business and posted an add on Craigslist (circa 2007). Pierre was my first (and one of two) clients. After email exchanges post-meal-pick-up about Tuescany food and a pan “mix up,” he invited me to the symphony.... We eventually became friends." },
x: 123,
y: -157,
dx: 250,
dy: 70,
},
{
data: { Title: "Jessica", Story: "Jessica and I met in the elevator leaving a Meetup. We discovered we lived in the same neighborhood and she offered to share her Lyft with me. During the extra long ride (driver got lost), we chatted; we both love dancing, data, and maps. I then accompanied her on an impromptu scavenge to steal a construction sign across the street from her house. Our friendship was forever solidified." },
x: 105,
y: -169,
dx: 250,
dy: 10
},
{
data: { Title: "Claudine O.", Story: "Claudine O. and I met in Honduras when I was 19. She is the reason I live in California." },
x: -74,
y: 185,
dy: -50,
dx: -250
}].map(function (l) {l.note = Object.assign({},
l.note, { title: "" + l.data.Title, label: "" + l.data.Story });
l.subject = { radius: 6 };
return l;
});
window.makeAnnotations = d3.annotation()
.annotations(labels)
.type(d3.annotationCalloutCircle)
.on('subjectover', function (annotation) { annotation.type.a.selectAll("g.annotation-connector, g.annotation-note")
.classed("hidden", false); })
.on('subjectout', function (annotation) { annotation.type.a.selectAll("g.annotation-connector, g.annotation-note")
.classed("hidden", true); });
gViz.append("g")
.attr("class", "annotation-test")
.call(makeAnnotations);
gViz.selectAll("g.annotation-connector, g.annotation-note")
.classed("hidden", true);
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment