

{"id":10991,"date":"2018-07-06T13:34:53","date_gmt":"2018-07-06T18:34:53","guid":{"rendered":"https:\/\/rud.is\/b\/?p=10991"},"modified":"2018-07-07T08:00:18","modified_gmt":"2018-07-07T13:00:18","slug":"visualizing-macos-app-usage","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/","title":{"rendered":"Visualizing macOS App Usage with a Little Help from osqueryr &#038; mactheknife"},"content":{"rendered":"<p>Both my <code>osqueryr<\/code> and <code>macthekinfe<\/code> packages have had a few updates and I wanted to put together a fun example (it being Friday, and all) for what you can do with them. All my packages are now on GitHub and GitLab and I&#8217;ll be maintaining them on both so I can accommodate the comfort-level of any and all contributors but will be prioritizing issues and PRs on GitLab ahead of any other platform. Having said that, I&#8217;ll mark non-CRAN packages with a <code># notcran<\/code> comment in the source views so you know you need to install it from wherever you like to grab sketch packages from.<\/p>\n<p>One table that <code>osquery<\/code> makes available under macOS is an inventory of all &#8220;apps&#8221; that macOS knows about. Previous posts have shown how to access these tables via the <code>dplyr<\/code> interface I built for <code>osquery<\/code>, but they involved multiple steps and as I started to use it more regularly (especially to explore the macOS 10.14 beta I&#8217;m running) I noticed that it could use some helper functions. One in particular &#8212; <code>osq_expose_tables()<\/code> &#8212; is pretty helpful in that it handles all the <code>dplyr<\/code> boilerplate code and makes table(s) available in the global environment by name. It takes a single table name or regular expression and then exposes all matching entities. While the function has a help page, it&#8217;s easier just to see it in action. Let&#8217;s expose the <code>apps<\/code> table:<\/p>\n<pre><code class=\"language-r\">library(osqueryr) # notcran\nlibrary(tidyverse)\n\nosq_expose_tables(\"apps\")\n\napps\n## # Source:   table<apps> [?? x 19]\n## # Database: OsqueryConnection\n##    applescript_enab\u2026 bundle_executable    bundle_identifier   bundle_name  bundle_package_\u2026\n##    <chr>             <chr>                <chr>               <chr>        <chr>           \n##  1 0                 1Password 6          com.agilebits.onep\u2026 1Password 6  APPL            \n##  2 0                 2BUA8C4S2C.com.agil\u2026 2BUA8C4S2C.com.agi\u2026 1Password m\u2026 APPL            \n##  3 1                 Adium                com.adiumX.adiumX   Adium        APPL            \n##  4 1                 Adobe Connect        com.adobe.adobecon\u2026 Adobe Conne\u2026 APPL            \n##  5 1                 Adobe Illustrator    com.adobe.illustra\u2026 Illustrator\u2026 APPL            \n##  6 \"\"                AIGPUSniffer         com.adobe.AIGPUSni\u2026 AIGPUSniffer APPL            \n##  7 \"\"                CEPHtmlEngine Helper com.adobe.cep.CEPH\u2026 CEPHtmlEngi\u2026 APPL            \n##  8 \"\"                CEPHtmlEngine        com.adobe.cep.CEPH\u2026 CEPHtmlEngi\u2026 APPL            \n##  9 \"\"                LogTransport2        com.adobe.headligh\u2026 LogTranspor\u2026 APPL            \n## 10 \"\"                droplet              \"\"                  Analyze Doc\u2026 APPL            \n## # ... with more rows, and 14 more variables: bundle_short_version <chr>,\n## #   bundle_version <chr>, category <chr>, compiler <chr>, copyright <chr>,\n## #   development_region <chr>, display_name <chr>, element <chr>, environment <chr>,\n## #   info_string <chr>, last_opened_time <chr>, minimum_system_version <chr>, name <chr>,\n## #   path <chr><\/code><\/pre>\n<p>There&#8217;s tons of info on all the apps macOS knows about, some of which are system services and &#8220;helper&#8221; apps (like Chrome&#8217;s auto-updater). One field &#8212; <code>last_opened_time<\/code> &#8212; caught my eye and I thought it would be handy to see which apps had little use (i.e. ones that haven&#8217;t been opened in a while) and which apps I might use more frequently (i.e. ones with more recent &#8220;open&#8221; times). That <code>last_open_time<\/code> is a fractional POSIX timestamp and, due to the way  <code>osquery<\/code> created the schemas, it&#8217;s in a character field. That&#8217;s easy enough to convert and then <code>arrange()<\/code> the whole list in descending order to let you see what you use most frequently.<\/p>\n<p>But, this is R and we can do better than a simple table or even a <code>DT::datatable()<\/code>.<\/p>\n<p>I recently added the ability to read macOS property lists (a.k.a. &#8220;plists&#8221;) to <code>mactheknife<\/code> by wrapping a Python module (<code>plistlib<\/code>). Since all (OK, &#8220;most&#8221;) macOS apps have an icon, I thought it would be fun to visualize the last opened frequency for each app using the app icons and <code>ggplot2<\/code>. Unfortunately, the ImageMagick (and, thus the <code>magick<\/code> package) cannot read macOS <code>icns<\/code> files, so you&#8217;ll need to do a <code>brew install libicns<\/code> before working with any of the remaining code since we&#8217;ll be relying on a command-line utility from that formula.<\/p>\n<p>Let&#8217;s get the frontmatter out of the way:<\/p>\n<pre><code class=\"language-r\">library(sys)\nlibrary(magick)\nlibrary(osqueryr) # notcran\nlibrary(mactheknife) #notcran\nlibrary(ggimage)\nlibrary(hrbrthemes)\nlibrary(ggbeeswarm)\nlibrary(tidyverse)\n\nosq_expose_tables(\"apps\")\n\n# macOS will use a generic app icon when none is present in an app bundle; this is the location and we'll\n# need to use it when our plist app spelunking comes up short\n\ndefault_app <- \"\/System\/Library\/CoreServices\/CoreTypes.bundle\/Contents\/Resources\/GenericApplicationIcon.icns\"\n<\/code><\/pre>\n<p>Next, we'll:<\/p>\n<ul>\n<li>collect the apps table locally<\/li>\n<li>filter out system-ish things (which we really don't care about for this post)<\/li>\n<li>convert the last used time to something useful (and reduce it to a day resolution)<\/li>\n<li>try to locate the property list for the app and read the path to the app icon file, substituting the generic one if not found (or other errors pop up):<\/li>\n<\/ul>\n<pre><code class=\"language-r\">select(apps, name, path, last_opened_time) %>%\n  collect() %>%\n  filter(!str_detect(path, \"(^\/System|usr|\/\/System|\/Library\/|Helper|\/Contents\/|\\\\.service$)\")) %>%\n  mutate(lop_day = as.Date(anytime::anytime(as.numeric(last_opened_time)))) %>%\n  mutate(icon = map_chr(path, ~{\n    p <- read_plist(file.path(.x, \"Contents\", \"Info.plist\"))\n    icns <- p$CFBundleIconFile[1]\n    if (is.null(icns)) return(default_app)\n    if (!str_detect(icns, \"\\\\.icns$\")) icns <- sprintf(\"%s.icns\", icns)\n    file.path(.x, \"Contents\", \"Resources\", icns)\n  })) -> apps_df\n\napps_df\n## # A tibble: 274 x 5\n##    last_opened_time name                       path                      lop_day    icon                       \n##    <chr>            <chr>                      <chr>                     <date>     <chr>                      \n##  1 1529958322.11297 1Password 6.app            \/Applications\/1Password \u2026 2018-06-25 \/Applications\/1Password 6.\u2026\n##  2 1523889402.80918 Adium.app                  \/Applications\/Adium.app   2018-04-16 \/Applications\/Adium.app\/Co\u2026\n##  3 1516307513.7606  Adobe Connect.app          \/Applications\/Adobe Conn\u2026 2018-01-18 \/Applications\/Adobe Connec\u2026\n##  4 1530044681.76677 Adobe Illustrator.app      \/Applications\/Adobe Illu\u2026 2018-06-26 \/Applications\/Adobe Illust\u2026\n##  5 -1.0             Analyze Documents.app      \/Applications\/Adobe Illu\u2026 1969-12-31 \/Applications\/Adobe Illust\u2026\n##  6 -1.0             Make Calendar.app          \/Applications\/Adobe Illu\u2026 1969-12-31 \/Applications\/Adobe Illust\u2026\n##  7 -1.0             Contact Sheets.app         \/Applications\/Adobe Illu\u2026 1969-12-31 \/Applications\/Adobe Illust\u2026\n##  8 -1.0             Export Flash Animation.app \/Applications\/Adobe Illu\u2026 1969-12-31 \/Applications\/Adobe Illust\u2026\n##  9 -1.0             Web Gallery.app            \/Applications\/Adobe Illu\u2026 1969-12-31 \/Applications\/Adobe Illust\u2026\n## 10 -1.0             Adobe InDesign CC 2018.app \/Applications\/Adobe InDe\u2026 1969-12-31 \/Applications\/Adobe InDesi\u2026\n## # ... with 264 more rows<\/code><\/pre>\n<p>Since I really didn't feel like creating a package wrapper for <code>libicns<\/code>, we're going to use the <code>sys<\/code> package to make system calls to convert the <code>icns<\/code> files to <code>png<\/code> files. We <em>really<\/em> don't want to do this repeatedly for the same files if we ever run this again, so we'll setup a cache directory to hold our converted <code>png<\/code>s.<\/p>\n<p>Apps can (and, usually do) have multiple icons with varying sizes and are not guaranteed to have every common size available. So, we'll have the <code>libicns<\/code> <code>icns2png<\/code> utility extract <em>all<\/em> the icons and use the highest resolution one, using <code>magick<\/code> to reduce it to a 32x32 png bitmap.<\/p>\n<pre><code class=\"language-r\"># setup the cache dir -- use whatever you want\ncache_dir <- path.expand(\"~\/.r-icns-cache\")\ndir.create(cache_dir)\n\n# create a unique name hash for more compact names\nmutate(apps_df, icns_png = map_chr(icon, ~{\n  hash <- digest::digest(.x, serialize=FALSE)\n  file.path(cache_dir, sprintf(\"%s.png\", hash))\n})) -> apps_df\n\n# find the icns2png program\nicns2png <- unname(Sys.which(\"icns2png\"))\n\n# go through each icon file \npb <- progress_estimated(length(apps_df$icns_png))\nwalk2(apps_df$icon, apps_df$icns_png, ~{\n\n  pb$tick()$print() # progress!\n\n  if (!file.exists(.y)) { # don't create it if it already exists\n\n    td <- tempdir()\n\n    # no icon file == use default one\n    if (!file.exists(.x)) .x <- default_app\n\n    # convert all of them to pngs\n    sys::exec_internal(\n      cmd = icns2png,\n      args = c(\"-x\", \"-o\", td, .x),\n      error = FALSE\n    ) -> res\n\n    rawToChar(res$stdout) %>% # go through icns2png output\n      str_split(\"\\n\") %>%\n      flatten_chr() %>%\n      keep(str_detect, \"  Saved\") %>% # find all the extracted icons\n      last() %>% # use the last one\n      str_replace(\".* to \/\", \"\/\") %>% # clean up the filename so we can read it in\n      str_replace(\"\\\\.$\", \"\") -> png\n\n    # read and convert\n    image_read(png) %>%\n      image_resize(geometry_area(32, 32)) %>%\n      image_write(.y)\n\n  }\n\n})<\/code><\/pre>\n<p>You can open up that cache directory with the macOS finder to find all the extracted\/converted <code>png<\/code>s.<\/p>\n<p><a href=\"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/screen-shot-2018-07-06-at-14-35-03\/\" rel=\"attachment wp-att-10998\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"10998\" data-permalink=\"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/screen-shot-2018-07-06-at-14-35-03\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/Screen-Shot-2018-07-06-at-14.35.03.png?fit=1586%2C1120&amp;ssl=1\" data-orig-size=\"1586,1120\" 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=\"Screen Shot 2018-07-06 at 14.35.03\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/Screen-Shot-2018-07-06-at-14.35.03.png?fit=510%2C360&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/Screen-Shot-2018-07-06-at-14.35.03.png?resize=510%2C360&#038;ssl=1\" alt=\"\" width=\"510\" height=\"360\" class=\"aligncenter size-full wp-image-10998\" \/><\/a><\/p>\n<p>Now, we're on the final leg of our app-use visualization journey.<\/p>\n<p>Some system\/utility apps have start-of-epoch dates due to the way the macOS installer tags them. We only want \"recent\" ones so I set an arbitrary cutoff date of the year 2000. Since many apps would have the same last opened date, I wanted to get a spread out layout \"for free\". One way to do that is to use <code>ggbeeswarm::position_beswarm()<\/code>:<\/p>\n<pre><code class=\"language-r\">filter(apps_df, lop_day > as.Date(\"2000-01-01\")) %>%\n  ggplot() +\n  geom_image(\n    aes(x=\"\", lop_day, image = icns_png), size = 0.033,\n    position = position_quasirandom(width = 0.5)\n  ) +\n  geom_text(\n    data = data_frame(\n      x = c(0.6, 0.6),\n      y = as.Date(c(\"2018-05-01\", \"2017-09-15\")),\n      label = c(\"More recently used \u2191\", \"Not used in a while \u2193\")\n    ), \n    aes(x, y, label=label), family = font_an, size = 5 , hjust = 0,\n    color = \"lightslategray\"\n  ) +\n  labs(x = NULL, y = \"Last Opened Time\") +\n  labs(\n    x = NULL, y = NULL,\n    title = \"macOS 'Last Used' App History\"\n  ) +\n  theme_ipsum_rc(grid=\"Y\") +\n  theme(axis.text.x = element_blank())<\/code><\/pre>\n<p><a href=\"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/app-lod-tree-1\/\" rel=\"attachment wp-att-10995\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"10995\" data-permalink=\"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/app-lod-tree-1\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1818%2C1814&amp;ssl=1\" data-orig-size=\"1818,1814\" 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=\"app-lod-tree-1\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=510%2C509&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?resize=510%2C509&#038;ssl=1\" alt=\"\" width=\"510\" height=\"509\" class=\"aligncenter size-full wp-image-10995\" \/><\/a><\/p>\n<p>There are tons of other ways to look at this data and you can use the <code>osquery<\/code> daemon to log this data regularly so you can get an extra level of detail. An interesting offshot project would be to grab the latest RStudio dailies and see if you can wrangle a sweet D3 visualization from the app data we collected. Make sure to drop a comment with your creations in the comments. You can find the full code <a href=\"https:\/\/gitlab.com\/snippets\/1730983\">in this snippet<\/a>.<\/p>\n<h3>UPDATE (2018-07-07)<\/h3>\n<p>A commenter <em>really<\/em> wanted tooltips with app names. So did I, but neither <code>plotly<\/code> nor <code>ggiraph<\/code> support <code>ggimage<\/code> so we can't get tooltips for free.<\/p>\n<p>However, if you're willing to use the latest RStudio Preview or Daily editions, then we can \"easily\" use the new built-in D3 support to get some sketch tooltips.<\/p>\n<p>First, we need to change up the plotting code a bit so we can get some base data to feed to D3:<\/p>\n<pre><code class=\"language-r\">filter(apps_df, lop_day > as.Date(\"2000-01-01\")) %>%\n  mutate(name = sub(\"\\\\.app\", \"\", name)) %>% \n  ggplot() +\n  geom_image(\n    aes(x=\"\", lop_day, image = icns_png, name=name), size = 0.033,\n    position = position_quasirandom(width = 0.5)\n  ) +\n  geom_text(\n    data = data_frame(\n      x = c(0.6, 0.6),\n      y = as.Date(c(\"2018-05-01\", \"2017-09-15\")),\n      label = c(\"More recently used \u2191\", \"Not used in a while \u2193\")\n    ), \n    aes(x, y, label=label), family = font_an, size = 5 , hjust = 0,\n    color = \"lightslategray\"\n  ) +\n  labs(x = NULL, y = \"Last Opened Time\") +\n  labs(\n    x = NULL, y = NULL,\n    title = \"macOS 'Last Used' App History\"\n  ) +\n  theme_ipsum_rc(grid=\"Y\") +\n  theme(axis.text.x = element_blank()) -> gg\n\ngb <- ggplot_build(gg) # compute the layout\n\nidf <- tbl_df(gb$data[[1]]) # extract the data\nidf <- mutate(idf, image = sprintf(\"lib\/imgs-1.0.0\/%s\", basename(image))) # munge the png paths so D3 can find them\n\nwrite_rds(idf, \"~\/Data\/apps.rds\") # save off the data<\/code><\/pre>\n<p>Now, we just need some D3 javascript glue:<\/p>\n<pre><code class=\"language-js\">\/\/ !preview r2d3 data=data.frame(readRDS(\"~\/Data\/apps.rds\")), d3_version = 4, dependencies = htmltools::htmlDependency(name = \"imgs\", version = \"1.0.0\", src = \"~\/.r-icns-cache\", all_files = TRUE)\n\nvar margin = {top: 16, right: 32, bottom: 16, left: 32},\n    width = width - margin.left - margin.right,\n    height = height - margin.top - margin.bottom;\n\nvar x = d3.scaleLinear().range([0, width]);\nvar y = d3.scaleLinear().range([height, 0]);\n\nx.domain([\n  d3.min(data, function(d) { return d.x; }) - 0.05,\n  d3.max(data, function(d) { return d.x; }) + 0.05\n]);\n\ny.domain([\n  d3.min(data, function(d) { return d.y; }) - 16,\n  d3.max(data, function(d) { return d.y; }) + 16\n]);\n\nvar tooltip = d3.select(\"body\")\n    .append(\"div\")\n    .style(\"position\", \"absolute\")\n    .style(\"z-index\", \"10\")\n    .style(\"visibility\", \"hidden\")\n    .style(\"color\", \"blue\")\n    .style(\"background\", \"white\")\n    .style(\"padding\", \"5px\")\n    .style(\"font-family\", \"sans-serif\")\n    .text(\"\");\n\nsvg.attr(\"width\", width + margin.left + margin.right)\n    .attr(\"height\", height + margin.top + margin.bottom)\n  .append(\"g\")\n    .attr(\"transform\",\n          \"translate(\" + margin.left + \",\" + margin.top + \")\");\n\nvar images = svg.selectAll(\"appimg\")\n      .data(data)\n    .enter().append(\"svg:image\")\n      .attr(\"xlink:href\",  function(d) { return d.image;})\n      .attr(\"x\", function(d) { return x(d.x);})\n      .attr(\"y\", function(d) { return y(d.y);})\n      .attr(\"height\", 32)\n      .attr(\"width\", 32)\n      .on(\"mouseover\", function(d) { return tooltip.style(\"visibility\", \"visible\").text(d.name); })\n  .on(\"mousemove\", function(){ return tooltip.style(\"top\", (event.pageY-10)+\"px\").style(\"left\",(event.pageX+10)+\"px\"); })\n  .on(\"mouseout\", function(){ return tooltip.style(\"visibility\", \"hidden\"); });<\/code><\/pre>\n<p>If you don't want to live dangerously, you can also save that script off and just use <code>r2d3<\/code> directly:<\/p>\n<pre><code class=\"language-js\">r2d3::r2d3(\n  data = data.frame(readRDS(\"~\/Data\/apps.rds\")), \n  script = \"~\/Desktop\/app-d3.js\",\n  d3_version = 4, \n  dependencies = htmltools::htmlDependency(\n    name = \"imgs\", \n    version = \"1.0.0\", \n    src = \"~\/.r-icns-cache\", \n    all_files = TRUE\n  )\n)<\/code><\/pre>\n<p>Either way gives us interactive tooltips:<\/p>\n<p><img decoding=\"async\" src=\"\/dl\/r2d3-001.gif\"\/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Both my osqueryr and macthekinfe packages have had a few updates and I wanted to put together a fun example (it being Friday, and all) for what you can do with them. All my packages are now on GitHub and GitLab and I&#8217;ll be maintaining them on both so I can accommodate the comfort-level of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":10995,"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-10991","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.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Visualizing macOS App Usage with a Little Help from osqueryr &amp; mactheknife - 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\/2018\/07\/06\/visualizing-macos-app-usage\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Visualizing macOS App Usage with a Little Help from osqueryr &amp; mactheknife - rud.is\" \/>\n<meta property=\"og:description\" content=\"Both my osqueryr and macthekinfe packages have had a few updates and I wanted to put together a fun example (it being Friday, and all) for what you can do with them. All my packages are now on GitHub and GitLab and I&#8217;ll be maintaining them on both so I can accommodate the comfort-level of [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2018-07-06T18:34:53+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-07-07T13:00:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1818\" \/>\n\t<meta property=\"og:image:height\" content=\"1814\" \/>\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=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"Visualizing macOS App Usage with a Little Help from osqueryr &#038; mactheknife\",\"datePublished\":\"2018-07-06T18:34:53+00:00\",\"dateModified\":\"2018-07-07T13:00:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/\"},\"wordCount\":922,\"commentCount\":7,\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2018\\\/07\\\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1\",\"articleSection\":[\"R\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/\",\"name\":\"Visualizing macOS App Usage with a Little Help from osqueryr & mactheknife - rud.is\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2018\\\/07\\\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1\",\"datePublished\":\"2018-07-06T18:34:53+00:00\",\"dateModified\":\"2018-07-07T13:00:18+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2018\\\/07\\\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2018\\\/07\\\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1\",\"width\":\"1818\",\"height\":\"1814\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/07\\\/06\\\/visualizing-macos-app-usage\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/rud.is\\\/b\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Visualizing macOS App Usage with a Little Help from osqueryr &#038; mactheknife\"}]},{\"@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":"Visualizing macOS App Usage with a Little Help from osqueryr & mactheknife - 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\/2018\/07\/06\/visualizing-macos-app-usage\/","og_locale":"en_US","og_type":"article","og_title":"Visualizing macOS App Usage with a Little Help from osqueryr & mactheknife - rud.is","og_description":"Both my osqueryr and macthekinfe packages have had a few updates and I wanted to put together a fun example (it being Friday, and all) for what you can do with them. All my packages are now on GitHub and GitLab and I&#8217;ll be maintaining them on both so I can accommodate the comfort-level of [&hellip;]","og_url":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/","og_site_name":"rud.is","article_published_time":"2018-07-06T18:34:53+00:00","article_modified_time":"2018-07-07T13:00:18+00:00","og_image":[{"width":1818,"height":1814,"url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1","type":"image\/png"}],"author":"hrbrmstr","twitter_card":"summary_large_image","twitter_misc":{"Written by":"hrbrmstr","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"Visualizing macOS App Usage with a Little Help from osqueryr &#038; mactheknife","datePublished":"2018-07-06T18:34:53+00:00","dateModified":"2018-07-07T13:00:18+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/"},"wordCount":922,"commentCount":7,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"image":{"@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1","articleSection":["R"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/","url":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/","name":"Visualizing macOS App Usage with a Little Help from osqueryr & mactheknife - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/#primaryimage"},"image":{"@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1","datePublished":"2018-07-06T18:34:53+00:00","dateModified":"2018-07-07T13:00:18+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/#primaryimage","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/07\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1","width":"1818","height":"1814"},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2018\/07\/06\/visualizing-macos-app-usage\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"Visualizing macOS App Usage with a Little Help from osqueryr &#038; mactheknife"}]},{"@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\/2018\/07\/app-lod-tree-1.png?fit=1818%2C1814&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p23idr-2Rh","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":12185,"url":"https:\/\/rud.is\/b\/2019\/05\/12\/quick-hit-updates-to-quicklookr-and-rdatainfo\/","url_meta":{"origin":10991,"position":0},"title":"Quick Hit: Updates to QuickLookR and {rdatainfo}","author":"hrbrmstr","date":"2019-05-12","format":false,"excerpt":"I'm using GitUgh links here b\/c the issue was submitted there. Those not wishing to be surveilled by Microsoft can find the macOS QuickLook plugin project and {rdatainfo} project in SourceHut and GitLab (~hrbrmstr and hrbrmstr accounts respectively). I hadn't touched QuickLookR? or {rdatainfo}? at all since 2016 since it\u2026","rel":"","context":"In &quot;macOS&quot;","block_context":{"text":"macOS","link":"https:\/\/rud.is\/b\/category\/macos\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":14475,"url":"https:\/\/rud.is\/b\/2023\/09\/30\/avoid-libwebp-electron-woes-on-macos-with-positron\/","url_meta":{"origin":10991,"position":1},"title":"Avoid libwebp Electron Woes On macOS With positron","author":"hrbrmstr","date":"2023-09-30","format":false,"excerpt":"If you've got ? on this blog (directly, or via syndication) you'd have to have been living under a rock to not know about the libwebp supply chain disaster. An unfortunate casualty of inept programming just happened to be any app in the Electron ecosystem that doesn't undergo bleeding-edge updates.\u2026","rel":"","context":"In &quot;Cybersecurity&quot;","block_context":{"text":"Cybersecurity","link":"https:\/\/rud.is\/b\/category\/cybersecurity\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/09\/resource-database-Ix86EQm6HDQ-unsplash.jpg?fit=960%2C1200&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/09\/resource-database-Ix86EQm6HDQ-unsplash.jpg?fit=960%2C1200&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/09\/resource-database-Ix86EQm6HDQ-unsplash.jpg?fit=960%2C1200&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/09\/resource-database-Ix86EQm6HDQ-unsplash.jpg?fit=960%2C1200&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":6071,"url":"https:\/\/rud.is\/b\/2017\/06\/10\/engaging-the-tidyverse-clean-slate-protocol\/","url_meta":{"origin":10991,"position":2},"title":"Engaging the tidyverse Clean Slate Protocol","author":"hrbrmstr","date":"2017-06-10","format":false,"excerpt":"I caught the 0.7.0 release of dplyr on my home CRAN server early Friday morning and immediately set out to install it since I'm eager to finish up my sergeant package and get it on CRAN. \"Tidyverse\" upgrades aren't trivial for me as I tinker quite a bit with the\u2026","rel":"","context":"In &quot;dplyr&quot;","block_context":{"text":"dplyr","link":"https:\/\/rud.is\/b\/category\/dplyr\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/06\/CSP.png?fit=1000%2C416&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/06\/CSP.png?fit=1000%2C416&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/06\/CSP.png?fit=1000%2C416&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2017\/06\/CSP.png?fit=1000%2C416&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":12438,"url":"https:\/\/rud.is\/b\/2019\/08\/22\/quick-hit-a-new-64-bit-swift-5-rswitch-app\/","url_meta":{"origin":10991,"position":3},"title":"Quick Hit: A new 64-bit Swift 5 RSwitch App","author":"hrbrmstr","date":"2019-08-22","format":false,"excerpt":"At the bottom of the R for macOS Developer's Page there's mention of an \"other binary\" called \"RSwitch\" that is \"a small GUI that allows you to switch between R versions quickly (if you have multiple versions of R framework installed).\" Said switching requires you to use the \"tar.gz\" versions\u2026","rel":"","context":"In &quot;Apple&quot;","block_context":{"text":"Apple","link":"https:\/\/rud.is\/b\/category\/apple\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":11427,"url":"https:\/\/rud.is\/b\/2018\/08\/24\/friday-rstats-twofer-finding-macos-32-bit-apps-processing-data-from-system-commands\/","url_meta":{"origin":10991,"position":4},"title":"Friday #rstats twofer: Finding macOS 32-bit apps &#038; Processing Data from System Commands","author":"hrbrmstr","date":"2018-08-24","format":false,"excerpt":"Apple has run the death bell on 32-bit macOS apps and, if you're running a recent macOS version on your Mac (which you should so you can get security updates) you likely see this alert from time-to-time: If you're like me, you click through that and keep working but later\u2026","rel":"","context":"In &quot;Apple&quot;","block_context":{"text":"Apple","link":"https:\/\/rud.is\/b\/category\/apple\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/Screen-Shot-2018-08-24-at-4.58.41-AM.png?fit=1200%2C612&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":4611,"url":"https:\/\/rud.is\/b\/2016\/08\/06\/quicklookr-a-macos-quicklook-plugin-for-r-data-files\/","url_meta":{"origin":10991,"position":5},"title":"QuickLookR &#8211; A macOS QuickLook plugin for R Data files","author":"hrbrmstr","date":"2016-08-06","format":false,"excerpt":"I had tried to convert my data-saving workflows to [`feather`](https:\/\/github.com\/wesm\/feather\/tree\/master\/R) but there have been [issues](https:\/\/github.com\/wesm\/feather\/issues\/155) with it supporting large files (that seem to be near resolution), so I've been continuing to use R Data files for local saving of processed\/cleaned data. I make _many_ of these files and sometimes I\u2026","rel":"","context":"In &quot;Objective-C&quot;","block_context":{"text":"Objective-C","link":"https:\/\/rud.is\/b\/category\/objective-c\/"},"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\/10991","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=10991"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/10991\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media\/10995"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=10991"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=10991"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=10991"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}