

{"id":6917,"date":"2017-10-30T20:16:15","date_gmt":"2017-10-31T01:16:15","guid":{"rendered":"https:\/\/rud.is\/b\/?p=6917"},"modified":"2018-03-10T07:53:58","modified_gmt":"2018-03-10T12:53:58","slug":"gg_tweeting-power-outages","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/","title":{"rendered":"gg_tweet&#8217;ing Power Outages"},"content":{"rendered":"<p>As many folks know, I live in semi-rural Maine and we were hit pretty hard with a wind+rain storm Sunday to Monday. The hrbrmstr compound had no power (besides a generator) and no stable\/high-bandwidth internet (Verizon LTE was heavily congested) since 0500 Monday and still does not as I write this post.<\/p>\n<p>I&#8217;ve played with scraping power outage data from Central Maine Power but there&#8217;s a great Twitter account \u2014\u00a0<a href=\"https:\/\/mobile.twitter.com\/PowerOutage_us\">PowerOutage&#95;us<\/a> \u2014 that has done much of the legwork for the entire country. They don&#8217;t cover everything and do not provide easily accessible historical data (likely b\/c evil folks wld steal it w\/o payment or credit) but they do have a site you can poke at and do provide updates via Twitter. As you&#8217;ve seen in a previous post, we can use the <code>rtweet<\/code> package to easily read Twitter data. And, the power outage tweets are regular <em>enough<\/em> to identify and parse. But raw data is so&hellip;<em>raw<\/em>.<\/p>\n<p>While one <em>could<\/em> graph data just for one&#8217;s self, I decided to marry this power scraping capability with a recent idea I&#8217;ve been toying with adding to <code>hrbrthemes<\/code> or <code>ggalt<\/code>: <code>gg_tweet()<\/code>. Imagine being able to take a ggplot2 object and &#8220;plot&#8221; it to Twitter, fully conforming to Twitter&#8217;s stream or card image sizes. By conforming to these size constraints, they don&#8217;t get cropped in the timeline view (if you allow images to be previewed in-timeline). This is even more powerful if you have some helper functions for proper theme-ing (font sizes especially need to be tweaked). Enter <code>gg_tweet()<\/code>.<\/p>\n<h2>Power Scraping<\/h2>\n<p>We&#8217;ll cover scraping @PowerOutage_us first, but we&#8217;ll start with all the packages we&#8217;ll need and a helper function to convert power outage estimates to numeric values:<\/p>\n<pre id=\"powertweet01\"><code class=\"language-r\">library(httr)\r\nlibrary(magick)\r\nlibrary(rtweet)\r\nlibrary(stringi)\r\nlibrary(hrbrthemes)\r\nlibrary(tidyverse)\r\n\r\nwords_to_num &lt;- function(x) {\r\n  map_dbl(x, ~{\r\n    val &lt;- stri_match_first_regex(.x, &quot;^([[:print:]]+) #PowerOutages&quot;)[,2]\r\n    mul &lt;- case_when(\r\n      stri_detect_regex(val, &quot;[Kk]&quot;) ~ 1000,\r\n      stri_detect_regex(val, &quot;[Mm]&quot;) ~ 1000000,\r\n      TRUE ~ 1\r\n    ) \r\n    val &lt;- stri_replace_all_regex(val, &quot;[^[:digit:]\\\\.]&quot;, &quot;&quot;)\r\n    as.numeric(val) * mul \r\n  })\r\n}<\/code><\/pre>\n<p>Now, I can&#8217;t cover setting up <code>rtweet<\/code> OAuth here. The vignette and package web site do that well.<\/p>\n<p>The bot tweets infrequently enough that this is really all we need (though, bump up <code>n<\/code> as you need to):<\/p>\n<pre id=\"powertweet02\"><code class=\"language-r\">outage &lt;- get_timeline(&quot;PowerOutage_us&quot;, n=300)<\/code><\/pre>\n<p>Yep, that gets the last 300 tweets from said account. It&#8217;s amazingly simple.<\/p>\n<p>Now, the outage tweets for the east coast \/ northeast are not individually uniform but collectively they are (there&#8217;s a pattern that may change but you can tweak this if they do):<\/p>\n<pre id=\"powertweet03\"><code class=\"language-r\">filter(outage, stri_detect_regex(text, &quot;\\\\#(EastCoast|NorthEast)&quot;)) %&gt;% \r\n  mutate(created_at = lubridate::with_tz(created_at, &#039;America\/New_York&#039;)) %&gt;% \r\n  mutate(number_out = words_to_num(text)) %&gt;%  \r\n  ggplot(aes(created_at, number_out)) +\r\n  geom_segment(aes(xend=created_at, yend=0), size=5) +\r\n  scale_x_datetime(date_labels = &quot;%Y-%m-%d\\n%H:%M&quot;, date_breaks=&quot;2 hours&quot;) +\r\n  scale_y_comma(limits=c(0,2000000)) +\r\n  labs(\r\n    x=NULL, y=&quot;# Customers Without Power&quot;,\r\n    title=&quot;Northeast Power Outages&quot;,\r\n    subtitle=&quot;Yay! Twitter as a non-blather data source&quot;,\r\n    caption=&quot;Data via: @PowerOutage_us &lt;https:\/\/twitter.com\/PowerOutage_us&gt;&quot;\r\n  ) -&gt; gg<\/code><\/pre>\n<p>That pipe chain looks for key hashtags (for my area), rejiggers the time zone, and calls the helper function to, say, convert <code>1.2+ Million<\/code> to <code>1200000<\/code>. Finally it builds a mostly complete ggplot2 object (you should make the max Y limit more dynamic).<\/p>\n<p>You can plot that on your own (print <code>gg<\/code>). We&#8217;re here to tweet, so let&#8217;s go into the next section.<\/p>\n<h2>Magick Tweeting<\/h2>\n<p>@opencpu made it possible shunt plot output to a <code>magick<\/code> device. This means we have really precise control over ggplot2 output size as well as the ability to add other graphical components to a ggplot2 plot using <code>magick<\/code> idioms. One thing we need to take into account is &#8220;retina&#8221; plots. They are &mdash; essentially &mdash; double resolution plots (72 => 144 pixels per inch). For the best looking plots we need to go retina, but that also means kicking up base plot theme font sizes a bit. Let&#8217;s build on <code>hrbrthemes::theme_ipsum_rc()<\/code> a bit and make a <code>theme_tweet_rc()<\/code>:<\/p>\n<pre id=\"powertweet04\"><code class=\"language-r\">theme_tweet_rc &lt;- function(grid = &quot;XY&quot;, style = c(&quot;stream&quot;, &quot;card&quot;), retina=TRUE) {\r\n  \r\n  style &lt;- match.arg(tolower(style), c(&quot;stream&quot;, &quot;card&quot;))\r\n  \r\n  switch(\r\n    style, \r\n    stream = c(24, 18, 16, 14, 12),\r\n    card = c(22, 16, 14, 12, 10)\r\n  ) -&gt; font_sizes\r\n  \r\n  theme_ipsum_rc(\r\n    grid = grid, \r\n    plot_title_size = font_sizes[1], \r\n    subtitle_size = font_sizes[2], \r\n    axis_title_size = font_sizes[3], \r\n    axis_text_size = font_sizes[4], \r\n    caption_size = font_sizes[5]\r\n  )\r\n  \r\n}<\/code><\/pre>\n<p>Now, we just need a way to take a ggplot2 object and shunt it off to twitter. The following <code>gg_tweet()<\/code> function does not (now) use <code>rtweet<\/code> as I&#8217;ll likely add it to either <code>ggalt<\/code> or <code>hrbrthemes<\/code> and want to keep dependencies to a minimum. I may opt-in to bypass the current method since it relies on environment variables vs an RDS file for app credential storage. Regardless, one thing I wanted to do here was provide a way to preview the image before tweeting.<\/p>\n<p>So you pass in a ggplot2 object (likely adding the tweet theme to it) and a Twitter status text (there&#8217;s a TODO to check the length for 140c compliance) plus choose a style (stream or card, defaulting to stream) and decide on whether you&#8217;re cool with the &#8220;retina&#8221; default.<\/p>\n<p>Unless you <em>tell<\/em> it to send the tweet it won&#8217;t, giving you a chance to preview the image before sending, just in case you want to tweak it a bit before committing it to the Twitterverse. It als returns the <code>magick<\/code> object it creates in the event you want to do something more with it:<\/p>\n<pre id=\"powertweet05\"><code class=\"language-r\">gg_tweet &lt;- function(g, status = &quot;ggplot2 image&quot;, style = c(&quot;stream&quot;, &quot;card&quot;), \r\n                     retina=TRUE, send = FALSE) {\r\n  \r\n  style &lt;- match.arg(tolower(style), c(&quot;stream&quot;, &quot;card&quot;))\r\n  \r\n  switch(\r\n    style, \r\n    stream = c(w=1024, h=512),\r\n    card = c(w=800, h=320)\r\n  ) -&gt; dims\r\n  \r\n  dims[&quot;res&quot;] &lt;- 72\r\n  \r\n  if (retina) dims &lt;- dims * 2\r\n  \r\n  fig &lt;- image_graph(width=dims[&quot;w&quot;], height=dims[&quot;h&quot;], res=dims[&quot;res&quot;])\r\n  print(g)\r\n  dev.off()\r\n  \r\n  if (send) {\r\n    \r\n    message(&quot;Posting image to twitter...&quot;)\r\n    \r\n    tf &lt;- tempfile(fileext = &quot;.png&quot;)\r\n    image_write(fig, tf, format=&quot;png&quot;)\r\n    \r\n    # Create an app at apps.twitter.com w\/callback URL of http:\/\/127.0.0.1:1410\r\n    # Save the app name, consumer key and secret to the following\r\n    # Environment variables\r\n    \r\n    app &lt;- oauth_app(\r\n      appname = Sys.getenv(&quot;TWITTER_APP_NAME&quot;),\r\n      key = Sys.getenv(&quot;TWITTER_CONSUMER_KEY&quot;),\r\n      secret = Sys.getenv(&quot;TWITTER_CONSUMER_SECRET&quot;)\r\n    )\r\n    \r\n    twitter_token &lt;- oauth1.0_token(oauth_endpoints(&quot;twitter&quot;), app)\r\n    \r\n    POST(\r\n      url = &quot;https:\/\/api.twitter.com\/1.1\/statuses\/update_with_media.json&quot;,\r\n      config(token = twitter_token), \r\n      body = list(\r\n        status = status,\r\n        media = upload_file(path.expand(tf))\r\n      )\r\n    ) -&gt; res\r\n    \r\n    warn_for_status(res)\r\n    \r\n    unlink(tf)\r\n    \r\n  }\r\n  \r\n  fig\r\n  \r\n}<\/code><\/pre>\n<h2>Two Great Tastes That Taste Great Together<\/h2>\n<p>We can combine the power outage scraper &amp; plotter with the tweeting code and just do:<\/p>\n<pre id=\"powertweet06\"><code class=\"language-r\">gg_tweet(\r\n  gg + theme_tweet_rc(grid=&quot;Y&quot;),\r\n  status = &quot;Progress! #rtweet #gg_tweet&quot;,\r\n  send=TRUE\r\n)<\/code><\/pre>\n<p>That was, in-fact, the last power outage tweet I sent.<\/p>\n<h2>Next Steps<\/h2>\n<p>Ironically, given current levels of U.S. news and public &#8220;discourse&#8221; on Twitter and some inane machinations in my own area of domain expertise (cyber), <code>gg_tweet()<\/code> is likely one of the few ways I&#8217;ll be interacting with Twitter for a while. You can ping me on Keybase \u2014\u00a0<a href=\"https:\/\/keybase.io\/hrbrmstr\">hrbrmstr<\/a> \u2014 or join the <code>rstats<\/code> <a href=\"https:\/\/keybase.io\/blog\/introducing-keybase-teams\">Keybase team<\/a> via <code>keybase team request-access rstats<\/code> if you need to poke me for anything for a while.<\/p>\n<h2>FIN<\/h2>\n<p>Kick the tyres and watch for <code>gg_tweet()<\/code> ending up in <code>ggalt<\/code> or <code>hrbrthemes<\/code>. Don&#8217;t hesitate to suggest (or code up) feature requests. This is still an idea in-progress and definitely not ready for prime time without a bit more churning. (Also, <code>words_to_num()<\/code> can be optimized, it was hastily crafted).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As many folks know, I live in semi-rural Maine and we were hit pretty hard with a wind+rain storm Sunday to Monday. The hrbrmstr compound had no power (besides a generator) and no stable\/high-bandwidth internet (Verizon LTE was heavily congested) since 0500 Monday and still does not as I write this post. I&#8217;ve played with [&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":false,"_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":[753,91,655],"tags":[810],"class_list":["post-6917","post","type-post","status-publish","format-standard","hentry","category-ggplot","category-r","category-twitter-2","tag-post"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>gg_tweet&#039;ing 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\/2017\/10\/30\/gg_tweeting-power-outages\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"gg_tweet&#039;ing Power Outages - rud.is\" \/>\n<meta property=\"og:description\" content=\"As many folks know, I live in semi-rural Maine and we were hit pretty hard with a wind+rain storm Sunday to Monday. The hrbrmstr compound had no power (besides a generator) and no stable\/high-bandwidth internet (Verizon LTE was heavily congested) since 0500 Monday and still does not as I write this post. I&#8217;ve played with [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2017-10-31T01:16:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-03-10T12:53:58+00:00\" \/>\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=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/10\\\/30\\\/gg_tweeting-power-outages\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/10\\\/30\\\/gg_tweeting-power-outages\\\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"gg_tweet&#8217;ing Power Outages\",\"datePublished\":\"2017-10-31T01:16:15+00:00\",\"dateModified\":\"2018-03-10T12:53:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/10\\\/30\\\/gg_tweeting-power-outages\\\/\"},\"wordCount\":899,\"commentCount\":3,\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"keywords\":[\"post\"],\"articleSection\":[\"ggplot\",\"R\",\"twitter\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/10\\\/30\\\/gg_tweeting-power-outages\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/10\\\/30\\\/gg_tweeting-power-outages\\\/\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/10\\\/30\\\/gg_tweeting-power-outages\\\/\",\"name\":\"gg_tweet'ing Power Outages - rud.is\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\"},\"datePublished\":\"2017-10-31T01:16:15+00:00\",\"dateModified\":\"2018-03-10T12:53:58+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/10\\\/30\\\/gg_tweeting-power-outages\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/10\\\/30\\\/gg_tweeting-power-outages\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2017\\\/10\\\/30\\\/gg_tweeting-power-outages\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/rud.is\\\/b\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"gg_tweet&#8217;ing 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":"gg_tweet'ing 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\/2017\/10\/30\/gg_tweeting-power-outages\/","og_locale":"en_US","og_type":"article","og_title":"gg_tweet'ing Power Outages - rud.is","og_description":"As many folks know, I live in semi-rural Maine and we were hit pretty hard with a wind+rain storm Sunday to Monday. The hrbrmstr compound had no power (besides a generator) and no stable\/high-bandwidth internet (Verizon LTE was heavily congested) since 0500 Monday and still does not as I write this post. I&#8217;ve played with [&hellip;]","og_url":"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/","og_site_name":"rud.is","article_published_time":"2017-10-31T01:16:15+00:00","article_modified_time":"2018-03-10T12:53:58+00:00","author":"hrbrmstr","twitter_card":"summary_large_image","twitter_misc":{"Written by":"hrbrmstr","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"gg_tweet&#8217;ing Power Outages","datePublished":"2017-10-31T01:16:15+00:00","dateModified":"2018-03-10T12:53:58+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/"},"wordCount":899,"commentCount":3,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"keywords":["post"],"articleSection":["ggplot","R","twitter"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/","url":"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/","name":"gg_tweet'ing Power Outages - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"datePublished":"2017-10-31T01:16:15+00:00","dateModified":"2018-03-10T12:53:58+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2017\/10\/30\/gg_tweeting-power-outages\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"gg_tweet&#8217;ing 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-1Nz","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":6930,"url":"https:\/\/rud.is\/b\/2017\/11\/02\/yet-another-power-outages-post-full-tidyverse-edition\/","url_meta":{"origin":6917,"position":0},"title":"Yet-Another-Power Outages Post : Full Tidyverse Edition","author":"hrbrmstr","date":"2017-11-02","format":false,"excerpt":"This past weekend, violent windstorms raged through New England. We \u2014 along with over 500,000 other Mainers \u2014 went \"dark\" in the wee hours of Monday morning and (this post was published on Thursday AM) we still have no utility-provided power nor high-speed internet access. The children have turned iFeral,\u2026","rel":"","context":"In &quot;R&quot;","block_context":{"text":"R","link":"https:\/\/rud.is\/b\/category\/r\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/11\/plot_zoom_png.png?fit=1200%2C628&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/11\/plot_zoom_png.png?fit=1200%2C628&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/11\/plot_zoom_png.png?fit=1200%2C628&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/11\/plot_zoom_png.png?fit=1200%2C628&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/11\/plot_zoom_png.png?fit=1200%2C628&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":2793,"url":"https:\/\/rud.is\/b\/2013\/11\/27\/mapping-power-outages-in-maine-with-r\/","url_meta":{"origin":6917,"position":1},"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":2803,"url":"https:\/\/rud.is\/b\/2013\/11\/27\/mapping-power-outages-in-maine-dynamically-with-shinyr\/","url_meta":{"origin":6917,"position":2},"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":2846,"url":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/","url_meta":{"origin":6917,"position":3},"title":"Points, Polygons and Power Outages","author":"hrbrmstr","date":"2013-12-27","format":false,"excerpt":"Most of my free coding time has been spent tweaking a D3-based live power outage tracker for Central Maine Power customers (there's also a woefully less-featured Shiny app for it, too). There is some R associated with the D3 vis, but it's limited to a cron job that's makes the\u2026","rel":"","context":"In &quot;Data Visualization&quot;","block_context":{"text":"Data Visualization","link":"https:\/\/rud.is\/b\/category\/data-visualization\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"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":6917,"position":4},"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":2816,"url":"https:\/\/rud.is\/b\/2013\/11\/28\/one-more-timemapping-maine-power-outages-with-d3\/","url_meta":{"origin":6917,"position":5},"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":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/6917","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=6917"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/6917\/revisions"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=6917"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=6917"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=6917"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}