Advertisement
Guest User

Untitled

a guest
Apr 21st, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.18 KB | None | 0 0
  1. /////////////////////////////////////
  2. ///reusable code starts here
  3. ////////////////////////////////////
  4.  
  5. var Scatter_Plot = function(opt) {
  6. this.data = opt.data;
  7. this.element = opt.element;
  8. this.orientation = opt.orientation;
  9. this.width = opt.width;
  10. this.height = opt.height;
  11. this.r = opt.circleRadius;
  12. this.padding = opt.padding;
  13. this.speed = opt.speed;
  14. this.optionalColorPalette = opt.colorPalette;
  15. this.xTicksNum = opt.xTicksNum;
  16. this.yTicksNum = opt.yTicksNum;
  17. this.barPaddingInner = opt.barPaddingInner;
  18. this.fontSize = opt.fontSize;
  19. this.draw();
  20. };
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27. Scatter_Plot.prototype.draw = function() {
  28. this.padding = 50;
  29.  
  30. var svg = d3.select(this.element).append('svg')
  31. .attr("padding",this.padding)
  32. .attr('viewBox',"0 0 "+this.width+" "+this.height)
  33. .attr("preserveAspectRatio","xMinYMin")
  34.  
  35. this.plot = svg.append('g')
  36. .attr('class', 'Scatter_Plot_holder')
  37. .attr('transform', "translate(" + this.padding + "," + this.padding + ")");
  38.  
  39. this.generateData();
  40. this.generateXScale();
  41. this.generateYScale();
  42. this.generateColorScale();
  43. this.addAxis();
  44. this.generateButtons();
  45. this.generateCircles();
  46. this.addReferenceLines();
  47.  
  48. };
  49.  
  50. Scatter_Plot.prototype.generateXScale = function() {
  51. if(this.orientation=='vertical'){
  52. this.xScale = d3.scaleLinear()
  53. .domain([0,d3.max(this.data,function(d) {
  54. return d.x;
  55. })*1.2])
  56. .range([0, this.width - 2 * this.padding])
  57. }else if (this.orientation=='horizontal'){
  58. this.xScale = d3.scaleLinear()
  59. .domain([0,d3.max(this.data,function(d){
  60. return d.y;
  61. })*1.2])
  62. .range([0, this.width - 2 * this.padding])
  63. };
  64.  
  65. this.xAxis = d3.axisBottom().ticks(this.xTicksNum).scale(this.xScale);
  66. };
  67.  
  68. Scatter_Plot.prototype.generateYScale = function() {
  69. if(this.orientation =='vertical'){
  70. this.yScale = d3.scaleLinear()
  71. .domain([0, d3.max(this.data, function(d) {
  72. return d.y ;
  73. }) * 1.2])
  74. .range([this.height - 2 * this.padding, 0])
  75. }else if(this.orientation=='horizontal'){
  76. this.yScale = d3.scaleLinear()
  77. .domain(this.data.map(function(d) {
  78. return d.x;
  79. }))
  80. .range([this.height - 2 * this.padding, 0])
  81. .paddingInner(this.barPaddingInner);
  82. }
  83. this.yAxis = d3.axisLeft().ticks(this.yTicksNum).scale(this.yScale);
  84. };
  85.  
  86. Scatter_Plot.prototype.generateColorScale = function() {
  87.  
  88. var that=this;
  89.  
  90. this.colorPalette = [
  91. {
  92. "key":1,
  93. "color": "#1f77b4"
  94. },
  95. {
  96. "key":2,
  97. "color": "#ff7f0e"
  98. },
  99. {
  100. "key":3,
  101. "color": "#2ca02c"
  102. },
  103. {
  104. "key":4,
  105. "color": "#9467bd"
  106. },
  107. {
  108. "key":5,
  109. "color": "#8c564b"
  110. },
  111. {
  112. "key":6,
  113. "color": "#e377c2"
  114. },
  115. {
  116. "key":7,
  117. "color": "#7f7f7f"
  118. },
  119. {
  120. "key":8,
  121. "color": "#bcbd22"
  122. },
  123. {
  124. "key":9,
  125. "color": "#17becf"
  126. }
  127. ];
  128.  
  129. this.optionalColorPalette.map(function(d){
  130. var curKey = d.key;
  131. var curColor = d.color;
  132.  
  133. that.colorPalette.map(function(d){
  134. if(d.key == curKey){
  135. d.color = curColor;
  136. }
  137. }
  138. )
  139.  
  140. });
  141.  
  142.  
  143.  
  144. this.colorScale = d3.scaleOrdinal()
  145. .domain(this.data.map(function(d) {
  146. return d.x;
  147. }))
  148. .range(this.colorPalette.map(function(d) {
  149. return d.color;
  150. }));
  151.  
  152. }
  153.  
  154.  
  155. Scatter_Plot.prototype.addAxis = function() {
  156. this.plot.append("g")
  157. .attr("id", "x-axisGroup")
  158. .attr("class", "x-axis")
  159. .attr("transform", "translate(" + "0" + "," + (this.height - 2 * this.padding) + ")");
  160.  
  161. this.plot.select(".x-axis")
  162. .transition()
  163. .duration(1000)
  164. .call(this.xAxis)
  165.  
  166. this.plot.append("g")
  167. .attr("id", "y-axisGroup")
  168. .attr("class", "y-axis")
  169. .attr("transform", "translate(0,0)");
  170.  
  171. this.plot.select(".y-axis")
  172. .transition()
  173. .duration(1000)
  174. .call(this.yAxis)
  175.  
  176. }
  177.  
  178. Scatter_Plot.prototype.updateAxis = function() {
  179. this.plot.select(".x-axis")
  180. .transition()
  181. .duration(1000)
  182. .call(this.xAxis)
  183.  
  184. this.plot.select(".y-axis")
  185. .transition()
  186. .duration(1000)
  187. .call(this.yAxis)
  188.  
  189. }
  190.  
  191.  
  192. Scatter_Plot.prototype.generateCircles = function() {
  193.  
  194. if(this.orientation == 'vertical'){
  195. var that = this;
  196.  
  197. var rect = this.plot.selectAll(".chartCircle")
  198. .data(this.data,function(d){return d.x});
  199.  
  200. //remove any elements that don't have data
  201. rect.exit().remove();
  202.  
  203. //update elements that do have Data
  204. rect
  205. .transition().duration(this.speed)
  206. .attr("cx", function(d) {
  207. return that.xScale(d.x);
  208. })
  209. .attr("cy", function(d) {
  210. return that.yScale(d.y);
  211. })
  212. .attr("r",this.r)
  213.  
  214. //create new elements for data that is new
  215. rect.enter().append("circle")
  216. .attr("class","chartCircle")
  217. .attr("cx", function(d) {
  218. return that.xScale(d.x);
  219. })
  220. .attr("cy", function(d){
  221. return that.yScale(d.y);
  222. })
  223. .on("mouseover", function(d) {
  224. that.showToolTip(d)
  225. })
  226. .on("mouseout", function(d) {
  227. that.hideToolTip(d)
  228. })
  229. .transition().duration(this.speed) // start at "y=0" then transition to the top of the grpah while the height increases
  230. .attr("cx", function(d) {
  231. return that.xScale(d.x)
  232. })
  233. .attr("cy", function(d) {
  234. return that.yScale(d.y)
  235. })
  236. .attr("r", this.r)
  237. .attr("fill", function(d) {
  238. return that.colorScale(d.x)
  239. });
  240.  
  241.  
  242. }else if (this.orientation =='horizontal'){
  243. var that = this;
  244.  
  245. var rect = this.plot.selectAll("rect")
  246. .data(this.data,function(d){return d.x});
  247.  
  248. //remove any elements that don't have data
  249. rect.exit().remove();
  250.  
  251. //update elements that do have Data
  252. rect
  253. .transition().duration(this.speed)
  254. .attr("x", 1)
  255. .attr("y", function(d) {
  256. return that.yScale(d.x)
  257. })
  258. .attr("height",this.yScale.bandwidth())
  259. .attr("width", function(d){
  260. return that.xScale(d.y);
  261. })
  262.  
  263. //create new elements for data that is new
  264. rect.enter().append("rect")
  265. .attr("x", 1)
  266. .attr("y", function(d) {
  267. return that.yScale(d.x) + 5
  268. })
  269. .attr("height",this.yScale.bandwidth())
  270. .on("mouseover", function(d) {
  271. that.showToolTip(d)
  272. })
  273. .on("mouseout", function(d) {
  274. that.hideToolTip(d)
  275. })
  276. .transition().duration(this.speed) // start at "y=0" then transition to the top of the grpah while the height increases
  277. .attr("y", function(d) {
  278. return that.yScale(d.x)
  279. })
  280. .attr("height",this.yScale.bandwidth())
  281. .attr("width", function(d) {
  282. return that.xScale(d.y) ;
  283. })
  284. .attr("fill", function(d) {
  285. return that.colorScale(d.x)
  286. });
  287.  
  288. }
  289.  
  290. };
  291.  
  292. Scatter_Plot.prototype.calculateDataParameters = function(){
  293. if(this.orientation == 'vertical'){
  294.  
  295. this.avgX = d3.mean(this.data,function(d){return d.x});
  296. this.maxY = d3.max(this.data,function(d){return d.y})*1.2;
  297. this.avgY = d3.mean(this.data,function(d){return d.y});
  298. this.maxX = d3.max(this.data,function(d){return d.x});
  299. this.minX = d3.min(this.data,function(d){return d.x});
  300.  
  301. };
  302.  
  303. this.xRefLineData = [
  304. {x:this.avgX,
  305. y:0
  306. },
  307. {x:this.avgX,
  308. y:this.maxY
  309. },
  310. ];
  311.  
  312. this.yRefLineData = [
  313. {x:0,
  314. y:this.avgY
  315. },
  316. {x:this.maxX*1.2,
  317. y:this.avgY
  318. },
  319. ];
  320.  
  321.  
  322.  
  323. };
  324.  
  325. Scatter_Plot.prototype.addReferenceLines = function(){
  326.  
  327. this.calculateDataParameters();
  328.  
  329. if(this.orientation == 'vertical'){
  330. var that = this;
  331.  
  332. var refLineGenerator = d3.line()
  333. .x(function(d){
  334. return that.xScale(d.x)
  335. })
  336. .y(function(d){
  337. return that.yScale(d.y)
  338. });
  339.  
  340.  
  341. this.plot
  342. .append("path")
  343. .attr("d",refLineGenerator(this.xRefLineData))
  344. .attr("id","xRefLine")
  345. .attr("stroke","#a7a7a7")
  346. .attr("stroke-width","1px");
  347.  
  348.  
  349. this.plot
  350. .append("path")
  351. .attr("d",refLineGenerator(this.yRefLineData))
  352. .attr("id","yRefLine")
  353. .attr("stroke","#a7a7a7")
  354. .attr("stroke-width","1px");
  355.  
  356. };
  357.  
  358. };
  359.  
  360. Scatter_Plot.prototype.updateReferenceLines = function(){
  361.  
  362. this.calculateDataParameters();
  363.  
  364. if(this.orientation == 'vertical'){
  365.  
  366. var that=this;
  367.  
  368. var refLineGenerator = d3.line()
  369. .x(function(d){
  370. return that.xScale(d.x)
  371. })
  372. .y(function(d){
  373. return that.yScale(d.y)
  374. });
  375.  
  376. this.plot.selectAll("#xRefLine")
  377. .transition()
  378. .duration(this.speed)
  379. .attr("d",refLineGenerator(this.xRefLineData));
  380.  
  381.  
  382. this.plot.selectAll("#yRefLine")
  383. .transition()
  384. .duration(this.speed)
  385. .attr("d",refLineGenerator(this.yRefLineData));
  386.  
  387. };
  388.  
  389. Scatter_Plot.prototype.addKMeansClusters = function(){
  390.  
  391. var that = this;
  392. this.k_means = new K_Means(this.data,5);
  393. this.clusterData = this.k_means.centroidList;
  394.  
  395. this.plot.selectAll(".clusterCircle")
  396. .data(this.clusterData)
  397. .enter()
  398. .append("circle")
  399. .attr("class","clusterCircle")
  400. .attr("cx",function(d){return that.xScale(d.x);})
  401. .attr("cy",function(d){return that.yScale(d.y);})
  402. .attr("r",3)
  403. .attr("fill","Purple")
  404.  
  405. };
  406.  
  407.  
  408. };
  409.  
  410. Scatter_Plot.prototype.greyColors = function(){
  411.  
  412. this.plot.selectAll(".chartCircle")
  413. .transition()
  414. .duration(100)
  415. .attr("fill","#a7a7a7")
  416. };
  417.  
  418. Scatter_Plot.prototype.updateColors = function(){
  419.  
  420. var that=this;
  421.  
  422. this.plot.selectAll(".chartCircle")
  423. .transition()
  424. .duration(100)
  425. .attr("fill",function(d){
  426. var key = d.cluster+1
  427. return that.colorScale(key);
  428.  
  429. });
  430.  
  431.  
  432. this.plot.selectAll(".clusterCircle")
  433. .transition()
  434. .duration(100)
  435. .attr("cx",function(d){return that.xScale(d.x);})
  436. .attr("cy",function(d){return that.yScale(d.y);})
  437. .attr("r",5)
  438. .attr("fill","#000");
  439.  
  440. };
  441.  
  442.  
  443.  
  444. Scatter_Plot.prototype.updateBars = function() {
  445. this.generateXScale();
  446. this.generateYScale();
  447. this.generateColorScale();
  448. this.updateAxis();
  449. this.generateCircles();
  450. this.updateReferenceLines();
  451.  
  452. };
  453.  
  454. Scatter_Plot.prototype.boxMuller = function(mu,sigma,u1){
  455. //var u1 = Math.random();
  456. var u2 = Math.random();
  457.  
  458. var z0 = Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(Math.PI*2 * u2);
  459. //var z1 = Math.sqrt(-2.0 * Math.log(u1)) * Math.sin(Math.PI*2 * u2);
  460.  
  461. return z0 * sigma + mu
  462.  
  463. }
  464.  
  465. Scatter_Plot.prototype.generateData = function(){
  466.  
  467. this.center1 = {
  468. x:10,
  469. y:20,
  470. mu:1,
  471. sigma:1
  472. };
  473.  
  474. this.center2 = {
  475. x:10,
  476. y:10,
  477. mu:2,
  478. sigma:3
  479. };
  480.  
  481. this.center3 = {
  482. x:4,
  483. y:7,
  484. mu:3,
  485. sigma:2
  486. };
  487.  
  488.  
  489. this.data.push(this.center1,this.center2,this.center3);
  490.  
  491. };
  492.  
  493. Scatter_Plot.prototype.updateData = function() {
  494.  
  495.  
  496. for(i=0;i<=20;i++){
  497. var u1 = Math.random();
  498.  
  499. var newEntry = {
  500. x: this.center1.x + this.boxMuller(this.center1.mu,this.center1.sigma,u1),
  501. y: this.center1.y + this.boxMuller(this.center1.mu,this.center1.sigma,u1)
  502. };
  503.  
  504. this.data.push(newEntry);
  505.  
  506. var newEntry1 = {
  507. x: this.center2.x + this.boxMuller(this.center2.mu,this.center2.sigma,u1),
  508. y: this.center2.y + this.boxMuller(this.center2.mu,this.center2.sigma,u1)
  509. };
  510.  
  511. this.data.push(newEntry1);
  512.  
  513. var newEntry2 = {
  514. x: this.center3.x + this.boxMuller(this.center3.mu,this.center3.sigma,u1),
  515. y: this.center3.y + this.boxMuller(this.center3.mu,this.center3.sigma,u1)
  516. };
  517.  
  518. this.data.push(newEntry2);
  519.  
  520. };
  521.  
  522. this.updateBars();
  523.  
  524.  
  525. };
  526.  
  527. Scatter_Plot.prototype.showToolTip = function(d) {
  528.  
  529. if (this.tooltipNode != undefined) {
  530. this.tooltipNode.remove()
  531. };
  532.  
  533. this.tooltipNode = this.plot.append("g")
  534.  
  535.  
  536. this.tooltipNode.append("text")
  537. .attr("id","tooltiptext")
  538. .attr("opacity",1)
  539. .attr("x", "0.5em")
  540. .text(d.x + " | "+ d.y );
  541.  
  542. var text_width = d3.select("#tooltiptext").node().getComputedTextLength()+15;
  543. if(this.orientation == 'vertical'){
  544.  
  545. this.tooltipNode
  546. .attr("transform", "translate(" + (this.xScale(d.x) * 1 + 5) + "," + (this.yScale(d.y) * 1 - 10) + ")")
  547. .style("opacity", 0);
  548. }else if(this.orientation == 'horizontal'){
  549. this.tooltipNode
  550. .attr("transform", "translate(" + Math.min(this.xScale(d.y)+5,this.xScale(d.y)+5-text_width) + "," + (this.yScale(d.x) * 1 - 10) + ")")
  551. .style("opacity", 0);
  552.  
  553. };
  554.  
  555. this.tooltipNode
  556. .append("rect")
  557. .attr("width", text_width)
  558. .attr("height", "1.6em")
  559. .attr("y", "-1.25em")
  560. .attr("fill", "lightgray")
  561. .attr("rx", 4)
  562. .style("pointer-events", "none");
  563.  
  564. this.tooltipNode.append("text")
  565. .attr("x", "0.5em")
  566. .style("opacity",0.9)
  567. .style("background", "lightgray")
  568. .text(d.x + " | "+ d.y);
  569.  
  570. this.tooltipNode
  571. .transition().duration(200)
  572. .style("opacity", 1);
  573.  
  574. };
  575.  
  576. Scatter_Plot.prototype.hideToolTip = function() {
  577. var that = this;
  578. that.tooltipNode.remove();
  579. };
  580.  
  581. Scatter_Plot.prototype.generateButtons = function() {
  582. var that = this;
  583. d3.select(".button-container").append("button")
  584. .text("Add Data")
  585. .on("click", function() {
  586. that.updateData()
  587. });
  588. d3.select(".button-container").append("button")
  589. .text("Initialize Clusters")
  590. .on("click", function() {
  591. that.addKMeansClusters();
  592. that.greyColors();
  593. });
  594. d3.select(".button-container").append("button")
  595. .text("KMeans Iteration")
  596. .on("click", function() {
  597. that.k_means.euclideanDistance();
  598. that.updateColors();
  599. });
  600. };
  601.  
  602. Scatter_Plot.prototype.removeData = function() {
  603. this.data.pop();
  604. this.updateBars();
  605.  
  606. };
  607.  
  608.  
  609. Scatter_Plot.prototype.rotateChart= function(){
  610. if(this.orientation=='vertical'){
  611. this.orientation='horizontal';
  612. }else{
  613. this.orientation='vertical';
  614. };
  615. this.updateBars();
  616.  
  617.  
  618. };
  619.  
  620. /////////////////////////////////////
  621. ////New class for k means clustering
  622. /////////////////////////////////
  623.  
  624.  
  625. var K_Means = function(dataset,k){
  626. this.k = k;
  627. this.dataset = dataset;
  628. this.centroidList = [];
  629.  
  630. this.xData = this.dataset.map(function(d){return d.x});
  631. this.yData = this.dataset.map(function(d){return d.y});
  632.  
  633. for(i=0; i<this.k; i++){
  634.  
  635. var centroid = {
  636. x:(i+1)*((Math.max.apply(null,this.xData) - Math.min.apply(null,this.xData))/(this.k)),
  637. y:(i+1)*((Math.max.apply(null,this.yData) - Math.min.apply(null,this.yData))/(this.k))
  638. };
  639. this.centroidList.push(centroid)
  640. };
  641.  
  642. };
  643.  
  644. K_Means.prototype.euclideanDistance = function(){
  645.  
  646. this.xData = this.dataset.map(function(d){return d.x});
  647. this.yData = this.dataset.map(function(d){return d.y});
  648. this.center1xDiff = 0;
  649. this.center1yDiff = 0;
  650. this.center2Diff = 0;
  651.  
  652.  
  653. //iterate over each point
  654. for(i=0; i < this.dataset.length; i++){
  655. var pointDistanceList = [];
  656. for(k=0; k< this.centroidList.length; k++){
  657. var pointDistance = Math.sqrt(Math.pow((this.xData[i] - this.centroidList[k].x),2) + Math.pow((this.yData[i] - this.centroidList[k].y),2));
  658. pointDistanceList.push(pointDistance);
  659. };
  660.  
  661. //find the arg min of the pointDistanceList
  662. var argMin = pointDistanceList.map((x, i) => [x, i]).reduce((r, a) => (a[0] < r[0] ? a : r))[1];
  663.  
  664. //assign point to cluster
  665. this.dataset[i].cluster = argMin;
  666. };
  667.  
  668. //move the centroid to the average of it's data points;
  669. for(k=0; k<this.centroidList.length; k++){
  670.  
  671. this.centroidList[k].x = d3.mean(this.dataset.filter(d=>d.cluster == k),function(d){return d.x});
  672.  
  673. this.centroidList[k].y = d3.mean(this.dataset.filter(d=>d.cluster == k),function(d){return d.y});
  674. }
  675. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement