class: center, middle, inverse, title-slide # Network Visualization in R ## using ggraph and graphlayouts ### David Schoch ### University of Manchester --- layout: true class: paint-bg --- # about me <br> - Research on social media and social networks - R developer since 2012 - Self taught in data/network visualization - I blog about R dev (blog.schochastics.net) <div style="position:absolute;right:5%;top:25%"> <img src="https://www.exeley.com/exeley/journals/connections/exeley-connections.jpg"> </div> <div style="position:absolute;left:5%;bottom:-1%"> <img src="figures/packages.png" height="250px"> </div> --- # about today <br> <br> - No introduction to R 😞 - No introduction to network analysis 😞 - Just drawing pretty pictures 😀 --- # ordinary data .left-code[ <table> <thead> <tr> <th style="text-align:left;"> </th> <th style="text-align:right;"> mpg </th> <th style="text-align:right;"> cyl </th> <th style="text-align:right;"> disp </th> <th style="text-align:right;"> hp </th> <th style="text-align:right;"> drat </th> <th style="text-align:right;"> wt </th> <th style="text-align:right;"> qsec </th> <th style="text-align:right;"> vs </th> <th style="text-align:right;"> am </th> <th style="text-align:right;"> gear </th> <th style="text-align:right;"> carb </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Mazda RX4 </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 160 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.620 </td> <td style="text-align:right;"> 16.46 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 Wag </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 160 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.875 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Datsun 710 </td> <td style="text-align:right;"> 22.8 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 108 </td> <td style="text-align:right;"> 93 </td> <td style="text-align:right;"> 3.85 </td> <td style="text-align:right;"> 2.320 </td> <td style="text-align:right;"> 18.61 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet 4 Drive </td> <td style="text-align:right;"> 21.4 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 258 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.08 </td> <td style="text-align:right;"> 3.215 </td> <td style="text-align:right;"> 19.44 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet Sportabout </td> <td style="text-align:right;"> 18.7 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 360 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.15 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Valiant </td> <td style="text-align:right;"> 18.1 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 225 </td> <td style="text-align:right;"> 105 </td> <td style="text-align:right;"> 2.76 </td> <td style="text-align:right;"> 3.460 </td> <td style="text-align:right;"> 20.22 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> </tbody> </table> ] --- # ordinary data .left-code[ <table> <thead> <tr> <th style="text-align:left;"> </th> <th style="text-align:right;"> mpg </th> <th style="text-align:right;"> cyl </th> <th style="text-align:right;"> disp </th> <th style="text-align:right;"> hp </th> <th style="text-align:right;"> drat </th> <th style="text-align:right;"> wt </th> <th style="text-align:right;"> qsec </th> <th style="text-align:right;"> vs </th> <th style="text-align:right;"> am </th> <th style="text-align:right;"> gear </th> <th style="text-align:right;"> carb </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Mazda RX4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 21.0 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 160 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.620 </td> <td style="text-align:right;"> 16.46 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 Wag </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 21.0 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 160 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.875 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Datsun 710 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 22.8 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 108 </td> <td style="text-align:right;"> 93 </td> <td style="text-align:right;"> 3.85 </td> <td style="text-align:right;"> 2.320 </td> <td style="text-align:right;"> 18.61 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet 4 Drive </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 21.4 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 258 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.08 </td> <td style="text-align:right;"> 3.215 </td> <td style="text-align:right;"> 19.44 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet Sportabout </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 18.7 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 360 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.15 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Valiant </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 18.1 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 225 </td> <td style="text-align:right;"> 105 </td> <td style="text-align:right;"> 2.76 </td> <td style="text-align:right;"> 3.460 </td> <td style="text-align:right;"> 20.22 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> </tbody> </table> ] .plot-callout[ <img src="slides_files/figure-html/mtcars1-callout-1.png" height="99%" /> ] --- # ordinary data .left-code[ <table> <thead> <tr> <th style="text-align:left;"> </th> <th style="text-align:right;"> mpg </th> <th style="text-align:right;"> cyl </th> <th style="text-align:right;"> disp </th> <th style="text-align:right;"> hp </th> <th style="text-align:right;"> drat </th> <th style="text-align:right;"> wt </th> <th style="text-align:right;"> qsec </th> <th style="text-align:right;"> vs </th> <th style="text-align:right;"> am </th> <th style="text-align:right;"> gear </th> <th style="text-align:right;"> carb </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Mazda RX4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 160 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.620 </td> <td style="text-align:right;"> 16.46 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 Wag </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 160 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.875 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Datsun 710 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 22.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 108 </td> <td style="text-align:right;"> 93 </td> <td style="text-align:right;"> 3.85 </td> <td style="text-align:right;"> 2.320 </td> <td style="text-align:right;"> 18.61 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet 4 Drive </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 21.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 258 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.08 </td> <td style="text-align:right;"> 3.215 </td> <td style="text-align:right;"> 19.44 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet Sportabout </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 18.7 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 360 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.15 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Valiant </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 18.1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 225 </td> <td style="text-align:right;"> 105 </td> <td style="text-align:right;"> 2.76 </td> <td style="text-align:right;"> 3.460 </td> <td style="text-align:right;"> 20.22 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> </tbody> </table> ] .plot-callout[ <img src="slides_files/figure-html/mtcars2-callout-1.png" height="99%" /> ] --- # ordinary data .left-code[ <table> <thead> <tr> <th style="text-align:left;"> </th> <th style="text-align:right;"> mpg </th> <th style="text-align:right;"> cyl </th> <th style="text-align:right;"> disp </th> <th style="text-align:right;"> hp </th> <th style="text-align:right;"> drat </th> <th style="text-align:right;"> wt </th> <th style="text-align:right;"> qsec </th> <th style="text-align:right;"> vs </th> <th style="text-align:right;"> am </th> <th style="text-align:right;"> gear </th> <th style="text-align:right;"> carb </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Mazda RX4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 160 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.620 </td> <td style="text-align:right;"> 16.46 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 Wag </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 160 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.875 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Datsun 710 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 22.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 108 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 93 </td> <td style="text-align:right;"> 3.85 </td> <td style="text-align:right;"> 2.320 </td> <td style="text-align:right;"> 18.61 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet 4 Drive </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 21.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 258 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 110 </td> <td style="text-align:right;"> 3.08 </td> <td style="text-align:right;"> 3.215 </td> <td style="text-align:right;"> 19.44 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet Sportabout </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 18.7 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 360 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 175 </td> <td style="text-align:right;"> 3.15 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Valiant </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 18.1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 225 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 105 </td> <td style="text-align:right;"> 2.76 </td> <td style="text-align:right;"> 3.460 </td> <td style="text-align:right;"> 20.22 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> </tbody> </table> ] .plot-callout[ <img src="slides_files/figure-html/mtcars3-callout-1.png" height="99%" /> ] --- # ordinary data .left-code[ <table> <thead> <tr> <th style="text-align:left;"> </th> <th style="text-align:right;"> mpg </th> <th style="text-align:right;"> cyl </th> <th style="text-align:right;"> disp </th> <th style="text-align:right;"> hp </th> <th style="text-align:right;"> drat </th> <th style="text-align:right;"> wt </th> <th style="text-align:right;"> qsec </th> <th style="text-align:right;"> vs </th> <th style="text-align:right;"> am </th> <th style="text-align:right;"> gear </th> <th style="text-align:right;"> carb </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Mazda RX4 </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;"> 160 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 3.90 </td> <td style="text-align:right;"> 2.620 </td> <td style="text-align:right;"> 16.46 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 Wag </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;"> 160 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 3.90 </td> <td style="text-align:right;"> 2.875 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Datsun 710 </td> <td style="text-align:right;"> 22.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 4 </td> <td style="text-align:right;"> 108 </td> <td style="text-align:right;"> 93 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 3.85 </td> <td style="text-align:right;"> 2.320 </td> <td style="text-align:right;"> 18.61 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet 4 Drive </td> <td style="text-align:right;"> 21.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;"> 258 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 3.08 </td> <td style="text-align:right;"> 3.215 </td> <td style="text-align:right;"> 19.44 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet Sportabout </td> <td style="text-align:right;"> 18.7 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 8 </td> <td style="text-align:right;"> 360 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 3.15 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Valiant </td> <td style="text-align:right;"> 18.1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6 </td> <td style="text-align:right;"> 225 </td> <td style="text-align:right;"> 105 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 2.76 </td> <td style="text-align:right;"> 3.460 </td> <td style="text-align:right;"> 20.22 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> </tbody> </table> ] .plot-callout[ <img src="slides_files/figure-html/mtcars4-callout-1.png" height="99%" /> ] --- # why visualizing networks is hard(er) **ordinary data** - clear file format (spreadsheet, csv) - clear data format (rows: observations, columns: variables) - plot style dependent on variable scale (barchart, scatterplot,boxplot,...) - illustrate relations between variables - given relative positions **network data** - many different file formats (csv,graphml,dot,dl,gexf,net,gdf,gml,nnf,sif,xgmml) - different data formats (adjacency matrix,edgelist,adjaceny list,incidence matrix) - how to choose a proper layout algorithm? - more degrees of freedom - can we draw any conclusions from a network plot? --- # network visualization software ## gephi works quite well for visualizing large networks ## visone well designed GUI and algorithms (`graphlayouts` implements most algorithms from it) ## and many more cytoscape, NodeXL, Graphviz, python, ... --- layout: false class: normal-bg .center[ <img src="http://social-dynamics.org/wp-content/uploads/2011/11/gephi.png" height="700px"> ] --- .center[ <img src="https://visone.ethz.ch/wiki/images/thumb/5/55/Caltech36-Quadrilateral-Backbone.png/770px-Caltech36-Quadrilateral-Backbone.png" height="600px"> ] --- layout: true class: paint-bg --- # network visualization in R **why R?** open source, cross-platform, CRAN, more than SNA, community (#rstats/RLadies) **different file/data formats** R can handle many file formats, RStudio addin `Netreader` **how to choose a proper layout algorithm?** `graphlayouts` ⇒ layout_with_stress(), layout_as_backbone(), ... **more degrees of freedom** manage degrees of freedom via grammar of graphics (see `ggplot2`) **more complex?** RStudio addin `SNAhelper` (no coding needed!) --- # which packages to choose? <br> - `igraph`: great for analyses, but plotting can be tricky (check out https://kateto.net/network-visualization) - `visNetwork`: interactive network visualizations using the vis.js - `threejs`: interactive (3D) network visualizations using three.js - `ggnet2`: plot network objects as `ggplot2` objects - .highlight[`ggraph`: an implementation of grammar of graphics for networks] --- # grammar of graphics .center[ <img src="figures/grammar.png" height="400"> ] --- # network data: the graph? .center[ <img src="slides_files/figure-html/sw_init-1.png" height="400" /> ] --- # network data: data frames! <div style="position:absolute;left:10%;top:25%"> <table class="table" style="width: auto !important; margin-left: auto; margin-right: auto;"> <caption>Nodes</caption> <thead> <tr> <th style="text-align:left;"> name </th> <th style="text-align:left;"> sex </th> <th style="text-align:left;"> homeworld </th> <th style="text-align:left;"> species </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> R2-D2 </td> <td style="text-align:left;"> none </td> <td style="text-align:left;"> Naboo </td> <td style="text-align:left;"> Droid </td> </tr> <tr> <td style="text-align:left;"> NUTE GUNRAY </td> <td style="text-align:left;"> male </td> <td style="text-align:left;"> Cato Neimoidia </td> <td style="text-align:left;"> Neimodian </td> </tr> <tr> <td style="text-align:left;"> OBI-WAN </td> <td style="text-align:left;"> male </td> <td style="text-align:left;"> Stewjon </td> <td style="text-align:left;"> Human </td> </tr> <tr> <td style="text-align:left;"> EMPEROR </td> <td style="text-align:left;"> male </td> <td style="text-align:left;"> Naboo </td> <td style="text-align:left;"> Human </td> </tr> <tr> <td style="text-align:left;"> JAR JAR </td> <td style="text-align:left;"> male </td> <td style="text-align:left;"> Naboo </td> <td style="text-align:left;"> Gungan </td> </tr> <tr> <td style="text-align:left;"> TARPALS </td> <td style="text-align:left;"> male </td> <td style="text-align:left;"> Naboo </td> <td style="text-align:left;"> Gungan </td> </tr> </tbody> </table> </div> <div style="position:absolute;right:10%;top:25%"> <table class="table" style="width: auto !important; margin-left: auto; margin-right: auto;"> <caption>Edges</caption> <thead> <tr> <th style="text-align:left;"> from </th> <th style="text-align:left;"> to </th> <th style="text-align:right;"> weight </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> KI-ADI-MUNDI </td> <td style="text-align:left;"> YODA </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> QUI-GON </td> <td style="text-align:left;"> JAR JAR </td> <td style="text-align:right;"> 22 </td> </tr> <tr> <td style="text-align:left;"> TC-14 </td> <td style="text-align:left;"> OBI-WAN </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> ANAKIN </td> <td style="text-align:left;"> BRAVO TWO </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> SIO BIBBLE </td> <td style="text-align:left;"> JAR JAR </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> ANAKIN </td> <td style="text-align:left;"> C-3PO </td> <td style="text-align:right;"> 3 </td> </tr> </tbody> </table> </div> <span style="position:absolute;bottom:10%;left:5%;font-size:40px;font-weight:700">+layout </span> <span style="position:absolute;bottom:5%;right:5%;">see `tidygraph` </span> --- # first full example (don't panic!) ```r ggraph(graph = g,layout = "stress") + geom_edge_link0(edge_colour = "grey25", aes(edge_width = weight)) + geom_node_point(shape = 21, color = "black",stroke = 1, aes(fill = sex,size = interactions)) + geom_node_text(color = "grey25", fontface = "bold", size = 6, repel = TRUE, aes(filter = (interactions>=65),label = name))+ scale_edge_width(range = c(0.1,1.5),guide = "none")+ scale_size(range = c(3,10),guide = "none")+ scale_fill_manual(values = sw_palette, na.value = "grey",name = "")+ theme_graph() + theme(legend.position = "bottom") + guides(fill = guide_legend(override.aes = list(size=6))) ``` --- layout: false class: normal-bg <img src="slides_files/figure-html/sw_plot1-1.png" height="600" style="display: block; margin: auto;" /> --- layout: true class: paint-bg --- # 1) layout <span class="alert">`ggraph(graph = g,layout = "stress")`</span> - graph: `igraph` object g (can also be a `tidygraph` object) - layout: used algorithm (from `igraph` or .highlight[`graphlayouts`]) <!-- --> <img src="figures/cross-stroke-ff6f3c.png" style="position:absolute;top:47%;right:11%" height="300"> see also https://www.data-imaginist.com/2017/ggraph-introduction-layouts/ --- # 2) edges .alert[`geom_edge_link0(edge_colour = "grey25",aes(edge_width = weight))`] **edge geoms** there are many (see `geom_edge_*`) but `geom_edge_link0()` and `geom_edge_parallel0()` suffice **mapping .underline[aes]thetics** .alert[global]: all edges have the same appearance (e.g. `edge_colour="grey25"`) .alert[via attributes]: appearance depends on attribute (e.g. `aes(edge_width = weight)`) **available aesthetics** edge_colour, edge_width, edge_linetype, edge_alpha --- # 3) nodes .alert[`geom_node_point(shape = 21, color = "black",stroke = 1,`] <span style="margin-left: 7.5em;">.alert[`aes(fill = sex,size = interactions))`]</span> **node geoms** there are some (see `geom_node_*`) but `geom_node_point()` suffices **mapping .underline[aes]thetics** .alert[global]: all nodes have the same appearance (e.g. `shape = 21`) .alert[via attributes]: appearance depends on attribute (e.g. `aes(fill = sex)`) **available aesthetics** alpha, colour, fill, shape, size, stroke (usage of colour and fill depend on shape) --- # 4) labels .alert[`geom_node_text(color = "grey25", fontface = "bold", size = 6, repel = TRUE, `] <span style="margin-left: 7em;">.alert[`aes(filter = (interactions>=65),label = name))`]</span> **mapping .underline[aes]thetics** .alert[global]: specify font properties .alert[via attributes]: set label to name attribute of node .alert[filter]: only display for nodes (or edges!) that fulfil a given criterion **available aesthetics** many! but most important: label, colour, family, size, and repel --- # 5) scales .alert[`scale_edge_width(range = c(0.1,1.5),guide = "none")`] .alert[`scale_size(range = c(3,10),guide = "none")`] .alert[`scale_fill_manual(values = sw_palette, na.value = "grey",name = "")`] control aesthetics that are mapped within `aes()` **rule of thumb** although optional, set one `scale_*` per parameter in any `aes()` **form of scale functions** `scale_<aes>_<variable type>()` **additional options** `guide` (show in legend or not), `name` (label in legend), `na.value` (value for NA values) --- # 5) scales **node size and edge width (and node/edge alpha)** `scale_size()` and `scale_edge_width()` (`*_continuous` not needed) many parameters, but the most relevant is `range=c(min,max)` **continuous variable to colour** e.g. `scale_(edge_)colour_gradient(low = ...,high = ...)` **categorical variable to colour** e.g. `scale_colour_brewer()`, `scale_colour_manual(values = ...)` **colour or fill?** node shapes 21-25 have both colour (border) and fill all others only have colour <img src="http://www.sthda.com/sthda/RDoc/images/points-symbols.png" style="position:absolute;bottom:5%;right:2%;background:white" height="330"> **misc**: `scale_shape()` and `scale_edge_linetype()` --- # 6) themes .alert[`theme_graph() + theme(legend.position = "bottom")`] control the overall look of the plot `theme()` has a lot of options but we really don't need them `theme_graph()` erases all defaults (e.g. axis, grids, etc.) only worthwile option is `legend.position` <br> .alert[`guides(fill = guide_legend(override.aes = list(size=6)))`] change appearance of geoms in legend (highly optional!) --- # summary **layout** `ggraph(graph,layout = "stress") + ` **edges** `geom_edge_link0(<<global>>,aes(<<via variables>>)) + ` **nodes** `geom_node_point(<global>,aes(<via variables>)) + ` `geom_node_text(<global>,aes(<via variables>)) + ` **scales** `scale_<aes>_<variable type>() + ` (one per variable in `aes()`) **themes** `theme_graph() + theme(legend.position = <position>)` --- # first full example (revisited) ```r ggraph(graph = g,layout = "stress") + geom_edge_link0(edge_colour = "grey25", aes(edge_width = weight)) + geom_node_point(shape = 21, color = "black",stroke = 1, aes(fill = sex,size = interactions)) + geom_node_text(color = "grey25", fontface = "bold", size = 6, repel = TRUE, aes(filter = (interactions>=65),label = name))+ scale_edge_width(range = c(0.1,1.5),guide = "none")+ scale_size(range = c(3,10),guide = "none")+ scale_fill_manual(values = sw_palette, na.value = "grey",name = "")+ theme_graph() + theme(legend.position = "bottom") + guides(fill = guide_legend(override.aes = list(size=6))) ``` --- # beyond standard plots: layout = "focus" Concentric circles help to emphasize the position of certain nodes in the network. ```r ggraph(g,layout = "focus",focus = 19)+ draw_circle(col = "#00BFFF", use = "focus",max.circle = 3)+ geom_edge_link0(edge_colour = "grey25",edge_alpha = 0.5)+ geom_node_point(shape = 21,size = 5,fill = "grey66")+ geom_node_text(aes(filter = (name=="ANAKIN"),label = name))+ theme_graph()+ coord_fixed() ``` `focus=...` : id to be put in the center (other nodes are on concentric circles around it) `draw_circle`: draw the concentric circles `coord_fxed()`: make sure that circles are plot as circles and not ellipses --- layout: false class: normal-bg .center[ <img src="figures/ego_ani_plot.png" height=600> ] --- layout: true class: paint-bg --- # beyond standard plots: layout = "centrality" ```r ggraph(g,layout = "centrality",cent = graph.strength(g))+ draw_circle(col = "#00BFFF", use = "cent")+ geom_edge_link0(edge_colour = "grey25",edge_alpha = 0.5)+ geom_node_point(shape = 21,size = 5,fill = "grey66")+ geom_node_text(aes(filter = (name=="QUI-GON"),label = name))+ theme_graph()+ coord_fixed() ``` `cent = graph.strength(g)`: concentric layout according to weighted degree --- layout: false class: normal-bg .center[ <img src="figures/cent_ani_plot.png" height=600> ] --- layout: true class: paint-bg --- # beyond standard plots: the backbone layout `layout_as_backbone()` is an algorithm that can help emphasize hidden group structures. ```r g <- sample_islands(9,40,0.4,15) g <- simplify(g) V(g)$grp <- as.character(rep(1:9,each = 40)) ``` try the standard first ```r ggraph(g,layout = "stress")+ geom_edge_link0(edge_colour = "black",edge_width = 0.1, edge_alpha = 0.5)+ geom_node_point(shape = 21, size = 3, aes(fill = grp))+ scale_fill_brewer(palette = "Set1")+ theme_graph()+ theme(legend.position = "none") ``` --- layout: false class: normal-bg <img src="slides_files/figure-html/hairball_plot-1.png" style="display: block; margin: auto;" /> --- layout: true class: paint-bg --- # beyond standard plots: backbone try to reveal the hidden group structure with `layout="backbone"` ```r ggraph(g,"backbone")+ geom_edge_link0(aes(edge_color=backbone),edge_width = 0.3)+ geom_node_point(shape = 21,size = 3, aes(fill = grp))+ scale_fill_brewer(palette = "Set1")+ scale_edge_color_manual(values=c(rgb(0,0,0,0.3),rgb(0,0,0,1)))+ theme_graph()+ theme(legend.position = "none") ``` --- layout: false class: normal-bg <img src="slides_files/figure-html/backbone_plot-1.png" style="display: block; margin: auto;" /> --- <img src="http://mr.schochastics.net/img/facebook.png" height=600> --- layout: true class: paint-bg --- # beyond standard plots: large networks `layout = "sparse_stress"` and `layout = "pmds"` work well for up to 50k nodes <table> <thead> <tr> <th style="text-align:left;"> graph </th> <th style="text-align:left;"> stress </th> <th style="text-align:left;"> sparsestress(50) </th> <th style="text-align:left;"> sparsestress(100) </th> <th style="text-align:left;"> drl(igraph) </th> <th style="text-align:left;"> mds(igraph) </th> <th style="text-align:left;"> pivotmds(50) </th> <th style="text-align:left;"> pivotmds(100) </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> 1138bus (n=1138, m=1458) </td> <td style="text-align:left;"> 2.6s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 0.4s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 0.7s </td> <td style="text-align:left;"> 1.7s </td> <td style="text-align:left;"> 1.4s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 0.05s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 0.08s </td> </tr> <tr> <td style="text-align:left;"> 3elt (n=4720, m=13722) </td> <td style="text-align:left;"> 113s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 3.4s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 5.2s </td> <td style="text-align:left;"> 8.4s </td> <td style="text-align:left;"> 95s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 1s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 1.1s </td> </tr> <tr> <td style="text-align:left;"> power grid (n=4941, m=6594) </td> <td style="text-align:left;"> 134s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 3.4s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 5.6s </td> <td style="text-align:left;"> 6.9s </td> <td style="text-align:left;"> 114s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 1s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 1.1s </td> </tr> <tr> <td style="text-align:left;"> pesa (n=11738 m=67828) </td> <td style="text-align:left;"> - </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 18.3s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 26.5s </td> <td style="text-align:left;"> 21s </td> <td style="text-align:left;"> - </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6.3s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 6.8s </td> </tr> <tr> <td style="text-align:left;"> cond-mat(n=13861 m=44619) </td> <td style="text-align:left;"> - </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 22.9s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 33.5s </td> <td style="text-align:left;"> 24.8s </td> <td style="text-align:left;"> - </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 8.0s </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: #ffc93c !important;"> 8.7s </td> </tr> </tbody> </table> --- # layout summary <br> **most useful layouts** `layout = "stress"`: all purpose layout algorithm `layout = "focus"`: ego-centric type layouts `layout = "centrality"`: concentric centrality layout `layout = "backbone"`: emphasize a hidden group structure (**if it exists!!!**) `layout = "sparse_stress"`: large networks <br> **not covered here** multilevel layout algorithm (see [my blog](http://blog.schochastics.net/post/visualizing-multilevel-networks-with-graphlayouts/)) dynamic layout algorithm (see [github](https://github.com/schochastics/graphlayouts#dynamic-layouts)) constrained stress layout algorithm --- # beyond standard plots: flow maps & edgebundling R package `edgebundle` (github.com/schochastics/edgebundle) <img src="slides_files/figure-html/edgebundle-1.png" style="display: block; margin: auto;" /> --- layout: false class: black-bg .center[ <img src = "https://github.com/schochastics/edgebundle/raw/main/man/figures/flights_fdeb.png" height="700px"> ] --- class: black-bg .center[ <img src = "https://github.com/schochastics/edgebundle/raw/main/man/figures/flights_heb.png" height="700px"> ] --- class: black-bg .center[ <img src = "https://github.com/schochastics/edgebundle/raw/main/man/figures/flights_seb.png" height="700px"> ] --- class: normal-bg .center[ <img src = "https://github.com/schochastics/edgebundle/raw/main/man/figures/cali2010_flow.png" height="700px"> ] --- class: normal-bg .center[ <img src="http://minard.schochastics.net/img/038/viz.png" width="1200px" style="position:absolute;left:0%;top:10%"> ] --- class: normal-bg .center[ <img src="https://github.com/schochastics/edgebundle/raw/main/man/figures/berlin.gif"> ] --- layout: true class: paint-bg --- # additional material **slides** http://talks.schochastics.net/netVizR/slides.html **tutorial** http://mr.schochastics.net/netVizR.html http://graphlayouts.schochastics.net/ **tips and tricks** http://blog.schochastics.net/post/ggraph-tricks-for-common-problems/ **multilayer layouts** http://blog.schochastics.net/post/visualizing-multilevel-networks-with-graphlayouts/ **edgebundling** http://blog.schochastics.net/post/non-hierarchical-edge-bundling-in-r/