

{"id":13382,"date":"2022-04-03T07:32:01","date_gmt":"2022-04-03T12:32:01","guid":{"rendered":"https:\/\/rud.is\/b\/?p=13382"},"modified":"2022-04-03T14:20:24","modified_gmt":"2022-04-03T19:20:24","slug":"turning-ggplot2-into-a-pos-point-of-sale-system","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/","title":{"rendered":"Turning {ggplot2} Into a PoS (Point-of-Sale) System"},"content":{"rendered":"<p>At the end of March, I caught a fleeting tweet that showcased an Epson thermal receipt printer generating a new &#8220;ticket&#8221; whenever a new GitHub issue was filed on a repository. @aschmelyun documents it well in <a href=\"https:\/\/aschmelyun.com\/blog\/i-built-a-receipt-printer-for-github-issues\/\">this blog post<\/a>. It&#8217;s a pretty cool hack, self-contained on a Pi Zero.<\/p>\n<p>Andrew&#8217;s project birthed an idea: could I write an R package that will let me plot {ggplot2}\/{grid} objects to it? The form factor of the receipt printer is tiny (~280 &#8220;pixels&#8221; wide), but the near infinite length of the paper means one can play with some data visualizations that cannot be done in other formats (and it would be cool to be able to play with other content to print to it in and outside of R).<\/p>\n<p>One of the features that makes Andrew&#8217;s hack extra cool is that he used an Epson receipt printer model that was USB connected. I don&#8217;t see the need to dedicate and extra piece of plastic, metal, and silicon to manage the printing experience, especially since I already have a big linux server where I run personal, large scale data science jobs. I ended up getting a used (lots of restaurants close down each week) <a href=\"https:\/\/www.epson.com.au\/pos\/products\/receiptprinters\/DisplaySpecs.asp?id=tmt88v\">Epson TM-T88V<\/a> off of eBay since it has Ethernet and is supports <a href=\"https:\/\/www.epson-biz.com\/modules\/ref_escpos\/index.php?content_id=2\">ESC\/POS commands<\/a>.<\/p>\n<p>After unpacking it, I needed to get it on the local network. There are many guides out there for this, but <a href=\"https:\/\/www.splitability.com\/pos-hardware\/printers\/epson-tm-t88v-i\/\">this one <\/a> sums up the process pretty well:<\/p>\n<ul>\n<li>Plug the printer in and reset it<\/li>\n<li>Hook up a system directly to it (Ethernet to Ethernet)<\/li>\n<li>Configure your system to use the Epson default IP addressing scheme<\/li>\n<li>Access the web setup page<\/li>\n<li>Configure it to work on your network<\/li>\n<li>Disconnect and restart the printer<\/li>\n<\/ul>\n<p>To make sure everything worked, I <a href=\"https:\/\/github.com\/mike42\/escpos-php\">grabbed one<\/a> of the (weirdly) many projects on GitHub that provided a means for formatting graphics files to an ESC\/POS compatible raster bitmap and processed a simple R-generated png to it, then used <code>netcat<\/code> to shunt the binary blob over to the printer on the default port of <code>9100<\/code>.<\/p>\n<p>I did some initial experiments with {magick}, pulling the graphics bits out of generated plots and then wrapping some R code around doing the conversion. It was clunky and tedious, and I knew there had to be a better way, so I hunted for some C\/C++, Rust, or Go code that already did the conversion and found <a href=\"https:\/\/github.com\/twg\/png2escpos\"><code>png2escpos<\/code><\/a> by The Working Group. However, I&#8217;ve switched to <a href=\"https:\/\/github.com\/petrkutalek\/png2pos\"><code>png2pos<\/code><\/a> by Petr Kutalek as the dithering it does won&#8217;t require the R user to produce only black-and-white plots for them to look good.<\/p>\n<p>I thought about implementing a graphics device to support any R graphics output, but there are enough methods to convert a base R plot to a grid\/grob object that I decided to mimic the functionality of <a href=\"https:\/\/ggplot2.tidyverse.org\/reference\/ggsave.html\"><code>ggsave()<\/code><\/a> and make a <code>ggpos()<\/code> function. The comment annotations in the code snippet below walk you through the extremely basic process:<\/p>\n<pre><code class=\"language-r\">ggpos &lt;- function(plot = ggplot2::last_plot(),\n                  host_pos,\n                  port = 9100L,\n                  scale = 2,\n                  width = 280,\n                  height = 280,\n                  units = \"px\",\n                  dpi = 144,\n                  bg = \"white\",\n                  ...) {\n\n  # we generate a png file using ggsave()\n\n  png_file &lt;- tempfile(fileext = \".png\")\n\n  ggplot2::ggsave(\n    filename = png_file,\n    plot = plot,\n    scale = scale,\n    width = width,\n    height = height,\n    units = units,\n    dpi = dpi,\n    bg = bg,\n    ...\n  )\n\n  # we call an internal C function to convert the generated png file to an ESC\/POS raster bitmap file\n\n  res &lt;- png_to_raster(png_file)\n\n  if (res != \"\") { # if the conversion ended up generating a new file\n\n    # read in the raw bytes\n\n    escpos_raster &lt;- stringi::stri_read_raw(res)\n\n    # open up a binary socket to the printer \n\n    socketConnection(\n      host = host_pos,\n      port = port,\n      open = \"a+b\"\n    ) -&gt; con\n\n    on.exit(close(con))\n\n    # shunt all the bytes over to it\n\n    writeBin(\n      object = escpos_raster,\n      con = con,\n      useBytes = TRUE\n    )\n\n  }\n\n  invisible(res)\n\n}\n<\/code><\/pre>\n<p>The only work I needed to do on the original C code was to have it output directly to a file instead of <code>stdout<\/code>.<\/p>\n<p>Now, plotting to the printer is as straightforward as:<\/p>\n<pre><code class=\"language-r\">library(ggplot2)\nlibrary(escpos)\n\nggplot(mtcars) +\n  geom_point(\n    aes(wt, mpg)\n  ) +\n  labs(\n    title = \"Test of {ggpos}\"\n  ) +\n  theme_ipsum_es(grid=\"XY\") +\n  theme(\n    panel.grid.major.x = element_line(color = \"black\"),\n    panel.grid.major.y = element_line(color = \"black\")\n  ) -&gt; gg\n\nggpos(gg, host_pos = HOSTNAME_OR_IP_ADDRESS_OF_YOUR_PRINTER)\n<\/code><\/pre>\n<p>That code produces this output (I&#8217;m still getting the hang of ripping the spooled paper off this thing):<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"13383\" data-permalink=\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/img_0217\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&amp;ssl=1\" data-orig-size=\"320,369\" 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;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"IMG_0217\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=260%2C300&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?resize=320%2C369&#038;ssl=1\" alt=\"ggplot receipt\" width=\"320\" height=\"369\" class=\"aligncenter size-full wp-image-13383\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?w=320&amp;ssl=1 320w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?resize=260%2C300&amp;ssl=1 260w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?resize=130%2C150&amp;ssl=1 130w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?resize=150%2C173&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?resize=200%2C231&amp;ssl=1 200w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/a><\/p>\n<p>This is the whole thing in action:<\/p>\n<div style=\"width: 510px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-13382-1\" width=\"510\" height=\"287\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/rud.is\/b\/wp-content\/uploads\/2022\/04\/ggpos.mp4?_=1\" \/><a href=\"https:\/\/rud.is\/b\/wp-content\/uploads\/2022\/04\/ggpos.mp4\">https:\/\/rud.is\/b\/wp-content\/uploads\/2022\/04\/ggpos.mp4<\/a><\/video><\/div>\n<p>One of the 2022 #30DayChartChallenge topics was &#8220;part-to-whole&#8221;, so I rejiggered my treemap entry into a very long plot that would make CVS cashiers feel quite inferior.<\/p>\n\n\t\t<style type=\"text\/css\">\n\t\t\t#gallery-1 {\n\t\t\t\tmargin: auto;\n\t\t\t}\n\t\t\t#gallery-1 .gallery-item {\n\t\t\t\tfloat: left;\n\t\t\t\tmargin-top: 10px;\n\t\t\t\ttext-align: center;\n\t\t\t\twidth: 50%;\n\t\t\t}\n\t\t\t#gallery-1 img {\n\t\t\t\tborder: 2px solid #cfcfcf;\n\t\t\t}\n\t\t\t#gallery-1 .gallery-caption {\n\t\t\t\tmargin-left: 0;\n\t\t\t}\n\t\t\t\/* see gallery_shortcode() in wp-includes\/media.php *\/\n\t\t<\/style>\n\t\t<div data-carousel-extra='{&quot;blog_id&quot;:1,&quot;permalink&quot;:&quot;https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/&quot;}' id='gallery-1' class='gallery galleryid-13382 gallery-columns-2 gallery-size-large'><dl class='gallery-item'>\n\t\t\t<dt class='gallery-icon portrait'>\n\t\t\t\t<a href='https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/fpr9rfaxwage6bn\/'><img loading=\"lazy\" decoding=\"async\" width=\"510\" height=\"680\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?fit=510%2C680&amp;ssl=1\" class=\"attachment-large size-large\" alt=\"\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=225%2C300&amp;ssl=1 225w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=530%2C707&amp;ssl=1 530w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=113%2C150&amp;ssl=1 113w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=768%2C1024&amp;ssl=1 768w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=1152%2C1536&amp;ssl=1 1152w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=1536%2C2048&amp;ssl=1 1536w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=500%2C667&amp;ssl=1 500w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=150%2C200&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=1200%2C1600&amp;ssl=1 1200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=400%2C533&amp;ssl=1 400w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=800%2C1067&amp;ssl=1 800w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=200%2C267&amp;ssl=1 200w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?resize=640%2C853&amp;ssl=1 640w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?w=1020&amp;ssl=1 1020w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" data-attachment-id=\"13386\" data-permalink=\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/fpr9rfaxwage6bn\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?fit=1920%2C2560&amp;ssl=1\" data-orig-size=\"1920,2560\" 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;,&quot;orientation&quot;:&quot;1&quot;}\" data-image-title=\"FPR9RFaXwAgE6bN\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?fit=225%2C300&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9RFaXwAgE6bN-scaled.jpeg?fit=510%2C680&amp;ssl=1\" \/><\/a>\n\t\t\t<\/dt><\/dl><dl class='gallery-item'>\n\t\t\t<dt class='gallery-icon portrait'>\n\t\t\t\t<a href='https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/fpr9spbxmag7dqo\/'><img loading=\"lazy\" decoding=\"async\" width=\"273\" height=\"1024\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?fit=273%2C1024&amp;ssl=1\" class=\"attachment-large size-large\" alt=\"\" srcset=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?w=683&amp;ssl=1 683w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=80%2C300&amp;ssl=1 80w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=273%2C1024&amp;ssl=1 273w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=40%2C150&amp;ssl=1 40w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=768%2C2881&amp;ssl=1 768w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=410%2C1536&amp;ssl=1 410w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=546%2C2048&amp;ssl=1 546w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=500%2C1875&amp;ssl=1 500w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=150%2C563&amp;ssl=1 150w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=400%2C1500&amp;ssl=1 400w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=800%2C3001&amp;ssl=1 800w, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?resize=200%2C750&amp;ssl=1 200w\" sizes=\"auto, (max-width: 273px) 100vw, 273px\" data-attachment-id=\"13385\" data-permalink=\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/fpr9spbxmag7dqo\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?fit=683%2C2560&amp;ssl=1\" data-orig-size=\"683,2560\" 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;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"FPR9SpBXMAg7Dqo\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?fit=80%2C300&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/FPR9SpBXMAg7Dqo-scaled.jpeg?fit=273%2C1024&amp;ssl=1\" \/><\/a>\n\t\t\t<\/dt><\/dl><br style=\"clear: both\" \/>\n\t\t<\/div>\n\n<p>You can find {escpos} over <a href=\"https:\/\/github.com\/hrbrmstr\/escpos\">on GitHub<\/a>.<\/p>\n<h3>FIN<\/h3>\n<p>One big caveat for this is that these printers have a tiny memory buffer, so very long, complex plots aren&#8217;t going to work out of the box. I had to break up my faceted heatmaps info individual ones and shunt them over one-by-one.<\/p>\n<p>I&#8217;ll be <strike>switching over the the new C library soon, and<\/strike> adding a small DSL to handle text formatting and printing from R (the device has 2 fonts and almost no styles). I&#8217;ve even threatened to make a ShinyPOS application, but we&#8217;ll see how the motivation for that goes.<\/p>\n<p>Kick the tyres and let me know if you end up using the package (+ share your creation to the ?).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>At the end of March, I caught a fleeting tweet that showcased an Epson thermal receipt printer generating a new &#8220;ticket&#8221; whenever a new GitHub issue was filed on a repository. @aschmelyun documents it well in this blog post. It&#8217;s a pretty cool hack, self-contained on a Pi Zero. Andrew&#8217;s project birthed an idea: could [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":13383,"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":[91],"tags":[],"class_list":["post-13382","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-r"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Turning {ggplot2} Into a PoS (Point-of-Sale) System - 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\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Turning {ggplot2} Into a PoS (Point-of-Sale) System - rud.is\" \/>\n<meta property=\"og:description\" content=\"At the end of March, I caught a fleeting tweet that showcased an Epson thermal receipt printer generating a new &#8220;ticket&#8221; whenever a new GitHub issue was filed on a repository. @aschmelyun documents it well in this blog post. It&#8217;s a pretty cool hack, self-contained on a Pi Zero. Andrew&#8217;s project birthed an idea: could [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2022-04-03T12:32:01+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-04-03T19:20:24+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"320\" \/>\n\t<meta property=\"og:image:height\" content=\"369\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/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=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"Turning {ggplot2} Into a PoS (Point-of-Sale) System\",\"datePublished\":\"2022-04-03T12:32:01+00:00\",\"dateModified\":\"2022-04-03T19:20:24+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/\"},\"wordCount\":726,\"commentCount\":5,\"publisher\":{\"@id\":\"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886\"},\"image\":{\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1\",\"articleSection\":[\"R\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/\",\"url\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/\",\"name\":\"Turning {ggplot2} Into a PoS (Point-of-Sale) System - rud.is\",\"isPartOf\":{\"@id\":\"https:\/\/rud.is\/b\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1\",\"datePublished\":\"2022-04-03T12:32:01+00:00\",\"dateModified\":\"2022-04-03T19:20:24+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#primaryimage\",\"url\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1\",\"width\":320,\"height\":369,\"caption\":\"ggplot receipt\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/rud.is\/b\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Turning {ggplot2} Into a PoS (Point-of-Sale) System\"}]},{\"@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":"Turning {ggplot2} Into a PoS (Point-of-Sale) System - 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\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/","og_locale":"en_US","og_type":"article","og_title":"Turning {ggplot2} Into a PoS (Point-of-Sale) System - rud.is","og_description":"At the end of March, I caught a fleeting tweet that showcased an Epson thermal receipt printer generating a new &#8220;ticket&#8221; whenever a new GitHub issue was filed on a repository. @aschmelyun documents it well in this blog post. It&#8217;s a pretty cool hack, self-contained on a Pi Zero. Andrew&#8217;s project birthed an idea: could [&hellip;]","og_url":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/","og_site_name":"rud.is","article_published_time":"2022-04-03T12:32:01+00:00","article_modified_time":"2022-04-03T19:20:24+00:00","og_image":[{"width":320,"height":369,"url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1","type":"image\/png"}],"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\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"Turning {ggplot2} Into a PoS (Point-of-Sale) System","datePublished":"2022-04-03T12:32:01+00:00","dateModified":"2022-04-03T19:20:24+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/"},"wordCount":726,"commentCount":5,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"image":{"@id":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1","articleSection":["R"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/","url":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/","name":"Turning {ggplot2} Into a PoS (Point-of-Sale) System - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#primaryimage"},"image":{"@id":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1","datePublished":"2022-04-03T12:32:01+00:00","dateModified":"2022-04-03T19:20:24+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#primaryimage","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1","width":320,"height":369,"caption":"ggplot receipt"},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2022\/04\/03\/turning-ggplot2-into-a-pos-point-of-sale-system\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"Turning {ggplot2} Into a PoS (Point-of-Sale) System"}]},{"@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":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2022\/04\/IMG_0217.png?fit=320%2C369&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p23idr-3tQ","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":4133,"url":"https:\/\/rud.is\/b\/2016\/03\/16\/supreme-annotations\/","url_meta":{"origin":13382,"position":0},"title":"Supreme Annotations","author":"hrbrmstr","date":"2016-03-16","format":false,"excerpt":"This is a follow up to a twitter-gist post & to the annotation party we're having this week I had not intended this to be \"Annotation Week\" but there was a large, positive response to my annotation \"hack\" post. This reaction surprised me, then someone pointed me to this link\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\/2016\/03\/supremes.png?fit=1200%2C987&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/03\/supremes.png?fit=1200%2C987&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/03\/supremes.png?fit=1200%2C987&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/03\/supremes.png?fit=1200%2C987&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/03\/supremes.png?fit=1200%2C987&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3665,"url":"https:\/\/rud.is\/b\/2015\/09\/08\/roll-your-own-stats-and-geoms-in-ggplot2-part-1-splines\/","url_meta":{"origin":13382,"position":1},"title":"Roll Your Own Stats and Geoms in ggplot2 (Part 1: Splines!)","author":"hrbrmstr","date":"2015-09-08","format":false,"excerpt":"A huge change is coming to ggplot2 and you can get a preview of it over at Hadley's github repo. I've been keenly interested in this as I will be fixing, finishing & porting coord_proj to it once it's done. Hadley & Winston have re-built ggplot2 with an entirely new\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":5050,"url":"https:\/\/rud.is\/b\/2017\/02\/15\/ggalt-0-4-0-now-on-cran\/","url_meta":{"origin":13382,"position":2},"title":"ggalt 0.4.0 now on CRAN","author":"hrbrmstr","date":"2017-02-15","format":false,"excerpt":"I'm uncontainably excited to report that the ggplot2 extension package ggalt is now on CRAN. The absolute best part of this package is the R community members who contributed suggestions and new geoms, stats, annotations and integration features. This release would not be possible without the PRs from: Ben Bolker\u2026","rel":"","context":"In &quot;ggplot&quot;","block_context":{"text":"ggplot","link":"https:\/\/rud.is\/b\/category\/ggplot\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/02\/RStudio-1.png?fit=1200%2C510&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/02\/RStudio-1.png?fit=1200%2C510&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/02\/RStudio-1.png?fit=1200%2C510&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/02\/RStudio-1.png?fit=1200%2C510&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/02\/RStudio-1.png?fit=1200%2C510&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":14001,"url":"https:\/\/rud.is\/b\/2023\/04\/29\/supreme-annotations-plot-redux-an-ojs-plot%e2%86%94ggplot2-rosetta-stone\/","url_meta":{"origin":13382,"position":3},"title":"Supreme Annotations Plot Redux &#038; An OJS Plot\u2194ggplot2 Rosetta Stone","author":"hrbrmstr","date":"2023-04-29","format":false,"excerpt":"Back in 2016, I did a post on {ggplot2} text annotations because it was a tad more challenging to do some of the things in that post back in the day. Since I've been moving back and forth between R and Observable (and JavaScript in general), I decided to recreate\u2026","rel":"","context":"In &quot;Observable&quot;","block_context":{"text":"Observable","link":"https:\/\/rud.is\/b\/category\/observable\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3929,"url":"https:\/\/rud.is\/b\/2016\/02\/11\/plot-the-new-svg-r-logo-with-ggplot2\/","url_meta":{"origin":13382,"position":4},"title":"Plot the new SVG R logo with ggplot2","author":"hrbrmstr","date":"2016-02-11","format":false,"excerpt":"High resolution and SVG versions of the new R logo are finally available. I converted the SVG to WKT (file here) which means we can use it like we would a shapefile in R. That includes plotting! Here's a short example of how to read that WKT and plot the\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\/2016\/02\/RStudio.png?fit=1198%2C942&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/02\/RStudio.png?fit=1198%2C942&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/02\/RStudio.png?fit=1198%2C942&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/02\/RStudio.png?fit=1198%2C942&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/02\/RStudio.png?fit=1198%2C942&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3832,"url":"https:\/\/rud.is\/b\/2015\/12\/28\/world-map-panel-plots-with-ggplot2-2-0-ggalt\/","url_meta":{"origin":13382,"position":5},"title":"World Map Panel Plots with ggplot2 2.0 &#038; ggalt","author":"hrbrmstr","date":"2015-12-28","format":false,"excerpt":"James Austin (@awhstin) made some #spiffy 4-panel maps with base R graphics but also posited he didn't use ggplot2 because: \u2026ggplot2 and maps currently do not support world maps at this point, which does not give us a great overall view. That is certainly a box I would not put\u2026","rel":"","context":"In &quot;cartography&quot;","block_context":{"text":"cartography","link":"https:\/\/rud.is\/b\/category\/cartography\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2015\/12\/facetmaps.png?fit=1154%2C722&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2015\/12\/facetmaps.png?fit=1154%2C722&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2015\/12\/facetmaps.png?fit=1154%2C722&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2015\/12\/facetmaps.png?fit=1154%2C722&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2015\/12\/facetmaps.png?fit=1154%2C722&ssl=1&resize=1050%2C600 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/13382","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=13382"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/13382\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media\/13383"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=13382"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=13382"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=13382"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}