1<!DOCTYPE html> 2<html lang="en"> 3 <head> 4 5 <!-- Global site tag (gtag.js) - Google Analytics -->
vendor: 81 bytes, lines 5-9
5 6 7 <script 8 async 9 src="https://www.googletagmanager.com/gtag/js?id=
9UA-79254642-6
vendor: 22 bytes, lines 9-12
9" 10 ></script> 11 12
12<script> 13
vendor: 163 bytes, lines 13-19
13window.dataLayer = window.dataLayer || []; 14 function gtag() { 15 dataLayer.push(arguments); 16 } 17 gtag("js", new Date()); 18 19 gtag("config", "
19UA-79254642-6
vendor: 8 bytes, lines 19-20
19"); 20
20</script>
20 21 22 <meta charset="utf-8" /> 23 <title>Boxplot | the D3 Graph Gallery</title> 24 25 <meta 26 name="viewport" 27 content="width=device-width, initial-scale=1, shrink-to-fit=no" 28 /> 29 <meta 30 name="description" 31 content="How to build a boxplot with Javascript and D3.js: from the most basic example to highly customized examples." 32 /> 33 <meta 34 name="keywords" 35 content="Data,Dataviz,Datavisualization,Javascript,D3,D3.js,boxplot" 36 /> 37 <meta name="author" content="Yan Holtz" /> 38 <link rel="icon" href="img/logo/D3_single_small.png" /> 39 40 <meta property="og:title" content="Boxplot | the D3 Graph Gallery" /> 41 <meta property="og:image" content="img/overview_RGG.png" /> 42 <meta 43 property="og:description" 44 content="How to build a boxplot with Javascript and D3.js: from the most basic example to highly customized examples." 45 /> 46 47 <!-- Bootstrap core CSS --> 48 <link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet" /> 49 50 <!-- Custom fonts for this template --> 51 <link 52 href="vendor/font-awesome/css/font-awesome.min.css" 53 rel="stylesheet" 54 type="text/css" 55 /> 56 <link 57 href="https://fonts.googleapis.com/css?family=Montserrat:400,700" 58 rel="stylesheet" 59 type="text/css" 60 /> 61 <link 62 href="https://fonts.googleapis.com/css?family=Kaushan+Script" 63 rel="stylesheet" 64 type="text/css" 65 /> 66 <link 67 href="https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic,700italic" 68 rel="stylesheet" 69 type="text/css" 70 /> 71 <link 72 href="https://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700" 73 rel="stylesheet" 74 type="text/css" 75 /> 76 77 <!-- Custom styles for this template --> 78 <link href="css/agency.css" rel="stylesheet" /> 79 80 <!-- JQUERY --> 81
81<script src="vendor/jquery/jquery.min.js"></script>
81 82 83 <!-- d3.v4 and Plugin for color scale --> 84
84<script src="js/d3.v4.js"></script>
84 85
85<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
85 86 </head> 87 88 <body id="page-top"> 89 <!-- THIS ALLOWS TO INSERT THE MENU THAT IS STORED IN A MENU.HTML FILE--> 90 <nav class="navbar navbar-expand-lg fixed-top" id="mainNav"></nav> 91
91<script> 92 $(function () { 93 $("#mainNav").load("html_chunk/menu.html"); 94 }); 95 </script>
95 96 97 <!-- THIS ALLOWS TO INSERT THE MODAL OF THE MENU THAT IS STORED IN A MENU_MODAL.HTML FILE--> 98 <div id="modal_menu_insertion"></div> 99
99<script> 100 $(function () { 101 $("#modal_menu_insertion").load("html_chunk/menu_modal.html"); 102 }); 103 </script>
103 104 105 <!-- Header --> 106 <header class="masthead" style="padding-top: 150px; padding-bottom: 80px"> 107 <div class="textlanding"> 108 <h1>Boxplot</h1> 109 <hr class="short_hr" /> 110 <br /> 111 <ul class="list-inline social-buttons"> 112 <li class="list-inline-item"> 113 <a href="https://twitter.com/R_Graph_Gallery"> 114 <i class="fa fa-twitter"></i> 115 </a> 116 </li> 117 <li class="list-inline-item social-buttons"> 118 <a href="https://github.com/holtzy"> 119 <i class="fa fa-github" style="color: white"></i> 120 </a> 121 </li> 122 <li class="list-inline-item social-buttons"> 123 <a href="https://www.linkedin.com/in/yan-holtz-2477534a/"> 124 <i class="fa fa-linkedin"></i> 125 </a> 126 </li> 127 <li class="list-inline-item social-buttons"> 128 <a href="https://www.yan-holtz.com"> 129 <i class="fa fa-home"></i> 130 </a> 131 </li> 132 </ul> 133 <br /><br /> 134 <p style="max-width: 700px; margin: auto"> 135 This is the 136 <a href="https://www.data-to-viz.com/caveat/boxplot.html">boxplot</a> 137 section of the gallery. If you want to know more about this kind of 138 chart, visit 139 <a href="https://www.data-to-viz.com/caveat/boxplot.html" 140 >data-to-viz.com</a 141 >. If you're looking for a simple way to implement it in d3.js, pick 142 an example below. 143 </p> 144 </div> 145 </header> 146 147 148 <!-- ======================== PORTFOLIO SECTION ============================ --><!-- Images must be 480 x 480, resize them with ./script_reformat_img.sh output_name.png --> 149 <section class="bg" id="portfolio" style="padding-top: 10px"> 150 <div class="container"> 151 <div class="mySeryTitle">Step by step</div> 152 <hr /> 153 <div id="portfolio-items" class="row"> 154 <div class="col-md-4 col-sm-6 portfolio-item"> 155 <a class="portfolio-link" href="graph/boxplot_basic.html"> 156 <div class="portfolio-hover"> 157 <div class="portfolio-hover-content"> 158 <p>Most basic</p> 159 <hr /> 160 <p class="explanation_portfolio"> 161 The most basic boxplot you can do in d3.js. Keeping only the 162 core code. Starts with an array of data. 163 </p> 164 </div> 165 </div> 166 <img class="img-fluid" src="img/graph/boxplot_basic.png" alt="" /> 167 </a> 168 </div> 169 <div class="col-md-4 col-sm-6 portfolio-item"> 170 <a class="portfolio-link" href="graph/boxplot_several_groups.html"> 171 <div class="portfolio-hover"> 172 <div class="portfolio-hover-content"> 173 <p>With several group</p> 174 <hr /> 175 <p class="explanation_portfolio"> 176 A boxplot with several groups. It extends the technique used 177 on the previous chart. The tricky part is to computed 178 summary statistics for each group. 179 </p> 180 </div> 181 </div> 182 <img 183 class="img-fluid" 184 src="img/graph/boxplot_several_groups.png" 185 alt="" 186 /> 187 </a> 188 </div> 189 <div class="col-md-4 col-sm-6 portfolio-item"> 190 <a 191 class="portfolio-link" 192 href="graph/boxplot_show_individual_points.html" 193 > 194 <div class="portfolio-hover"> 195 <div class="portfolio-hover-content"> 196 <p>Show individual data points</p> 197 <hr /> 198 <p class="explanation_portfolio"> 199 The major downside of boxplot is that it hides the 200 underlying data points. It is a good practice to show them 201 using jitter. Learn how with this example. 202 </p> 203 </div> 204 </div> 205 <img 206 class="img-fluid" 207 src="img/graph/boxplot_show_individual_points.png" 208 alt="" 209 /> 210 </a> 211 </div> 212 </div> 213 214 <br /><br /> 215 <div class="mySeryTitle">Template</div> 216 <hr /> 217 <p> 218 Here is the template I'm starting with when in need for a boxplot in 219 my work. See the code 220 <a href="graph/boxplot_horizontal.html">here</a>. 221 </p> 222 <div class="row"> 223 <div class="col-lg-12"> 224 <center><div id="boxplot_template"></div></center> 225 </div> 226 </div> 227 228 <br /><br /> 229 <div class="mySeryTitle">Related blocks</div> 230 <hr /> 231 </div> 232 </section> 233 234 <!-- ======================================================================= --> 235 236 <!-- ============================ JAVASCRIPT BOXPLOT TEMPLATE ============================ --> 237 238 <!-- Tooltip style --> 239 <style> 240 .tooltip { 241 background-color: black; 242 border: none; 243 border-radius: 5px; 244 padding: 15px; 245 min-width: 200px; 246 text-align: left; 247 color: white; 248 } 249 250 svg { 251 border: 1px solid #e8e8e8; 252 border-radius: 6px; 253 } 254 </style> 255 256
256<script> 257 // set the dimensions and margins of the graph 258 var margin = { top: 10, right: 30, bottom: 50, left: 70 }, 259 width = 760 - margin.left - margin.right, 260 height = 600 - margin.top - margin.bottom; 261 262 // append the svg object to the body of the page 263 var svg = d3 264 .select("#boxplot_template") 265 .append("svg") 266 .attr("width", width + margin.left + margin.right) 267 .attr("height", height + margin.top + margin.bottom) 268 .append("g") 269 .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 270 271 // Read the data and compute summary statistics for each specie 272 d3.csv( 273 "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/iris.csv", 274 function (data) { 275 // Compute quartiles, median, inter quantile range min and max --> these info are then used to draw the box. 276 var sumstat = d3 277 .nest() // nest function allows to group the calculation per level of a factor 278 .key(function (d) { 279 return d.Species; 280 }) 281 .rollup(function (d) { 282 q1 = d3.quantile( 283 d 284 .map(function (g) { 285 return g.Sepal_Length; 286 }) 287 .sort(d3.ascending), 288 0.25 289 ); 290 median = d3.quantile( 291 d 292 .map(function (g) { 293 return g.Sepal_Length; 294 }) 295 .sort(d3.ascending), 296 0.5 297 ); 298 q3 = d3.quantile( 299 d 300 .map(function (g) { 301 return g.Sepal_Length; 302 }) 303 .sort(d3.ascending), 304 0.75 305 ); 306 interQuantileRange = q3 - q1; 307 min = q1 - 1.5 * interQuantileRange; 308 max = q3 + 1.5 * interQuantileRange; 309 return { 310 q1: q1, 311 median: median, 312 q3: q3, 313 interQuantileRange: interQuantileRange, 314 min: min, 315 max: max, 316 }; 317 }) 318 .entries(data); 319 320 // Show the Y scale 321 var y = d3 322 .scaleBand() 323 .range([height, 0]) 324 .domain(["setosa", "versicolor", "virginica"]) 325 .padding(0.4); 326 svg 327 .append("g") 328 .call(d3.axisLeft(y).tickSize(0)) 329 .select(".domain") 330 .remove(); 331 332 // Show the X scale 333 var x = d3.scaleLinear().domain([4, 8]).range([0, width]); 334 svg 335 .append("g") 336 .attr("transform", "translate(0," + height + ")") 337 .call(d3.axisBottom(x).ticks(5)) 338 .select(".domain") 339 .remove(); 340 341 // Color scale 342 var myColor = d3 343 .scaleSequential() 344 .interpolator(d3.interpolateInferno) 345 .domain([4, 8]); 346 347 // Add X axis label: 348 svg 349 .append("text") 350 .attr("text-anchor", "end") 351 .attr("x", width) 352 .attr("y", height + margin.top + 30) 353 .text("Sepal Length"); 354 355 // Show the main vertical line 356 svg 357 .selectAll("vertLines") 358 .data(sumstat) 359 .enter() 360 .append("line") 361 .attr("x1", function (d) { 362 return x(d.value.min); 363 }) 364 .attr("x2", function (d) { 365 return x(d.value.max); 366 }) 367 .attr("y1", function (d) { 368 return y(d.key) + y.bandwidth() / 2; 369 }) 370 .attr("y2", function (d) { 371 return y(d.key) + y.bandwidth() / 2; 372 }) 373 .attr("stroke", "black") 374 .style("width", 40); 375 376 // rectangle for the main box 377 svg 378 .selectAll("boxes") 379 .data(sumstat) 380 .enter() 381 .append("rect") 382 .attr("x", function (d) { 383 return x(d.value.q1); 384 }) // console.log(x(d.value.q1)) ; 385 .attr("width", function (d) { 386 return x(d.value.q3) - x(d.value.q1); 387 }) //console.log(x(d.value.q3)-x(d.value.q1)) 388 .attr("y", function (d) { 389 return y(d.key); 390 }) 391 .attr("height", y.bandwidth()) 392 .attr("stroke", "black") 393 .style("fill", "#69b3a2") 394 .style("opacity", 0.3); 395 396 // Show the median 397 svg 398 .selectAll("medianLines") 399 .data(sumstat) 400 .enter() 401 .append("line") 402 .attr("y1", function (d) { 403 return y(d.key) + y.bandwidth() / 2; 404 }) 405 .attr("y2", function (d) { 406 return y(d.key) + y.bandwidth() / 2; 407 }) 408 .attr("x1", function (d) { 409 return x(d.value.median); 410 }) 411 .attr("x2", function (d) { 412 return x(d.value.median); 413 }) 414 .attr("stroke", "black") 415 .style("width", 80); 416 417 // create a tooltip 418 var tooltip = d3 419 .select("#boxplot_template") 420 .append("div") 421 .style("opacity", 0) 422 .attr("class", "tooltip") 423 .style("font-size", "16px"); 424 // Three function that change the tooltip when user hover / move / leave a cell 425 var mouseover = function (d) { 426 tooltip.transition().duration(200).style("opacity", 1); 427 tooltip 428 .html( 429 "<span style='color:grey'>Sepal length: </span>" + 430 d.Sepal_Length 431 ) // + d.Prior_disorder + "<br>" + "HR: " + d.HR) 432 .style("left", d3.mouse(this)[0] + 30 + "px") 433 .style("top", d3.mouse(this)[1] + 30 + "px"); 434 }; 435 var mousemove = function (d) { 436 tooltip 437 .style("left", d3.mouse(this)[0] + 30 + "px") 438 .style("top", d3.mouse(this)[1] + 30 + "px"); 439 }; 440 var mouseleave = function (d) { 441 tooltip.transition().duration(200).style("opacity", 0); 442 }; 443 444 // Add individual points with jitter 445 var jitterWidth = 60; 446 svg 447 .selectAll("indPoints") 448 .data(data) 449 .enter() 450 .append("circle") 451 .attr("cx", function (d) { 452 return x(d.Sepal_Length); 453 }) 454 .attr("cy", function (d) { 455 return ( 456 y(d.Species) + 457 y.bandwidth() / 2 - 458 jitterWidth / 2 + 459 Math.random() * jitterWidth 460 ); 461 }) 462 .attr("r", 6) 463 .style("fill", function (d) { 464 return myColor(+d.Sepal_Length); 465 }) 466 .attr("stroke", "black")
467 .on("mouseover", mouseover) 468 .on("mousemove", mousemove) 469 .on("mouseleave", mouseleave); 470 } 471 ); 472 </script>
472 473 474 <!-- ============================ RELATED SECTION ============================ --> 475 <section 476 class="bg-light" 477 id="portfolio_landing" 478 style="padding-top: 30px; padding-bottom: 30px" 479 > 480 <div class="container"> 481 <p class="mySeryTitle">Related chart types</p> 482 <hr /> 483 <div class="row"> 484 <div class="col-md-2 col-sm-4 portfolio-item"> 485 <a class="portfolio-link" href="violin.html"> 486 <div class="portfolio-hover"> 487 <div class="portfolio-hover-content"> 488 <i class="fa fa-plus fa-3x"></i> 489 </div> 490 </div> 491 <img class="img-fluid" src="img/section/Violin150.png" alt="" /> 492 </a> 493 <div class="captionPortfolio">Violin</div> 494 </div> 495 <div class="col-md-2 col-sm-4 portfolio-item"> 496 <a class="portfolio-link" href="density.html"> 497 <div class="portfolio-hover"> 498 <div class="portfolio-hover-content"> 499 <i class="fa fa-plus fa-3x"></i> 500 </div> 501 </div> 502 <img class="img-fluid" src="img/section/Density150.png" alt="" /> 503 </a> 504 <div class="captionPortfolio">Density</div> 505 </div> 506 <div class="col-md-2 col-sm-4 portfolio-item"> 507 <a class="portfolio-link" href="histogram.html"> 508 <div class="portfolio-hover"> 509 <div class="portfolio-hover-content"> 510 <i class="fa fa-plus fa-3x"></i> 511 </div> 512 </div> 513 <img 514 class="img-fluid" 515 src="img/section/Histogram150.png" 516 alt="" 517 /> 518 </a> 519 <div class="captionPortfolio">Histogram</div> 520 </div> 521 <div class="col-md-2 col-sm-4 portfolio-item"> 522 <a class="portfolio-link" href="boxplot.html"> 523 <div class="portfolio-hover"> 524 <div class="portfolio-hover-content"> 525 <i class="fa fa-plus fa-3x"></i> 526 </div> 527 </div> 528 <img class="img-fluid" src="img/section/Box1150.png" alt="" /> 529 </a> 530 <div class="captionPortfolio">Boxplot</div> 531 </div> 532 <div class="col-md-2 col-sm-4 portfolio-item"> 533 <a class="portfolio-link" href="ridgeline.html"> 534 <div class="portfolio-hover"> 535 <div class="portfolio-hover-content"> 536 <i class="fa fa-plus fa-3x"></i> 537 </div> 538 </div> 539 <img class="img-fluid" src="img/section/Joyplot150.png" alt="" /> 540 </a> 541 <div class="captionPortfolio">Ridgeline</div> 542 </div> 543 </div> 544 </div> 545 </section> 546 547 <!-- ============================ CONTACT SECTION ============================ --> 548 549 550 <section id="contact" class="bg" style="background-color: white"></section> 551 552 <!-- THIS ALLOWS TO INSERT THE NEWSLETTER CHUNK THAT IS STORED IN A NEWSLETTER_SECTION.HTML FILE--> 553
553<script> 554 $(function () { 555 $("#contact").load("html_chunk/newsletter_section.html"); 556 }); 557 </script>
557 558 559 <!-- ============================ FOOTER SECTION ============================ --> 560 <footer class="bg-light" id="myFooter"></footer> 561 562 563 <!-- THIS ALLOWS TO INSERT THE FOOTER THAT IS STORED IN A FOOTER.HTML FILE--> 564
564<script> 565 $(function () { 566 $("#myFooter").load("html_chunk/footer.html"); 567 }); 568 </script>
568 569 570 <!-- ============================ --> 571 572 <!-- =============== JAVASCRIPT SECTION =============== --> 573 574 <!-- Bootstrap core JavaScript --> 575
575<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
575 576 577 <!-- Plugin JavaScript --> 578
578<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
578 579 580 <!-- Custom scripts for this template --> 581
581<script src="js/agency.min.js"></script>
581 582 583 <!--============================== --> 584 <!-- Newsletter toast (pops bottom-right after a few seconds). Content lives in js/newsletter-toast.js --> 585
585<script src="js/newsletter-toast.js"></script>
585 586 </body> 587</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.