Skip to content

Instantly share code, notes, and snippets.

@e9t
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save e9t/cbc6dbdf5bb4fd1e4997 to your computer and use it in GitHub Desktop.
Save e9t/cbc6dbdf5bb4fd1e4997 to your computer and use it in GitHub Desktop.
데이터 사이언스 벤 다이어그램
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js" type="text/javascript"></script>
<link href="style.css" rel="stylesheet" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
</head>
<body>
<div id="venn"></div>
<script src="venn.min.js"></script>
<script>
// define sets and set set intersections
var sets = [ {sets: ['A'], size: 40, label: '해킹 실력'},
{sets: ['B'], size: 40, label: '수학 및 통계에 대한 지식'},
{sets: ['C'], size: 40, label: '도메인 전문성'},
{sets: ['A','B'], size: 8, label: '기계학습'},
{sets: ['A','C'], size: 8, label: '위험구역!'},
{sets: ['C','B'], size: 8, label: '전통적 학문'},
{sets: ['A','B','C'], size: 30, label: '데이터 사이언스'}
];
var chart = venn.VennDiagram()
.width(700)
.height(500)
.fontSize(20);
d3.select("#venn").datum(sets).call(chart);
</script>
</body>
</html>
var venn=venn||{};!function(a){"use strict";function b(b,c,d){var e,f,g=c[0].radius-a.distance(c[0],b);for(e=1;e<c.length;++e)f=c[e].radius-a.distance(c[e],b),g>=f&&(g=f);for(e=0;e<d.length;++e)f=a.distance(d[e],b)-d[e].radius,g>=f&&(g=f);return g}function c(c,d){var e,f=[];for(e=0;e<c.length;++e){var g=c[e];f.push({x:g.x,y:g.y}),f.push({x:g.x+g.radius/2,y:g.y}),f.push({x:g.x-g.radius/2,y:g.y}),f.push({x:g.x,y:g.y+g.radius/2}),f.push({x:g.x,y:g.y-g.radius/2})}var h=f[0],i=b(f[0],c,d);for(e=1;e<f.length;++e){var j=b(f[e],c,d);j>=i&&(h=f[e],i=j)}var k=a.fmin(function(a){return-1*b({x:a[0],y:a[1]},c,d)},[h.x,h.y],{maxIterations:500,minErrorDelta:1e-10}).solution,l={x:k[0],y:k[1]},m=!0;for(e=0;e<c.length;++e)if(a.distance(l,c[e])>c[e].radius){m=!1;break}for(e=0;e<d.length;++e)if(a.distance(l,d[e])<d[e].radius){m=!1;break}if(!m)if(1==c.length)l={x:c[0].x,y:c[0].y};else{var n={};a.intersectionArea(c,n),l=0===n.arcs.length?{x:0,y:-1e3,disjoint:!0}:a.getCenter(n.arcs.map(function(a){return a.p1}))}return l}function d(a,b){for(var d={},e=0;e<b.length;++e){for(var f=b[e].sets,g={},h=0;h<f.length;++h)g[f[h]]=!0;var i=[],j=[];for(var k in a)k in g?i.push(a[k]):j.push(a[k]);var l=c(i,j);d[f]=l,l.disjoint&&b[e].size>0&&console.log("WARNING: area "+f+" not represented on screen")}return d}a.VennDiagram=function(){function b(b){b.each(function(b){var l=a.scaleSolution(k(b),e,f,g),m=d(l,b),n=d3.select(this).selectAll("svg").data([l]);n.enter().append("svg"),n.attr("width",e).attr("height",f);var o={},p=!1;n.selectAll("g").each(function(b){var c=d3.select(this).select("path").attr("d");1==b.sets.length&&c&&(p=!0,o[b.sets[0]]=a.circleFromPath(c))});var q=function(b){return function(c){var d=b.sets.map(function(a){var b=o[a],d=l[a];return b||(b={x:e/2,y:f/2,radius:1}),d||(d={x:e/2,y:f/2,radius:1}),{x:b.x*(1-c)+d.x*c,y:b.y*(1-c)+d.y*c,radius:b.radius*(1-c)+d.radius*c}});return a.intersectionAreaPath(d)}},r=n.selectAll("g").data(b,function(a){return a.sets}),s=r.enter().append("g").attr("class",function(a){return"venn-area venn-"+(1==a.sets.length?"circle":"intersection")+(" venn-sets-"+a.sets.join("_"))});s.append("path").style("fill-opacity","0").filter(function(a){return 1==a.sets.length}).style("fill",function(a){return j(c(a))}).style("fill-opacity",".25");var t=s.append("text").style("fill",function(a){return 1==a.sets.length?j(c(a)):"#444"}).text(function(a){return c(a)}).attr("text-anchor","middle").attr("dy",".35em").attr("x",e/2).attr("y",f/2),u=r.transition("venn").duration(p?h:0);u.select("path").attrTween("d",q);var v=u.select("text").text(function(a){return c(a)}).each("end",a.wrapText(l,c)).attr("x",function(a){return Math.floor(m[a.sets].x)}).attr("y",function(a){return Math.floor(m[a.sets].y)});null!==i&&(t.style("font-size","0px"),v.style("font-size",i));var w=r.exit().transition("venn").duration(h).remove();w.select("path").attrTween("d",q),w.select("text").text(function(a){return c(a)}).attr("x",e/2).attr("y",f/2).style("font-size","0px")})}function c(a){return a.label?a.label:1==a.sets.length?""+a.sets[0]:void 0}var e=600,f=350,g=15,h=1e3,i=null,j=d3.scale.category10(),k=a.venn;return b.width=function(a){return arguments.length?(e=a,b):e},b.height=function(a){return arguments.length?(f=a,b):f},b.padding=function(a){return arguments.length?(g=a,b):g},b.colours=function(a){return arguments.length?(j=a,b):j},b.fontSize=function(a){return arguments.length?(i=a,b):i},b.duration=function(a){return arguments.length?(h=a,b):h},b.layoutFunction=function(a){return arguments.length?(k=a,b):k},b},a.wrapText=function(a,b){return function(){for(var c,d=d3.select(this),e=d.datum(),f=a[e.sets[0]].radius||50,g=b(e)||"",h=g.split(/\s+/).reverse(),i=3,j=(g.length+h.length)/i,k=h.pop(),l=[k],m=0,n=1.1,o=d.text(null).append("tspan").text(k);;){if(k=h.pop(),!k)break;l.push(k),c=l.join(" "),o.text(c),c.length>j&&o.node().getComputedTextLength()>f&&(l.pop(),o.text(l.join(" ")),l=[k],o=d.append("tspan").text(k),m++)}var p=.35-m*n/2,q=d.attr("x"),r=d.attr("y");d.selectAll("tspan").attr("x",q).attr("y",r).attr("dy",function(a,b){return p+b*n+"em"})}},a.computeTextCentre=c,a.computeTextCentres=d,a.sortAreas=function(a,b){a.selectAll("g").sort(function(a,c){return a.sets.length!=c.sets.length?a.sets.length-c.sets.length:a==b||c==b?a==b?1:-1:c.size-a.size})},a.circlePath=function(a,b,c){var d=[];return d.push("\nM",a,b),d.push("\nm",-c,0),d.push("\na",c,c,0,1,0,2*c,0),d.push("\na",c,c,0,1,0,2*-c,0),d.join(" ")},a.circleFromPath=function(a){var b=a.split(" ");return{x:parseFloat(b[1]),y:parseFloat(b[2]),radius:-parseFloat(b[4])}},a.intersectionAreaPath=function(b){var c={};a.intersectionArea(b,c);var d=c.arcs;if(0===d.length)return"M 0 0";if(1==d.length){var e=d[0].circle;return a.circlePath(e.x,e.y,e.radius)}for(var f=["\nM",d[0].p2.x,d[0].p2.y],g=0;g<d.length;++g){var h=d[g],i=h.circle.radius,j=h.width>i;f.push("\nA",i,i,0,j?1:0,1,h.p1.x,h.p1.y)}return f.join(" ")}}(venn),function(a){"use strict";a.venn=function(b,c){c=c||{},c.maxIterations=c.maxIterations||500;var d,e=c.lossFunction||a.lossFunction,f=c.initialLayout||a.greedyLayout,g=c.fmin||a.fmin,h=f(b),i=[],j=[];for(d in h)h.hasOwnProperty(d)&&(i.push(h[d].x),i.push(h[d].y),j.push(d));for(var k=0,l=g(function(a){k+=1;for(var c={},d=0;d<j.length;++d){var f=j[d];c[f]={x:a[2*d],y:a[2*d+1],radius:h[f].radius}}return e(c,b)},i,c),m=l.solution,n=0;n<j.length;++n)d=j[n],h[d].x=m[2*n],h[d].y=m[2*n+1];return h};var b=1e-10;a.distanceFromIntersectArea=function(c,d,e){return Math.min(c,d)*Math.min(c,d)*Math.PI<=e+b?Math.abs(c-d):a.bisect(function(b){return a.circleOverlap(c,d,b)-e},0,c+d)},a.getDistanceMatrix=function(b,c,d){for(var e=[],f=0;f<c.length;++f){e.push([]);for(var g=0;g<c.length;++g)e[f].push(0)}for(f=0;f<b.length;++f){var h=b[f];if(2===h.sets.length){var i=d[h.sets[0]],j=d[h.sets[1]],k=Math.sqrt(c[i].size/Math.PI),l=Math.sqrt(c[j].size/Math.PI),m=a.distanceFromIntersectArea(k,l,h.size);e[i][j]=e[j][i]=m}}return e},a.greedyLayout=function(c){function d(a,b){return b.size-a.size}function e(a){return a.set in r}function f(a,b){h[b].x=a.x,h[b].y=a.y,r[b]=!0}for(var g,h={},i={},j=0;j<c.length;++j){var k=c[j];1==k.sets.length&&(g=k.sets[0],h[g]={x:1e10,y:1e10,rowid:h.length,size:k.size,radius:Math.sqrt(k.size/Math.PI)},i[g]=[])}for(c=c.filter(function(a){return 2==a.sets.length}),j=0;j<c.length;++j){var l=c[j],m=l.hasOwnProperty("weight")?l.weight:1,n=l.sets[0],o=l.sets[1];l.size+b>=Math.min(h[n].size,h[o].size)&&(m=0),i[n].push({set:o,size:l.size,weight:m}),i[o].push({set:n,size:l.size,weight:m})}var p=[];for(g in i)if(i.hasOwnProperty(g)){var q=0;for(j=0;j<i[g].length;++j)q+=i[g][j].size*i[g][j].weight;p.push({set:g,size:q})}p.sort(d);var r={};for(f({x:0,y:0},p[0].set),j=1;j<p.length;++j){var s=p[j].set,t=i[s].filter(e);if(g=h[s],t.sort(d),0===t.length)throw"Need overlap information for set "+JSON.stringify(g);for(var u=[],v=0;v<t.length;++v){var w=h[t[v].set],x=a.distanceFromIntersectArea(g.radius,w.radius,t[v].size);u.push({x:w.x+x,y:w.y}),u.push({x:w.x-x,y:w.y}),u.push({y:w.y+x,x:w.x}),u.push({y:w.y-x,x:w.x});for(var y=v+1;y<t.length;++y)for(var z=h[t[y].set],A=a.distanceFromIntersectArea(g.radius,z.radius,t[y].size),B=a.circleCircleIntersection({x:w.x,y:w.y,radius:x},{x:z.x,y:z.y,radius:A}),C=0;C<B.length;++C)u.push(B[C])}var D=1e50,E=u[0];for(v=0;v<u.length;++v){h[s].x=u[v].x,h[s].y=u[v].y;var F=a.lossFunction(h,c);D>F&&(D=F,E=u[v])}f(E,s)}return h},a.classicMDSLayout=function(b){for(var c=[],d={},e=0;e<b.length;++e){var f=b[e];1==f.sets.length&&(d[f.sets[0]]=c.length,c.push(f))}var g=a.getDistanceMatrix(b,c,d),h=mds.classic(g),i={};for(e=0;e<c.length;++e){var j=c[e];i[j.sets[0]]={x:h[e][0],y:h[e][1],radius:Math.sqrt(j.size/Math.PI)}}return i},a.lossFunction=function(b,c){function d(a){return a.map(function(a){return b[a]})}for(var e=0,f=0;f<c.length;++f){var g,h=c[f];if(1!=h.sets.length){if(2==h.sets.length){var i=b[h.sets[0]],j=b[h.sets[1]];g=a.circleOverlap(i.radius,j.radius,a.distance(i,j))}else g=a.intersectionArea(d(h.sets));var k=h.hasOwnProperty("weight")?h.weight:1;e+=k*(g-h.size)*(g-h.size)}}return e},a.scaleSolution=function(a,b,c,d){var e=[],f=[];for(var g in a)a.hasOwnProperty(g)&&(f.push(g),e.push(a[g]));var h=function(a){var b=Math.max.apply(null,e.map(function(b){return b[a]+b.radius})),c=Math.min.apply(null,e.map(function(b){return b[a]-b.radius}));return{max:b,min:c}};b-=2*d,c-=2*d;for(var i=h("x"),j=h("y"),k=b/(i.max-i.min),l=c/(j.max-j.min),m=Math.min(l,k),n=(b-(i.max-i.min)*m)/2,o=(c-(j.max-j.min)*m)/2,p={},q=0;q<e.length;++q){var r=e[q];p[f[q]]={radius:m*r.radius,x:d+n+(r.x-i.min)*m,y:d+o+(r.y-j.min)*m}}return p}}(venn),function(a){"use strict";function b(a,b,c,d,e){for(var f=0;f<a.length;++f)a[f]=b*c[f]+d*e[f]}a.bisect=function(a,b,c,d){d=d||{};var e=d.maxIterations||100,f=d.tolerance||1e-10,g=a(b),h=a(c),i=c-b;if(g*h>0)throw"Initial bisect points must have opposite signs";if(0===g)return b;if(0===h)return c;for(var j=0;e>j;++j){i/=2;var k=b+i,l=a(k);if(l*g>=0&&(b=k),Math.abs(i)<f||0===l)return k}return b+i},a.fmin=function(a,c,d){d=d||{};var e,f=d.maxIterations||200*c.length,g=d.nonZeroDelta||1.1,h=d.zeroDelta||.001,i=d.minErrorDelta||1e-6,j=d.rho||1,k=d.chi||2,l=d.psi||-.5,m=d.sigma||.5,n=d.callback,o=c.length,p=new Array(o+1);p[0]=c,p[0].fx=a(c);for(var q=0;o>q;++q){var r=c.slice();r[q]=r[q]?r[q]*g:h,p[q+1]=r,p[q+1].fx=a(r)}for(var s=function(a,b){return a.fx-b.fx},t=c.slice(),u=c.slice(),v=c.slice(),w=c.slice(),x=0;f>x&&(p.sort(s),n&&n(p),!(Math.abs(p[0].fx-p[o].fx)<i));++x){for(q=0;o>q;++q){t[q]=0;for(var y=0;o>y;++y)t[q]+=p[y][q];t[q]/=o}var z=p[o];if(b(u,1+j,t,-j,z),u.fx=a(u),u.fx<=p[0].fx)b(w,1+k,t,-k,z),w.fx=a(w),w.fx<u.fx?(e=p[o],p[o]=w,w=e):(e=p[o],p[o]=u,u=e);else if(u.fx>=p[o-1].fx){var A=!1;if(u.fx<=z.fx?(b(v,1+l,t,-l,z),v.fx=a(v),v.fx<z.fx?(e=p[o],p[o]=v,v=e):A=!0):(b(v,1-l*j,t,l*j,z),v.fx=a(v),v.fx<=u.fx?(e=p[o],p[o]=v,v=e):A=!0),A)for(q=1;q<p.length;++q)b(p[q],1-m,p[0],m-1,p[q]),p[q].fx=a(p[q])}else e=p[o],p[o]=u,u=e}return p.sort(s),{f:p[0].fx,solution:p[0]}}}(venn),function(a){"use strict";function b(b){for(var c=[],d=0;d<b.length;++d)for(var e=d+1;e<b.length;++e)for(var f=a.circleCircleIntersection(b[d],b[e]),g=0;g<f.length;++g){var h=f[g];h.parentIndex=[d,e],c.push(h)}return c}var c=1e-10;a.intersectionArea=function(d,e){var f,g=b(d),h=g.filter(function(b){return a.containedInCircles(b,d)}),i=0,j=0,k=[];if(h.length>1){var l=a.getCenter(h);for(f=0;f<h.length;++f){var m=h[f];m.angle=Math.atan2(m.x-l.x,m.y-l.y)}h.sort(function(a,b){return b.angle-a.angle});var n=h[h.length-1];for(f=0;f<h.length;++f){var o=h[f];j+=(n.x+o.x)*(o.y-n.y);for(var p={x:(o.x+n.x)/2,y:(o.y+n.y)/2},q=null,r=0;r<o.parentIndex.length;++r)if(n.parentIndex.indexOf(o.parentIndex[r])>-1){var s=d[o.parentIndex[r]],t=Math.atan2(o.x-s.x,o.y-s.y),u=Math.atan2(n.x-s.x,n.y-s.y),v=u-t;0>v&&(v+=2*Math.PI);var w=u-v/2,x=a.distance(p,{x:s.x+s.radius*Math.sin(w),y:s.y+s.radius*Math.cos(w)});(null===q||q.width>x)&&(q={circle:s,width:x,p1:o,p2:n})}k.push(q),i+=a.circleArea(q.circle.radius,q.width),n=o}}else{var y=d[0];for(f=1;f<d.length;++f)d[f].radius<y.radius&&(y=d[f]);var z=!1;for(f=0;f<d.length;++f)if(a.distance(d[f],y)>Math.abs(y.radius-d[f].radius)){z=!0;break}z?i=j=0:(i=y.radius*y.radius*Math.PI,k.push({circle:y,p1:{x:y.x,y:y.y+y.radius},p2:{x:y.x-c,y:y.y+y.radius},width:2*y.radius}))}return j/=2,e&&(e.area=i+j,e.arcArea=i,e.polygonArea=j,e.arcs=k,e.innerPoints=h,e.intersectionPoints=g),i+j},a.containedInCircles=function(b,d){for(var e=0;e<d.length;++e)if(a.distance(b,d[e])>d[e].radius+c)return!1;return!0},a.circleIntegral=function(a,b){var c=Math.sqrt(a*a-b*b);return b*c+a*a*Math.atan2(b,c)},a.circleArea=function(b,c){return a.circleIntegral(b,c-b)-a.circleIntegral(b,-b)},a.distance=function(a,b){return Math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))},a.circleOverlap=function(b,c,d){if(d>=b+c)return 0;if(d<=Math.abs(b-c))return Math.PI*Math.min(b,c)*Math.min(b,c);var e=b-(d*d-c*c+b*b)/(2*d),f=c-(d*d-b*b+c*c)/(2*d);return a.circleArea(b,e)+a.circleArea(c,f)},a.circleCircleIntersection=function(b,c){var d=a.distance(b,c),e=b.radius,f=c.radius;if(d>=e+f||d<=Math.abs(e-f))return[];var g=(e*e-f*f+d*d)/(2*d),h=Math.sqrt(e*e-g*g),i=b.x+g*(c.x-b.x)/d,j=b.y+g*(c.y-b.y)/d,k=-(c.y-b.y)*(h/d),l=-(c.x-b.x)*(h/d);return[{x:i+k,y:j-l},{x:i-k,y:j+l}]},a.getCenter=function(a){for(var b={x:0,y:0},c=0;c<a.length;++c)b.x+=a[c].x,b.y+=a[c].y;return b.x/=a.length,b.y/=a.length,b}}(venn),function(a){"undefined"==typeof module||"undefined"==typeof module.exports?window.venn=a:module.exports=a}(venn);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment