

{"id":2846,"date":"2013-12-27T10:30:09","date_gmt":"2013-12-27T15:30:09","guid":{"rendered":"http:\/\/rud.is\/b\/?p=2846"},"modified":"2017-04-02T22:51:57","modified_gmt":"2017-04-03T03:51:57","slug":"points-polygons-and-power-outages","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/","title":{"rendered":"Points, Polygons and Power Outages"},"content":{"rendered":"<p>Most of my free coding time has been spent tweaking a D3-based <a href=\"https:\/\/rud.is\/outage\/\">live power outage tracker<\/a> for <span class=\"removed_link\" title=\"http:\/\/www.cmpco.com\/\">Central Maine Power<\/span> customers (there&#8217;s also a woefully less-featured <a href=\"http:\/\/datadrivensecurity.info:3838\/outages\/\">Shiny app<\/a> for it, too). There is <i>some<\/i> R associated with the D3 vis, but it&#8217;s limited to a cron job that&#8217;s makes the CSV files for the sparklines in D3 vis by<\/p>\n<ul>\n<li>reading historical outage data from a database of scraped readings I&#8217;ve been keeping<\/li>\n<li>filling out the time series<\/li>\n<li>reducing it to an hourly time series, and<\/li>\n<li>trimming the data set to the last 30 days of records:<\/li>\n<\/ul>\n<pre lang=\"rsplus\">#!\/usr\/bin\/Rscript\r\n# running in a cron job so no spurious text output pls\r\noptions(warn=-1)\r\noptions(show.error.messages=FALSE)\r\n \r\nsuppressMessages(library(methods))\r\nsuppressMessages(library(zoo))\r\nlibrary(chron)\r\nlibrary(xts)\r\nlibrary(reshape2)\r\nlibrary(DBI)\r\nlibrary(RMySQL)\r\n \r\nm <- dbDriver(\"MySQL\");\r\ncon <- dbConnect(m, user='DBUSER', password='DBPASSWORD', host='localhost', dbname='DBNAME');\r\nres <- dbSendQuery(con, \"SELECT * FROM outage\") # cld just pull the 2 fields I need\r\noutages <- fetch(res, n = -1)\r\noutages$ts <- as.POSIXct(gsub(\"\\\\:[0-9]+\\\\..*$\",\"\", outages$ts), format=\"%Y-%m-%d %H:%M\")\r\n\r\n# for each county we have data for\r\nfor (county in unique(outages$county)) {\r\n  \r\n  # get the 2 fields I need (shld prbly filter that in the SELECT)\r\n  outage.raw <- outages[outages$county == county,c(1,4)]\r\n  \r\n  # make it a zoo object\r\n  outage.zoo <- zoo(outage.raw$withoutpower, outage.raw$ts)\r\n  \r\n  # fill out the 15-minute readings\r\n  complete.zoo <- merge(outage.zoo, zoo(, seq(start(outage.zoo), max(outages$ts), by=\"15 min\")), all=TRUE)\r\n  complete.zoo[is.na(complete.zoo)] <- 0\r\n  \r\n  # shrink to hourly and trim at 30 days\r\n  hourly.zoo <- last(to.hourly(complete.zoo), \"30 days\")\r\n  \r\n  # crank out a CSV  \r\n  df <- data.frame(hourly.zoo)\r\n  df <- data.frame(ts=rownames(df), withoutPower=df$complete.zoo.High)\r\n  \r\n  write.csv(df, sprintf(\"OUTPOUT_LOCATION\/%s.csv\",county), row.names=FALSE)\r\n  \r\n}<\/pre>\n<p>I knew there were other power companies in Maine, but CMP is the largest, so I focused my attention on getting data from it. After hearing an outage update on <a href=\"http:\/\/mainepublic.org\/\">MPBN<\/a> I decided to see if <span class=\"removed_link\" title=\"http:\/\/bhe.com\/\">Bangor Hydro Electric<\/span> had scrape-able content and it turns out there was a lovely (well, as lovely as XML can be) <a href=\"http:\/\/apps.bhe.com\/about\/outages\/outage_map.xml\">XML file<\/a> delivered on the page with this \"meh\" Google push-pin map:<\/p>\n<p><center><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2848\" data-permalink=\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/bangor_hydro_electric_-_outage_map\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?fit=1200%2C982&amp;ssl=1\" data-orig-size=\"1200,982\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"Bangor_Hydro_Electric_-_Outage_Map\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?fit=300%2C245&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?fit=510%2C417&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?resize=510%2C417&#038;ssl=1\" alt=\"Bangor_Hydro_Electric_-_Outage_Map\" width=\"510\" height=\"417\" class=\"aligncenter size-large wp-image-2848\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?resize=530%2C433&amp;ssl=1 530w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?resize=150%2C122&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?resize=300%2C245&amp;ssl=1 300w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?resize=535%2C437&amp;ssl=1 535w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?w=1200&amp;ssl=1 1200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?w=1020&amp;ssl=1 1020w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/center><\/p>\n<p>The XML file is used to build the markers for the map and has <code>marker<\/code> tags that look like this:<\/p>\n<pre lang=\"xml\"><marker name=\"Exeter\" outages=\"18\" \r\n        lat=\"44.96218\" lng=\"-69.12253\" \r\n        streets=\"BUTTERS  RD;CHAMPEON  RD;GREENBUSH  RD;\" \r\n        reflabels=\"87757-1;84329-1;85032-1;\"\/><\/pre>\n<p>I'm really only tracking county-level data and BHE does not provide that, even in the huge table of street-level outages that you'll see on that outage page. I decided to use R to aggregate the BHE data to the county level via the \"point-in-polygon\" method.<\/p>\n<h3>Getting Right To the Point<\/h3>\n<p>To perform the aggregation in R, I needed county-level polygons for Maine. I already had that thanks to the previous work, but I wanted to optimize the search process, so I took the <a href=\"https:\/\/www.baruch.cuny.edu\/confluence\/display\/geoportal\/\">US counties shapefile<\/a> and used <code><a href=\"http:\/\/www.gdal.org\/ogr\/index.html\">OGR<\/a><\/code> from the <code><a href=\"http:\/\/www.gdal.org\/\">GDAL<\/a><\/code> (Geospatial Data Abstraction Library) suite to extract just the Maine county polygons:<\/p>\n<pre lang=\"bash\">ogr2ogr -f \"ESRI Shapefile\" \\\r\n        -where \"STATE_NAME = 'MAINE'\" maine.shp counties.shp<\/pre>\n<p>You can see both a reduction in file size and complexity via <code>ogrinfo<\/code>:<\/p>\n<pre lang=\"bash\">$ll *shp\r\n-rwxr-xr-x@ 1 bob  staff  1517624 Jan  8  2010 counties.shp\r\n-rw-r--r--  1 bob  staff    12588 Dec 26 23:03 maine.shp<\/pre>\n<pre lang=\"bash\">$ ogrinfo -sql \"SELECT COUNT(*) FROM counties\" counties.shp\r\nINFO: Open of 'counties.shp'\r\n      using driver 'ESRI Shapefile' successful.\r\n\r\nLayer name: counties\r\nGeometry: Polygon\r\nFeature Count: 1\r\nLayer SRS WKT:\r\n(unknown)\r\nCOUNT_*: Integer (0.0)\r\nOGRFeature(counties):0\r\n  COUNT_* (Integer) = 3141<\/pre>\n<pre lang=\"bash\">$ ogrinfo -sql \"SELECT COUNT(*) FROM maine\" maine.shp\r\nINFO: Open of 'maine.shp'\r\n      using driver 'ESRI Shapefile' successful.\r\n\r\nLayer name: maine\r\nGeometry: Polygon\r\nFeature Count: 1\r\nLayer SRS WKT:\r\n(unknown)\r\nCOUNT_*: Integer (0.0)\r\nOGRFeature(maine):0\r\n  COUNT_* (Integer) = 16<\/pre>\n<p>The conversion reduces the file size from 1.5MB to <b>~12K<\/b> and shrinks the number of polygons from 3,141 to <b>16<\/b>. The <code>counties.shp<\/code> and <code>maine.shp<\/code> shapefiles were built from U.S. census data and have scads more information that you might want to use (i.e. perhaps, for correlation with the outage info, though storms are the prime causal entity for the outages :-):<\/p>\n<pre lang=\"bash\">$ ogrinfo -al -so counties.shp\r\nINFO: Open of 'counties.shp'\r\n      using driver 'ESRI Shapefile' successful.\r\n\r\nLayer name: counties\r\nGeometry: Polygon\r\nFeature Count: 3141\r\nExtent: (-176.806138, 18.921786) - (-66.969271, 71.406235)\r\nLayer SRS WKT:\r\nGEOGCS[\"GCS_WGS_1984\",\r\n    DATUM[\"WGS_1984\",\r\n        SPHEROID[\"WGS_84\",6378137.0,298.257223563]],\r\n    PRIMEM[\"Greenwich\",0.0],\r\n    UNIT[\"Degree\",0.0174532925199433]]\r\nNAME: String (32.0)\r\nSTATE_NAME: String (25.0)\r\nSTATE_FIPS: String (2.0)\r\nCNTY_FIPS: String (3.0)\r\nFIPS: String (5.0)\r\nPOP2000: Integer (9.0)\r\nPOP2007: Integer (9.0)\r\nPOP00_SQMI: Real (10.1)\r\nPOP07_SQMI: Real (7.1)\r\nWHITE: Integer (9.0)\r\nBLACK: Integer (9.0)\r\nAMERI_ES: Integer (9.0)\r\nASIAN: Integer (9.0)\r\nHAWN_PI: Integer (9.0)\r\nOTHER: Integer (9.0)\r\nMULT_RACE: Integer (9.0)\r\nHISPANIC: Integer (9.0)\r\nMALES: Integer (9.0)\r\nFEMALES: Integer (9.0)\r\nAGE_UNDER5: Integer (9.0)\r\nAGE_5_17: Integer (9.0)\r\nAGE_18_21: Integer (9.0)\r\nAGE_22_29: Integer (9.0)\r\nAGE_30_39: Integer (9.0)\r\nAGE_40_49: Integer (9.0)\r\nAGE_50_64: Integer (9.0)\r\nAGE_65_UP: Integer (9.0)\r\nMED_AGE: Real (9.1)\r\nMED_AGE_M: Real (9.1)\r\nMED_AGE_F: Real (9.1)\r\nHOUSEHOLDS: Integer (9.0)\r\nAVE_HH_SZ: Real (9.2)\r\nHSEHLD_1_M: Integer (9.0)\r\nHSEHLD_1_F: Integer (9.0)\r\nMARHH_CHD: Integer (9.0)\r\nMARHH_NO_C: Integer (9.0)\r\nMHH_CHILD: Integer (9.0)\r\nFHH_CHILD: Integer (9.0)\r\nFAMILIES: Integer (9.0)\r\nAVE_FAM_SZ: Real (9.2)\r\nHSE_UNITS: Integer (9.0)\r\nVACANT: Integer (9.0)\r\nOWNER_OCC: Integer (9.0)\r\nRENTER_OCC: Integer (9.0)\r\nNO_FARMS97: Real (11.0)\r\nAVG_SIZE97: Real (11.0)\r\nCROP_ACR97: Real (11.0)\r\nAVG_SALE97: Real (7.2)\r\nSQMI: Real (8.1)\r\nOID: Integer (9.0)<\/pre>\n<p>With the new shapefile in hand, the basic workflow to get BHE outages at the county level is:<\/p>\n<ul>\n<li>Read and parse the BHE outages XML file to get the lat\/long pairs<\/li>\n<li>Build a <code>SpatialPoints<\/code> object out of those pairs<\/li>\n<li>Make a <code>SpatialPolygonsDataFrame<\/code> out of the reduced Maine counties shapefile<\/li>\n<li>Overlay the points in the polygons and get the feature metadata intersection (including county)<\/li>\n<li>Aggregate the outage data<\/li>\n<\/ul>\n<p>The R code (below) does all that and is liberally commented.  One has to appreciate how succinct the XML parsing is and the beautiful simplicity of the <code>over()<\/code> function (which does all the really hard work).<\/p>\n<pre lang=\"rsplus\">library(XML)\r\nlibrary(maptools)\r\nlibrary(sp)\r\nlibrary(plyr)\r\n\r\n# Small script to get county-level outage info from Bangor Hydro\r\n# Electric's town(-ish) level info\r\n#\r\n# BHE's outage google push-pin map is at\r\n#   http:\/\/apps.bhe.com\/about\/outages\/outage_map.cfm\r\n\r\n# read BHE outage XML file that was intended for the google map\r\n# yep. One. Line. #takethatpython\r\n\r\ndoc <- xmlTreeParse(\"http:\/\/apps.bhe.com\/about\/outages\/outage_map.xml\", \r\n                    useInternalNodes=TRUE)\r\n\r\n# xmlToDataFrame() coughed up blood on that simple file, so we have to\r\n# resort to menial labor to bend the XML to our will\r\n\r\ndoc.ls <- xmlToList(doc)\r\ndoc.attrs <- doc.ls$.attrs\r\ndoc.ls$.attrs <- NULL\r\n\r\n# this does the data frame conversion magic, tho it winces a bit\r\n\r\nsuppressWarnings(doc.df <- data.frame(do.call(rbind, doc.ls), \r\n                                      stringsAsFactors=FALSE))\r\n\r\n# need numbers for some of the columns (vs strings)\r\n\r\ndoc.df$outages <- as.numeric(doc.df$outages)\r\ndoc.df$lat <- as.numeric(doc.df$lat)\r\ndoc.df$lng <- as.numeric(doc.df$lng)\r\n\r\n# SpatialPoints likes matrices, note that it's in LON, LAT order\r\n# that always messes me up for some reason\r\n\r\ndoc.m <- as.matrix(doc.df[,c(4,3)])\r\ndoc.pts <- SpatialPoints(doc.m)\r\n\r\n# I trimmed down the country-wide counties file from\r\n#   http:\/\/www.baruch.cuny.edu\/geoportal\/data\/esri\/usa\/census\/counties.zip\r\n# with\r\n#   ogr2ogr -f \"ESRI Shapefile\" -where \"STATE_NAME = 'MAINE'\" maine.shp counties.shp\r\n# to both save load time and reduce the number of iterations for over() later\r\n\r\ncounties <- readShapePoly(\"maine.shp\", repair=TRUE, IDvar=\"NAME\")\r\n\r\n# So, all the above was pretty much just for this next line which does  \r\n# the \"is this point 'a' in polygon 'b' automagically for us. \r\n\r\nfound.pts <- over(doc.pts, counties)\r\n\r\n# steal the column we need (county name) and squirrel it away with outage count\r\n\r\ndoc.df$county <- found.pts$NAME\r\ndoc.sub <- doc.df[,c(2,7)]\r\n\r\n# aggregate the result to get outage count by county\r\n\r\ncount(doc.sub, c(\"county\"), wt_var=\"outages\")\r\n\r\n##      county freq\r\n##1    Hancock 4440\r\n##2  Penobscot  869\r\n##3      Waldo   28\r\n##4 Washington  545\r\n##5       <NA>  328<\/pre>\n<p>Astute readers will notice unresolved points (the <code>NAs<\/code>). I suspect they are right on coastal boundaries that were probably missed in these simplified county polygons. We can see what they are by looking at the <code>NA<\/code> entries in the merged data frame:<\/p>\n<pre lang=\"rsplus\">doc.df[is.na(doc.df$county),c(1:4)]\r\n           name outages      lat       lng\r\n35    Deer Isle       1 44.22451 -68.67778\r\n38   Harborside     166 44.34900 -68.81555\r\n39     Sorrento      43 44.47341 -68.17723\r\n62    Bucksport      71 44.57369 -68.79562\r\n70    Penobscot      40 44.44552 -68.81780\r\n78      Bernard       1 44.24119 -68.35585\r\n79   Stonington       5 44.15619 -68.66669\r\n80 Roque Bluffs       1 44.61286 -67.47971<\/pre>\n<p>But a map would be more useful for those not familiar with Maine geography\/extents:<\/p>\n<p><center><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2857\" data-permalink=\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/plot_zoom-3\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?fit=1170%2C616&amp;ssl=1\" data-orig-size=\"1170,616\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"Plot_Zoom\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?fit=300%2C157&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?fit=510%2C268&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?resize=510%2C268&#038;ssl=1\" alt=\"Plot_Zoom\" width=\"510\" height=\"268\" class=\"aligncenter size-large wp-image-2857\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?resize=530%2C279&amp;ssl=1 530w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?resize=150%2C78&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?resize=300%2C157&amp;ssl=1 300w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?resize=535%2C281&amp;ssl=1 535w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?w=1170&amp;ssl=1 1170w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom.png?w=1020&amp;ssl=1 1020w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/center><\/p>\n<pre lang=\"rsplus\">library(ggplot2)\r\n\r\nff = fortify(counties, region = \"NAME\")\r\n\r\nmissing <- doc.df[is.na(doc.df$county),]\r\n\r\ngg <- ggplot(ff, aes(x = long, y = lat))\r\ngg <- gg + geom_path(aes(group = group), size=0.15, fill=\"black\")\r\ngg <- gg + geom_point(data=missing, aes(x=lng, y=lat), \r\n                      color=\"#feb24c\", size=3)\r\ngg <- gg + coord_map(xlim=extendrange(range(missing$lng)), ylim=extendrange(range(missing$lat)))\r\ngg <- gg + theme_bw()\r\ngg <- gg + labs(x=\"\", y=\"\")\r\ngg <- gg + theme(plot.background = element_rect(fill = \"transparent\",colour = NA),\r\n                 panel.border = element_blank(),\r\n                 panel.background =element_rect(fill = \"transparent\",colour = NA),\r\n                 panel.grid = element_blank(),\r\n                 axis.text = element_blank(),\r\n                 axis.ticks = element_blank(),\r\n                 legend.position=\"right\",\r\n                 legend.title=element_blank())\r\ngg<\/pre>\n<p>The \"zoom in\" is done by taking and slightly extending the range of the extracted points via <code>range()<\/code> and <code>extendrange()<\/code>, reproduced below:<\/p>\n<pre lang=\"rsplus\">range(missing$lng)\r\n[1] -68.81780 -67.47971\r\nrange(missing$lat)\r\n[1] 44.15619 44.61286\r\n\r\nextendrange(range(missing$lng))\r\n[1] -68.88470 -67.41281\r\nextendrange(range(missing$lat))\r\n[1] 44.13336 44.63569<\/pre>\n<p>It turns out my suspicion was right, so to use this in \"production\" I'll need a more accurate shapefile for Maine counties (which I have, but <a href=\"https:\/\/www.fantasyflightgames.com\/en\/products\/descent-journeys-in-the-dark-second-edition\/\">Descent<\/a> is calling me, so it will have to wait for another day).<\/p>\n<p>I'll leave you with a non-Google push-pin map of outages that you can build upon (it needs some tweaking):<\/p>\n<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2861\" data-permalink=\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/plot_zoom-2-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?fit=1088%2C1378&amp;ssl=1\" data-orig-size=\"1088,1378\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"Plot_Zoom-2\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?fit=236%2C300&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?fit=510%2C646&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?resize=510%2C646&#038;ssl=1\" alt=\"Plot_Zoom-2\" width=\"510\" height=\"646\" class=\"aligncenter size-large wp-image-2861\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?resize=530%2C671&amp;ssl=1 530w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?resize=118%2C150&amp;ssl=1 118w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?resize=236%2C300&amp;ssl=1 236w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?resize=535%2C677&amp;ssl=1 535w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?w=1088&amp;ssl=1 1088w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Plot_Zoom-2.png?w=1020&amp;ssl=1 1020w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/p>\n<pre lang=\"rsplus\">gg <- ggplot(ff, aes(x = long, y = lat))\r\ngg <- gg + geom_polygon(aes(group = group), size=0.15, fill=\"black\", color=\"#7f7f7f\")\r\ngg <- gg + geom_point(data=doc.df, aes(x=lng, y=lat, alpha=outages, size=outages), \r\n                      color=\"#feb24c\")\r\ngg <- gg + coord_map(xlim=c(-71.5,-66.75), ylim=c(43,47.5))\r\ngg <- gg + theme_bw()\r\ngg <- gg + labs(x=\"\", y=\"\")\r\ngg <- gg + theme(plot.background = element_rect(fill = \"transparent\",colour = NA),\r\n                 panel.border = element_blank(),\r\n                 panel.background =element_rect(fill = \"transparent\",colour = NA),\r\n                 panel.grid = element_blank(),\r\n                 axis.text = element_blank(),\r\n                 axis.ticks = element_blank(),\r\n                 legend.position=\"right\",\r\n                 legend.title=element_blank())\r\ngg<\/pre>\n<p>You can find all the R code in one, compact <a href=\"https:\/\/gist.github.com\/hrbrmstr\/8148412\">gist<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Most of my free coding time has been spent tweaking a D3-based live power outage tracker for Central Maine Power customers (there&#8217;s also a woefully less-featured Shiny app for it, too). There is some R associated with the D3 vis, but it&#8217;s limited to a cron job that&#8217;s makes the CSV files for the sparklines [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":3,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":""},"categories":[678,673,674,63,707,706,7,91],"tags":[],"class_list":["post-2846","post","type-post","status-publish","format-standard","hentry","category-data-visualization","category-datavis-2","category-dataviz","category-development","category-maine","category-maps","category-programming","category-r"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Points, Polygons and Power Outages - rud.is<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Points, Polygons and Power Outages - rud.is\" \/>\n<meta property=\"og:description\" content=\"Most of my free coding time has been spent tweaking a D3-based live power outage tracker for Central Maine Power customers (there&#8217;s also a woefully less-featured Shiny app for it, too). There is some R associated with the D3 vis, but it&#8217;s limited to a cron job that&#8217;s makes the CSV files for the sparklines [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2013-12-27T15:30:09+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-04-03T03:51:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map-530x433.png\" \/>\n<meta name=\"author\" content=\"hrbrmstr\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"hrbrmstr\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"Points, Polygons and Power Outages\",\"datePublished\":\"2013-12-27T15:30:09+00:00\",\"dateModified\":\"2017-04-03T03:51:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/\"},\"wordCount\":615,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\"},\"image\":{\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map-530x433.png\",\"articleSection\":[\"Data Visualization\",\"DataVis\",\"DataViz\",\"Development\",\"maine\",\"maps\",\"Programming\",\"R\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/\",\"url\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/\",\"name\":\"Points, Polygons and Power Outages - rud.is\",\"isPartOf\":{\"@id\":\"https:\/\/rud.is\/b\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map-530x433.png\",\"datePublished\":\"2013-12-27T15:30:09+00:00\",\"dateModified\":\"2017-04-03T03:51:57+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#primaryimage\",\"url\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?fit=1200%2C982&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?fit=1200%2C982&ssl=1\",\"width\":1200,\"height\":982},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/rud.is\/b\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Points, Polygons and Power Outages\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/rud.is\/b\/#website\",\"url\":\"https:\/\/rud.is\/b\/\",\"name\":\"rud.is\",\"description\":\"&quot;In God we trust. All others must bring data&quot;\",\"publisher\":{\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/rud.is\/b\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\",\"name\":\"hrbrmstr\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1\",\"url\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1\",\"width\":460,\"height\":460,\"caption\":\"hrbrmstr\"},\"logo\":{\"@id\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1\"},\"description\":\"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7\",\"sameAs\":[\"http:\/\/rud.is\"],\"url\":\"https:\/\/rud.is\/b\/author\/hrbrmstr\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Points, Polygons and Power Outages - rud.is","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/","og_locale":"en_US","og_type":"article","og_title":"Points, Polygons and Power Outages - rud.is","og_description":"Most of my free coding time has been spent tweaking a D3-based live power outage tracker for Central Maine Power customers (there&#8217;s also a woefully less-featured Shiny app for it, too). There is some R associated with the D3 vis, but it&#8217;s limited to a cron job that&#8217;s makes the CSV files for the sparklines [&hellip;]","og_url":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/","og_site_name":"rud.is","article_published_time":"2013-12-27T15:30:09+00:00","article_modified_time":"2017-04-03T03:51:57+00:00","og_image":[{"url":"https:\/\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map-530x433.png","type":"","width":"","height":""}],"author":"hrbrmstr","twitter_card":"summary_large_image","twitter_misc":{"Written by":"hrbrmstr","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"Points, Polygons and Power Outages","datePublished":"2013-12-27T15:30:09+00:00","dateModified":"2017-04-03T03:51:57+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/"},"wordCount":615,"commentCount":1,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"image":{"@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map-530x433.png","articleSection":["Data Visualization","DataVis","DataViz","Development","maine","maps","Programming","R"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/","url":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/","name":"Points, Polygons and Power Outages - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#primaryimage"},"image":{"@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map-530x433.png","datePublished":"2013-12-27T15:30:09+00:00","dateModified":"2017-04-03T03:51:57+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#primaryimage","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?fit=1200%2C982&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/12\/Bangor_Hydro_Electric_-_Outage_Map.png?fit=1200%2C982&ssl=1","width":1200,"height":982},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"Points, Polygons and Power Outages"}]},{"@type":"WebSite","@id":"https:\/\/rud.is\/b\/#website","url":"https:\/\/rud.is\/b\/","name":"rud.is","description":"&quot;In God we trust. All others must bring data&quot;","publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rud.is\/b\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886","name":"hrbrmstr","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","width":460,"height":460,"caption":"hrbrmstr"},"logo":{"@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1"},"description":"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7","sameAs":["http:\/\/rud.is"],"url":"https:\/\/rud.is\/b\/author\/hrbrmstr\/"}]}},"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p23idr-JU","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":2793,"url":"https:\/\/rud.is\/b\/2013\/11\/27\/mapping-power-outages-in-maine-with-r\/","url_meta":{"origin":2846,"position":0},"title":"Mapping Power Outages In Maine With R","author":"hrbrmstr","date":"2013-11-27","format":false,"excerpt":"UPDATE: A Shiny (dynamic) version of this is now available. We had yet-another power outage this morning due to the weird weather patterns of the week and it was the final catalyst I needed to crank out some R code to map the affected counties. Central Maine Power provides an\u2026","rel":"","context":"In &quot;Charts &amp; Graphs&quot;","block_context":{"text":"Charts &amp; Graphs","link":"https:\/\/rud.is\/b\/category\/charts-graphs\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Plot_Zoom.png?fit=530%2C680&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Plot_Zoom.png?fit=530%2C680&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Plot_Zoom.png?fit=530%2C680&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":2816,"url":"https:\/\/rud.is\/b\/2013\/11\/28\/one-more-timemapping-maine-power-outages-with-d3\/","url_meta":{"origin":2846,"position":1},"title":"One More Time\u2026Mapping Maine Power Outages with D3","author":"hrbrmstr","date":"2013-11-28","format":false,"excerpt":"It started with a local R version and migrated to a Shiny version and is now in full D3 glory. Some down time gave me the opportunity to start a basic D3 version of the outage map, but it needs a bit of work as it relies on a page\u2026","rel":"","context":"In &quot;d3&quot;","block_context":{"text":"d3","link":"https:\/\/rud.is\/b\/category\/d3\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Central_Maine_Power_Live_Outage_Map-2.png?fit=757%2C649&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Central_Maine_Power_Live_Outage_Map-2.png?fit=757%2C649&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Central_Maine_Power_Live_Outage_Map-2.png?fit=757%2C649&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Central_Maine_Power_Live_Outage_Map-2.png?fit=757%2C649&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":3141,"url":"https:\/\/rud.is\/b\/2014\/11\/27\/power-outage-impact-choropleths-in-5-steps-in-r-featuring-rvest-rstudio-projects\/","url_meta":{"origin":2846,"position":2},"title":"Power Outage Impact Choropleths In 5 Steps in R (featuring rvest &#038; RStudio &#8220;Projects&#8221;)","author":"hrbrmstr","date":"2014-11-27","format":false,"excerpt":"I and @awpiii were trading news about the power outages in Maine & New Hampshire last night and he tweeted the link to the @PSNH [Outage Map](http:\/\/www.psnh.com\/outage\/). As if the Bing Maps tiles weren't bad enough, the use of a categorical color scale instead of a sequential one[[1](http:\/\/earthobservatory.nasa.gov\/blogs\/elegantfigures\/2011\/05\/20\/qualitative-vs-sequential-color-scales\/)] caused sufficient\u2026","rel":"","context":"In &quot;Charts &amp; Graphs&quot;","block_context":{"text":"Charts &amp; Graphs","link":"https:\/\/rud.is\/b\/category\/charts-graphs\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2803,"url":"https:\/\/rud.is\/b\/2013\/11\/27\/mapping-power-outages-in-maine-dynamically-with-shinyr\/","url_meta":{"origin":2846,"position":3},"title":"Mapping Power Outages in Maine Dynamically with Shiny\/R","author":"hrbrmstr","date":"2013-11-27","format":false,"excerpt":"I decided to forego the D3 map mentioned in the previous post in favor of a Shiny one since I had 90% of the mapping code written. I binned the ranges into three groups, changed the color over to something more pleasant (with RColorBrewer), added an interactive table for the\u2026","rel":"","context":"In &quot;data driven security&quot;","block_context":{"text":"data driven security","link":"https:\/\/rud.is\/b\/category\/data-driven-security\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/162.243.111.4_3838_outages_.png?fit=470%2C735&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":2728,"url":"https:\/\/rud.is\/b\/2013\/09\/28\/obamacare-jobs-r-d3\/","url_meta":{"origin":2846,"position":4},"title":"Visualizing &#8220;ObamaCare-related&#8221; Job Cuts","author":"hrbrmstr","date":"2013-09-28","format":false,"excerpt":"UPDATE: Added some extra visualization elements since this post went live. New select menu and hover text for individual job impact detail lines in the table. I was reviewing RSS feeds when I came across this story about \"ObamaCare Employer Mandate: A List Of Cuts To Work Hours, Jobs\" over\u2026","rel":"","context":"In &quot;Charts &amp; Graphs&quot;","block_context":{"text":"Charts &amp; Graphs","link":"https:\/\/rud.is\/b\/category\/charts-graphs\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/09\/oc-snap.png.png?fit=945%2C660&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/09\/oc-snap.png.png?fit=945%2C660&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/09\/oc-snap.png.png?fit=945%2C660&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/09\/oc-snap.png.png?fit=945%2C660&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":3028,"url":"https:\/\/rud.is\/b\/2014\/09\/20\/chartingmapping-the-scottish-vote-with-r-rvestdplyrtidyrtopojsonggplot\/","url_meta":{"origin":2846,"position":5},"title":"Charting\/Mapping the Scottish Vote with R (an rvest\/dplyr\/tidyr\/TopoJSON\/ggplot tutorial)","author":"hrbrmstr","date":"2014-09-20","format":false,"excerpt":"The BBC did a pretty good job [live tracking the Scotland secession vote](http:\/\/www.bbc.com\/news\/events\/scotland-decides\/results), but I really didn't like the color scheme they chose and decided to use the final tally site as the basis for another tutorial using the tools from the Hadleyverse and taking advantage of the fact that\u2026","rel":"","context":"In &quot;Charts &amp; Graphs&quot;","block_context":{"text":"Charts &amp; Graphs","link":"https:\/\/rud.is\/b\/category\/charts-graphs\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/2846","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/comments?post=2846"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/2846\/revisions"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=2846"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=2846"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=2846"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}