<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Pete Jones</title>
    <subtitle>Social scientist sometimes studying fictional characters and sometimes studying real people.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://petejon.es/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://petejon.es"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-09-18T00:00:00+00:00</updated>
    <id>https://petejon.es/atom.xml</id>
    <entry xml:lang="en">
        <title>You don&#x27;t need CI to deploy a static website</title>
        <published>2026-09-18T00:00:00+00:00</published>
        <updated>2026-09-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Pete Jones
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://petejon.es/posts/2026-09-18-deploying-static-sites/"/>
        <id>https://petejon.es/posts/2026-09-18-deploying-static-sites/</id>
        
        <content type="html" xml:base="https://petejon.es/posts/2026-09-18-deploying-static-sites/">&lt;p&gt;I had a rare surplus of energy this past week and I decided to divert it towards seeing if there was any maintenance that needed to be done on my public projects.
This ended up with me blowing the cobwebs off &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;catchup&quot;&gt;{catchup}&lt;&#x2F;a&gt;, an R package I use all the time in my personal workflow but rarely hack on.
I realised that the package might have a bit more appeal to somebody other than me if it had a nice-to-look-at documentation website rather than just the README of a rarely updated source repo.&lt;&#x2F;p&gt;
&lt;p&gt;A day or two later, after a bit of reading and some trial and error, I had managed to deploy the site at my own domain.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2026-09-18-deploying-static-sites&#x2F;img&#x2F;catchup_screenshot.png&quot; alt=&quot;screenshot of the top of the catchup documentation website, containing a navbar, package title, logo, badges, description and a sidebar with links&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And the best part is that it used no GitHub and no CI.&lt;&#x2F;p&gt;
&lt;p&gt;I was so won over by how much better the setup was than the one I had been using for my main website (i.e. this one) for years, that I swiftly switched it over to the same deployment system.&lt;&#x2F;p&gt;
&lt;p&gt;This post might be a bit of a departure from what I usually write about because it&#x27;s not as focused on data and research.
But I think there are a lot of people like me with no software development background, who have ended up in the world of programming and version control and code hosting repositories mostly to support their research activities.
Maybe this post will be helpful in providing an example of a pretty easy alternative to the vast amount of material assuming you&#x27;re happy to adopt a setup based on GitHub and&#x2F;or CI.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-drop-ci&quot;&gt;Why drop CI?&lt;&#x2F;h2&gt;
&lt;p&gt;I don&#x27;t think I need to rehearse the reasons why you would want to avoid GitHub at this point - you either get it or you don&#x27;t.
But it might be less obvious why I&#x27;m apparently lumping CI into the same category, so I guess I should expand on that.&lt;&#x2F;p&gt;
&lt;p&gt;The main issue with CI is that it&#x27;s resource-intensive.
That&#x27;s not as much of a problem for big software projects, where the cost is worth it to ensure that the test suite or the build pipeline is being run at certain points in the development process.
But tools like GitHub Actions have abstracted away the costs and realities of CI to the extent that it is overused on even tiny projects, a practice which has been super normalised in the data science world.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not that CI is inherently bad, it&#x27;s just not always the approriate tool for the job in my opinion, regardless of how frictionless it is.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ci-and-static-site-generators&quot;&gt;CI and static site generators&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s use static site generators (SSGs) as our example.
Typically, for a website built with an SSG, you have a source directory that follows a set structure, containing the theme, templates, configuration files and content for the website.
It might look something like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;content&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;static&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;templates&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;theme&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;config.toml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then you run the SSG program&#x27;s build command from the root of that directory to generate a new directory containing the static website files, which is what will actually be served:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;build&#x2F; (&amp;lt;- new, contains the static site)
&lt;&#x2F;span&gt;&lt;span&gt;content&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;static&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;templates&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;theme&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;config.toml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are a few different options for how you could deploy the site.
The simplest version doesn&#x27;t involve any version control at all - you can just take that the contents of that &lt;code&gt;build&#x2F;&lt;&#x2F;code&gt; directory and drop them anywhere that offers web hosting.&lt;&#x2F;p&gt;
&lt;p&gt;But the two main options I want to consider are the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Option 1&lt;&#x2F;strong&gt;: Put the source files in version control, and build the site via CI. (Generally, this will then integrate with something like Netlify or GitHub Pages to serve the built site.)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Option 2&lt;&#x2F;strong&gt;: Put both the source files and the locally built site in version control. You can use webhooks to serve the built site, updating on each push event.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In the first option, you don&#x27;t build the site locally, you set up a CI workflow that builds the site whenever you push the source.
So, every time you make a public-facing change to the website, you spin up a virtual machine just to run a simple build command that would take about a second to run on your laptop (where you&#x27;re already working on the source files), and then throw that machine away.
Is this necessary?
This seems like using a chainsaw to open a can of beans to me.&lt;&#x2F;p&gt;
&lt;p&gt;Option 2 gets to exactly the same end state, without any of the pointless waste.
It&#x27;s also more portable and less tied to specific platforms and services.
I think it makes way more sense, but it&#x27;s much less well documented.&lt;&#x2F;p&gt;
&lt;p&gt;For example, I built the {catchup} website with &lt;a href=&quot;https:&#x2F;&#x2F;pkgdown.r-lib.org&#x2F;&quot;&gt;{pkgdown}&lt;&#x2F;a&gt;, which is a really fantastic package.
However, {pkgdown} only really targets a GitHub Actions-based workflow for deployment of the websites it produces, and it makes very little effort to explain other strategies for getting your website online.&lt;&#x2F;p&gt;
&lt;p&gt;I guess that&#x27;s part of the gap that I&#x27;m trying to close here by writing up what I did and why I find it so much more sensible.
To explain that, there&#x27;s two parts to the setup that need to be outlined: git-pages, and git worktrees.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deploying-via-git-pages-with-codeberg&quot;&gt;Deploying via git-pages with Codeberg&lt;&#x2F;h2&gt;
&lt;p&gt;The first tool that really helps make this easy is &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;git-pages&#x2F;git-pages&quot;&gt;git-pages&lt;&#x2F;a&gt;, a relatively new tool that has been developed to underpin Codeberg&#x27;s Pages functionality.
It&#x27;s a git-based static site server - it takes a repo and serves a website from it.
It provides the basis for forges like Codeberg to offer something like what GitHub Pages can offer - a way of saying &quot;if you have your static site files in a repo hosted here, we have a way of serving the site over the web&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t go too much into the details of how to set up a repo to take advantage of it because honestly I just followed the &lt;a href=&quot;https:&#x2F;&#x2F;docs.codeberg.org&#x2F;codeberg-pages&#x2F;&quot;&gt;excellent documentation&lt;&#x2F;a&gt;.
The important point to note here is that Codeberg&#x27;s implementation expects that, for a repository-based website, your site files live in the root of a branch called &lt;code&gt;pages&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So, if you recall the example directory strucure from earlier, that would mean taking everything inside &lt;code&gt;build&#x2F;&lt;&#x2F;code&gt;, &lt;code&gt;.gitignore&lt;&#x2F;code&gt;-ing it, and checking it out at a separate branch &lt;code&gt;pages&lt;&#x2F;code&gt;, while the source continues to be in a separate branch (e.g. &lt;code&gt;main&lt;&#x2F;code&gt;).
There are various ways to arrive at this situation, but the one that makes this whole process a breeze is git worktrees, which I&#x27;ll get to in a second.&lt;&#x2F;p&gt;
&lt;p&gt;Once you have the site files in your public &lt;code&gt;pages&lt;&#x2F;code&gt; branch, you can set up a Forgejo webhook following the instructions in the Codeberg docs that will re-serve your site every time there is a new push event to the branch.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-git-worktrees-help&quot;&gt;How git worktrees help&lt;&#x2F;h2&gt;
&lt;p&gt;Perhaps you&#x27;re already using &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-worktree&quot;&gt;git worktrees&lt;&#x2F;a&gt;, but I&#x27;ll admit that I hadn&#x27;t yet found a use for them until discovering how perfectly they suit this branch-based deployment setup.&lt;&#x2F;p&gt;
&lt;p&gt;Git worktrees allow you to have a subdirectory within a repository act like a checked out branch of the repository, so that when you navigate to the subdirectory you checkout that branch.&lt;&#x2F;p&gt;
&lt;p&gt;This is the perfect mechanism for declaring that the &lt;code&gt;build&#x2F;&lt;&#x2F;code&gt; subdirectory of the repo should map to the &lt;code&gt;pages&lt;&#x2F;code&gt; branch, as &lt;a href=&quot;https:&#x2F;&#x2F;scy.name&#x2F;blog&#x2F;2025&#x2F;11&#x2F;git-worktree.html&quot;&gt;this post&lt;&#x2F;a&gt; points out.
When the SSG builds the static site directory, it puts the files where they need to be - in the root of the &lt;code&gt;pages&lt;&#x2F;code&gt; branch.&lt;&#x2F;p&gt;
&lt;p&gt;One thing to be careful of: the way that git keeps track of the worktree is via a .git file in the subdirectory, and some static site generators completely delete and rebuild the subdirectory each time they call their build command.
In that case, you need to temporarily move the .git file somewhere safe and put it back in place after and everything will work fine.
Thankfully, my SSG of choice, &lt;a href=&quot;https:&#x2F;&#x2F;getzola.org&quot;&gt;Zola&lt;&#x2F;a&gt; has a configuration option to preserve dotfiles in the build directory precisely for this use case.&lt;&#x2F;p&gt;
&lt;p&gt;So, if your webhook and your worktree are set up correctly, after updating your website&#x27;s source, you can deploy your website changes just by doing something like the following:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;myfavssg build
&lt;&#x2F;span&gt;&lt;span&gt;cd build
&lt;&#x2F;span&gt;&lt;span&gt;git add -A
&lt;&#x2F;span&gt;&lt;span&gt;git commit -m &amp;quot;fix typos in latest post&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;git push -u origin pages
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the site will be updated.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;to-sum-up&quot;&gt;To sum up&lt;&#x2F;h2&gt;
&lt;p&gt;Whether it&#x27;s a {pkgdown} site, or a site built by something like Zola or Hugo - if it generates a subdirectory with static site files, you can set it up as a worktree and point it to a &lt;code&gt;pages&lt;&#x2F;code&gt; branch that gets served via a webhook with Codeberg Pages.&lt;&#x2F;p&gt;
&lt;p&gt;Switching this site to use that deployment system meant I no longer had any ties to Netlify, and I could take back my DNS management from them for my domain, which is a bonus.
It also enabled me to reach &lt;em&gt;repository zero&lt;&#x2F;em&gt; on GitHub.&lt;&#x2F;p&gt;
&lt;p&gt;Let me know if there&#x27;s anything I&#x27;ve not been clear on here, or if you have any other tips on how to make this kind of thing work smoothly that I might have missed.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Using toolbox containers as a persistent, stable and easy-to-deploy development environment for data analysis work</title>
        <published>2026-07-27T00:00:00+00:00</published>
        <updated>2026-07-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Pete Jones
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://petejon.es/posts/2026-07-27-toolbox-workflow/"/>
        <id>https://petejon.es/posts/2026-07-27-toolbox-workflow/</id>
        
        <content type="html" xml:base="https://petejon.es/posts/2026-07-27-toolbox-workflow/">&lt;h2 id=&quot;a-bit-of-preamble&quot;&gt;A bit of preamble&lt;&#x2F;h2&gt;
&lt;p&gt;A while ago, I asked for some advice on the Fediverse about using containers for your development environment when doing interactive R&#x2F;Quarto data analysis work.
What triggered the question was a bit of frustration that &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;r-lib&#x2F;rig&quot;&gt;rig&lt;&#x2F;a&gt;, the software I prefer to use for managing my R installations on my machine, wasn&#x27;t keeping pace super well with Fedora&#x27;s releases.
This was sufficiently inconvenient that it forced me to deal with the fact that I shouldn&#x27;t really be relying on my standard day-to-day OS for my critical work tools.
They should be kept isolated in a stable environment so that I can manage or change my OS without worrying about breaking my projects or workflow.
Basically, I probably needed to learn more about containerised workflows.&lt;&#x2F;p&gt;
&lt;p&gt;As part of my Fediverse call for help, Jim Gardner took an interest in my use case and &lt;a href=&quot;https:&#x2F;&#x2F;jimgar.github.io&#x2F;posts&#x2F;interactive-neovim-development-container-r-quarto&#x2F;post.html&quot;&gt;wrote up a generous piece&lt;&#x2F;a&gt; demonstrating what building a working container for my particular workflow might look like.
This post is, in a sense, a very late follow up to his post.&lt;&#x2F;p&gt;
&lt;p&gt;In order to contextualise why it&#x27;s taken me so long to write up a response, I need to explain that by the time I had worked through Jim&#x27;s example and considered whether something like that might be just what I was looking for, I had already stumbled into a temporary, hacky solution to my Fedora-rig problems that enabled me to keep working with minimal disruption.
As it happens, that hacky solution has worked so incredibly well for the last year or so that I became convinced that it, in fact, was the solution I was looking for all along.&lt;&#x2F;p&gt;
&lt;p&gt;The solution I found which ended up being the answer to my problems?
Toolbox containers.&lt;&#x2F;p&gt;
&lt;p&gt;In this post, I&#x27;ll talk about what the toolbox approach to containerisation is and what my setup looks like.
I&#x27;ll talk about why I think this approach can be such a perfect fit if your circumstances and needs look like mine - and I&#x27;ll talk about why it&#x27;s probably not the right tool if they don&#x27;t.
I&#x27;ll also, finally, return to the point of Jim Gardner&#x27;s post as I talk about my attempt to build an image that serves as a &quot;batteries included&quot; command line environment for my development needs - Neovim, Quarto, R and more, all available out of the box.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2026-07-27-toolbox-workflow&#x2F;figs&#x2F;workbox_demo.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-toolbox-containers&quot;&gt;What are toolbox containers?&lt;&#x2F;h2&gt;
&lt;p&gt;The primary use case for toolbox containers is providing a standard modifiable command line environment on atomic or &quot;immutable&quot; operating systems.
In such OSes, only the user&#x27;s home directory is writable, and the system directories are administered as part of an overall system image which cannot be modified.
Basically, your home directory is yours to do what you want with, but the system only changes by swapping the image for an updated image.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s several advantages and drawbacks to the atomic OS paradigm, but a consequence is that traditional distro package management doesn&#x27;t work, because that approach usually writes packages and configuration files into system directories.
Toolboxes get around this problem by allowing users to create persistent containerised environments on their system that are &quot;mutable&quot;, allowing you to install packages the traditional way - they just live in the system of the container rather than the host.
To reduce friction, toolbox containers have some key properties: the user is carried through from the host system and has sudo access inside the container, and the user&#x27;s home directory is mounted inside the container.
Together, these features mean that being inside a toolbox environment on an atomic OS is largely indistinguishable from being at a command prompt in a traditional package-based OS.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;toolbox-vs-toolbx-vs-distrobox-a-note-on-tools-and-terms&quot;&gt;Toolbox vs Toolbx vs Distrobox: a note on tools and terms&lt;&#x2F;h3&gt;
&lt;p&gt;Now&#x27;s a good time to state that the term I&#x27;m using here - &quot;toolbox containers&quot; - isn&#x27;t ideal.
That&#x27;s because one of the major pieces of software implementing the idea is called &lt;a href=&quot;https:&#x2F;&#x2F;containertoolbx.org&#x2F;&quot;&gt;Toolbx&lt;&#x2F;a&gt; (I don&#x27;t know why they dropped the third &quot;o&quot;; the shell command is spelled &quot;toolbox&quot;.)
This overlap could get confusing, but unless I spell it without that third &quot;o&quot;, I&#x27;m talking about the general concept, regardless of implementation.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m sticking to the more general term because, while Toolbx is a great piece of software, it isn&#x27;t the only tool in this space.
In fact, if you&#x27;re not a Fedora user, you&#x27;re probably more likely to have encountered &lt;a href=&quot;https:&#x2F;&#x2F;distrobox.it&quot;&gt;Distrobox&lt;&#x2F;a&gt;, which implements and expands on Toolbx&#x27;s core ideas in a more general framework (and does it all using shell scripts!).
Unlike Toolbx, Distrobox doesn&#x27;t have a hard dependency on &lt;code&gt;systemd&lt;&#x2F;code&gt;, making it more broadly compatible as well.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s also a new tool that I&#x27;m keeping an eye on called &lt;a href=&quot;https:&#x2F;&#x2F;blog.lasath.org&#x2F;2026&#x2F;02&#x2F;kapsule-completing-kde-linux.html&quot;&gt;Kapsule&lt;&#x2F;a&gt;, which is a KDE project that is being developed primarily to enrich the new immutable &lt;a href=&quot;https:&#x2F;&#x2F;kde.org&#x2F;linux&quot;&gt;KDE Linux&lt;&#x2F;a&gt; distro.
This one&#x27;s particularly interesting because it&#x27;s not built on top of Docker&#x2F;podman, and is specifically built with persistence in mind.
It also has some interesting dials, like letting you decide how much of the host filesystem gets mounted into the container.
It seems like a super promising option, but it&#x27;s very early days.&lt;&#x2F;p&gt;
&lt;p&gt;Personally, I used Toolbx for probably around a year as I was a long time Fedora daily driver, and Toolbx is standard Fedora software.
In fact, when I first drafted this post, I was still using Toolbx.
However, a few months ago I picked up an open box ThinkPad for a good price (considering the... you know, everything, at the moment) and decided to use setting this machine up as an opportunity to change my daily driver to Void Linux.
It&#x27;s a great distribution, but it doesn&#x27;t use &lt;code&gt;systemd&lt;&#x2F;code&gt;, which means I needed to leave Toolbx behind.
Thankfully, it seems that any image that works as a Toolbx container will also work as a Distrobox container, so it was a very smooth switch.&lt;&#x2F;p&gt;
&lt;p&gt;Everything in this post should apply just as well to either Toolbx or Distrobox, so go with whatever&#x27;s more appealing to you.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-makes-this-a-good-fit-for-data-analysis-work&quot;&gt;What makes this a good fit for data analysis work?&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;em&gt;primary&lt;&#x2F;em&gt; use case is atomic OSes, but it&#x27;s not the only use case.
Both &lt;a href=&quot;https:&#x2F;&#x2F;distrobox.it&#x2F;#why&quot;&gt;Toolbx&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;distrobox.it&#x2F;#why&quot;&gt;Distrobox&lt;&#x2F;a&gt; list some examples of other use cases on their websites, and they can be summed up as &quot;you want to mix and match the characteristics of your host OS and a command line environment&quot;.
Funnily enough, Distrobox highlights the specific case of mixing a stable base OS with a bleeding-edge dev environment as one use case.
I think what makes these tools so attractive for data science work is exactly the opposite case: run the latest and greatest software on your machine, while keeping your work setup protected in a stable development environment.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s particularly important for those of us who work with data because we spend a lot of our time in our development environment, but we generally need to prioritise stability and continuity.&lt;&#x2F;p&gt;
&lt;p&gt;One example of this is for the sake of reproducibility.
If my code produced one result last month, I probably want the same code to produce the same result today, regardless of what updates I&#x27;ve installed on my base system in the meantime.&lt;&#x2F;p&gt;
&lt;p&gt;Another example is making sure things &quot;just work&quot;. Breaking changes can have a hugely disruptive impact on work and productivity, so I&#x27;m much more deliberate about updating workflow-critical tools than I am about all other software that I run.
Maybe one of the pieces of software in my workflow has some cool new features, but I&#x27;ll stay on a known-working version until I&#x27;m ready to deal with any friction that might arise from upgrading.
I don&#x27;t want these tools to be handled by my main distro package manager, or to fall too out of sync with any system-level dependencies that are handled by the package manager.
Toolboxes provide a great framework for isolating the work tools, giving me more agency over what I update and when.&lt;&#x2F;p&gt;
&lt;p&gt;In setting out why this approach works so well for me, I think it&#x27;s important to put some parameters on what I&#x27;m really talking about here.&lt;&#x2F;p&gt;
&lt;p&gt;I think using toolbox containers can be a great fit &lt;strong&gt;when&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You do your work on a mixed-purpose machine - i.e. the computer that you work on is also a computer you use for other things.&lt;&#x2F;li&gt;
&lt;li&gt;You want to &lt;em&gt;replace&lt;&#x2F;em&gt; working on your host OS with working in a controlled environment, rather than maintaining a mix of both workflows.&lt;&#x2F;li&gt;
&lt;li&gt;You do a lot of exploratory data analysis work - dipping in and out of different projects that can share an environment (e.g. libraries, maybe even some data files), not necessarily wanting to set up each thing that you work on as a separate self-contained environment.&lt;&#x2F;li&gt;
&lt;li&gt;Your work files live somewhere inside your home folder all the time, and are either synced to cloud storage or a source hosting repository.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;On the other hand, it&#x27;s probably &lt;strong&gt;not&lt;&#x2F;strong&gt; a good fit for you if:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You work mostly on remote machines, and want your containers to be entirely self-contained so that they can be one-click deployed on a new machine without needing to configure anything on the host.&lt;&#x2F;li&gt;
&lt;li&gt;You prefer to isolate projects from each other, only making the files and libraries of each project available inside its workspace.&lt;&#x2F;li&gt;
&lt;li&gt;Your reason for using containers is motivated purely by the goal of reproducibility.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In these cases, a more traditional container-based workflow probably makes more sense than the approach offered by tools like Toolbx.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-pros-and-cons-of-a-semi-containerised-life&quot;&gt;The pros and cons of a semi-containerised life&lt;&#x2F;h3&gt;
&lt;p&gt;Regardless of whether any of the above scenarios apply to you, I think I can boil down the approach to the following lists of pros and cons.&lt;&#x2F;p&gt;
&lt;p&gt;Some advantages of the toolbox model:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You&#x27;re free to upgrade and tinker with your host OS as much as you want, knowing nothing in the container will break.&lt;&#x2F;li&gt;
&lt;li&gt;You&#x27;re free to choose your daily driver OS without worrying about whether it&#x27;s a good fit for your work needs. If you want to run an Arch-based gaming distro on your computer but you know your R life will be much easier if you run something Debian-based because critical tools in your field don&#x27;t support Arch, you can just use a Debian-based image as a base for a toolbox container, no problem.&lt;&#x2F;li&gt;
&lt;li&gt;You can very quickly deploy an environment that has all your workflow tools, allowing you to get up and running faster on a new machine.&lt;&#x2F;li&gt;
&lt;li&gt;Your dotfiles will be picked up inside the container.&lt;&#x2F;li&gt;
&lt;li&gt;Your user-level R package library can be picked up inside each toolbox container (though this could end up being a bit of a headache, depending on your setup).&lt;&#x2F;li&gt;
&lt;li&gt;Any software that you make available through your host OS&#x27;s home directory (e.g. binaries that live in &lt;code&gt;~&#x2F;.local&#x2F;bin&lt;&#x2F;code&gt;) will be available inside the container, which can be very useful if there is software you want to share between host and container without installing it twice.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And some disadvantages:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The tight integration of the host system means that you don&#x27;t get as many guardrails as you would in a traditional container, and you need to be as careful as you would when operating on your host system&#x27;s command line.&lt;&#x2F;li&gt;
&lt;li&gt;Being inside a container can make some tasks a little bit more complicated - for example, R&#x27;s standard way of opening a web browser invokes &lt;code&gt;xdg-open&lt;&#x2F;code&gt;, but we need to replace it with a call to something like &lt;code&gt;flatpak-xdg-open&lt;&#x2F;code&gt; which allows the container to open the process on the host.&lt;&#x2F;li&gt;
&lt;li&gt;Because the container will get its home directory from the host system, it means that it can&#x27;t really be &lt;em&gt;pre-loaded&lt;&#x2F;em&gt; with things like dotfiles, as it needs to have no home directory when it&#x27;s created. This means that a Toolbx image isn&#x27;t quite as &quot;batteries included&quot; as a regular container image can be, because you&#x27;ll need to bring your own dotfiles, project files, etc. This isn&#x27;t a huge issue because you only need to source those files once, but it is a drawback.&lt;&#x2F;li&gt;
&lt;li&gt;Transitioning from a host-based workflow to a toolbox-style workflow on the same machine may not be entirely smooth. It could be the case, for example, that R packages that were installed on your host system will start to throw errors inside the container because the container&#x27;s system setup (presence of dependencies, location of library files etc) is different from the host&#x27;s.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;rolling-your-own-toolbox&quot;&gt;Rolling your own toolbox&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s pretty easy to get up and running, as the Toolbx project also publishes a number of base images that can be used as starting points for containers.
For example,using Toolbx, &lt;code&gt;toolbox create --distro fedora --release f42 f42box&lt;&#x2F;code&gt; creates a toolbox called &quot;f42box&quot; based on Fedora 42.
Alternatively, &lt;code&gt;toolbox create --image quay.io&#x2F;toolbx-images&#x2F;debian-toolbox:13&lt;&#x2F;code&gt; creates a toolbox called &quot;debian-toolbox-13&quot; from the community &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;toolbx-images&#x2F;images&quot;&gt;Debian 13 base image&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Then, you can enter the toolbox you created with &lt;code&gt;toolbox enter *toolbox-name*&lt;&#x2F;code&gt; and start to customise it to your liking.&lt;&#x2F;p&gt;
&lt;p&gt;This is the approach I used for about a year or so - I started with a Fedora base image, and I began installing the stuff I use inside it, as I would on my host machine.&lt;&#x2F;p&gt;
&lt;p&gt;However, when setting up the new ThinkPad I wanted to take the opportunity to streamline the setup process for this new machine, and the future machines that might follow it.
I knew I wanted to use a similar toolbox-based setup to the one I had been using, but I wanted to be able to start from a base image that was already tailored to my workflow and needs, instead of starting from zero.
In other words, it was time to build my own custom toolbox image.&lt;&#x2F;p&gt;
&lt;p&gt;The process of building a toolbox image is the same as building any other OCI container image, and thankfully, Jim Gardner wrote up &lt;a href=&quot;https:&#x2F;&#x2F;jimgar.github.io&#x2F;posts&#x2F;interactive-neovim-development-container-r-quarto&#x2F;post.html&quot;&gt;a really handy guide&lt;&#x2F;a&gt; on that a little while ago.
The only difference for a toolbox image is that it just needs to conform to the specific &lt;a href=&quot;https:&#x2F;&#x2F;containertoolbx.org&#x2F;doc&#x2F;#requirements&quot;&gt;requirements&lt;&#x2F;a&gt; that Toolbx has - the most important and tricky of which is that it needs to have an empty home directory.
The easiest way to ensure you&#x27;re Toolbx-compatible is to start with one of the standard Toolbx images as a base, since they&#x27;re already tailored for that purpose.
Let&#x27;s start there.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;walking-through-my-setup&quot;&gt;Walking through my setup&lt;&#x2F;h3&gt;
&lt;p&gt;I built my custom image &lt;a href=&quot;https:&#x2F;&#x2F;containertoolbx.org&#x2F;doc&#x2F;#from-a-containerfile&quot;&gt;from a Containerfile&lt;&#x2F;a&gt;, because I like doing things in a declarative way where possible.
Here it is in full:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;Containerfile&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-Containerfile &quot;&gt;&lt;code class=&quot;language-Containerfile&quot; data-lang=&quot;Containerfile&quot;&gt;&lt;span&gt;FROM registry.fedoraproject.org&#x2F;fedora-toolbox:43
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;RUN dnf --assumeyes copr enable dejan&#x2F;lazygit
&lt;&#x2F;span&gt;&lt;span&gt;RUN dnf --assumeyes copr enable atim&#x2F;starship
&lt;&#x2F;span&gt;&lt;span&gt;RUN dnf install --assumeyes fastfetch flatpak-xdg-utils fuse3 lazygit ripgrep starship stow uv wl-clipboard
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;RUN &amp;lt;&amp;lt;EOF
&lt;&#x2F;span&gt;&lt;span&gt;curl -LO https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&#x2F;releases&#x2F;download&#x2F;v0.11.7&#x2F;nvim-linux-x86_64.appimage
&lt;&#x2F;span&gt;&lt;span&gt;chmod u+x nvim-linux-x86_64.appimage
&lt;&#x2F;span&gt;&lt;span&gt;mv .&#x2F;nvim-linux-x86_64.appimage &#x2F;usr&#x2F;local&#x2F;bin&#x2F;nvim
&lt;&#x2F;span&gt;&lt;span&gt;chmod go+rx &#x2F;usr&#x2F;local&#x2F;bin&#x2F;nvim
&lt;&#x2F;span&gt;&lt;span&gt;EOF
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;RUN dnf install --assumeyes https:&#x2F;&#x2F;github.com&#x2F;r-lib&#x2F;rig&#x2F;releases&#x2F;download&#x2F;latest&#x2F;r-rig-latest-1.$(arch).rpm
&lt;&#x2F;span&gt;&lt;span&gt;RUN rig add --without-p3m 4.4
&lt;&#x2F;span&gt;&lt;span&gt;RUN rig add --without-p3m 4.5
&lt;&#x2F;span&gt;&lt;span&gt;RUN rig add --without-p3m release
&lt;&#x2F;span&gt;&lt;span&gt;RUN rig system add-pak --all
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;RUN &amp;lt;&amp;lt;EOF
&lt;&#x2F;span&gt;&lt;span&gt;curl -Lo &#x2F;tmp&#x2F;arf.tar.xz https:&#x2F;&#x2F;github.com&#x2F;eitsupi&#x2F;arf&#x2F;releases&#x2F;latest&#x2F;download&#x2F;arf-console-x86_64-unknown-linux-gnu.tar.xz
&lt;&#x2F;span&gt;&lt;span&gt;tar -C &#x2F;tmp -xf &#x2F;tmp&#x2F;arf.tar.xz
&lt;&#x2F;span&gt;&lt;span&gt;mv &#x2F;tmp&#x2F;arf-console-x86_64-unknown-linux-gnu&#x2F;arf &#x2F;usr&#x2F;local&#x2F;bin&#x2F;arf
&lt;&#x2F;span&gt;&lt;span&gt;chown root:root &#x2F;usr&#x2F;local&#x2F;bin&#x2F;arf
&lt;&#x2F;span&gt;&lt;span&gt;rm -r &#x2F;tmp&#x2F;arf-console-x86_64-unknown-linux-gnu &#x2F;tmp&#x2F;arf.tar.xz
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;arf --version
&lt;&#x2F;span&gt;&lt;span&gt;EOF
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;ENV QUARTO_VERSION=&amp;quot;1.10.18&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;RUN &amp;lt;&amp;lt;EOF
&lt;&#x2F;span&gt;&lt;span&gt;mkdir -p &#x2F;opt&#x2F;quarto&#x2F;${QUARTO_VERSION}
&lt;&#x2F;span&gt;&lt;span&gt;curl -o &#x2F;tmp&#x2F;quarto.tar.gz -L https:&#x2F;&#x2F;github.com&#x2F;quarto-dev&#x2F;quarto-cli&#x2F;releases&#x2F;download&#x2F;v${QUARTO_VERSION}&#x2F;quarto-${QUARTO_VERSION}-linux-amd64.tar.gz
&lt;&#x2F;span&gt;&lt;span&gt;tar -C &#x2F;opt&#x2F;quarto&#x2F;${QUARTO_VERSION} -xzvf &#x2F;tmp&#x2F;quarto.tar.gz --strip-components=1
&lt;&#x2F;span&gt;&lt;span&gt;rm &#x2F;tmp&#x2F;quarto.tar.gz
&lt;&#x2F;span&gt;&lt;span&gt;ln -s &#x2F;opt&#x2F;quarto&#x2F;${QUARTO_VERSION}&#x2F;bin&#x2F;quarto &#x2F;usr&#x2F;local&#x2F;bin&#x2F;quarto
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;quarto check
&lt;&#x2F;span&gt;&lt;span&gt;EOF
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;ENV RV_VERSION=&amp;quot;0.22.2&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;RUN &amp;lt;&amp;lt;EOF
&lt;&#x2F;span&gt;&lt;span&gt;mkdir -p &#x2F;opt&#x2F;rv&#x2F;${RV_VERSION}
&lt;&#x2F;span&gt;&lt;span&gt;curl -o &#x2F;tmp&#x2F;rv.tar.gz -L https:&#x2F;&#x2F;github.com&#x2F;A2-ai&#x2F;rv&#x2F;releases&#x2F;download&#x2F;v${RV_VERSION}&#x2F;rv-v${RV_VERSION}-x86_64-unknown-linux-gnu.tar.gz
&lt;&#x2F;span&gt;&lt;span&gt;tar -C &#x2F;opt&#x2F;rv&#x2F;${RV_VERSION}&#x2F; -xzvf &#x2F;tmp&#x2F;rv.tar.gz
&lt;&#x2F;span&gt;&lt;span&gt;rm &#x2F;tmp&#x2F;rv.tar.gz
&lt;&#x2F;span&gt;&lt;span&gt;chmod +x &#x2F;opt&#x2F;rv&#x2F;${RV_VERSION}&#x2F;rv
&lt;&#x2F;span&gt;&lt;span&gt;ln -s &#x2F;opt&#x2F;rv&#x2F;${RV_VERSION}&#x2F;rv &#x2F;usr&#x2F;local&#x2F;bin&#x2F;rv
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;rv --version
&lt;&#x2F;span&gt;&lt;span&gt;EOF
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;RUN dnf clean all
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It should be pretty self-explanatory if you&#x27;ve seen a Containerfile before (or if you read Jim Gardner&#x27;s post!), but I&#x27;ll explain my choices a little bit.&lt;&#x2F;p&gt;
&lt;p&gt;I originally explored using a Debian base image for my development environment, as I wondered whether Fedora&#x27;s release cadence might be a little too fast for the purpose at hand, and Debian is usually the go-to for stability.
However, after years of Fedora usage, I was pretty shocked at how out of date the software in the Debian repos (not just in &lt;code&gt;stable&lt;&#x2F;code&gt;!) was compared to Fedora.
So, in the end, I opted for Fedora 43 as a starting point, which should be perfectly fine for the foreseeable future, and requires less tinkering out of the box.&lt;&#x2F;p&gt;
&lt;p&gt;The bulk of the Containerfile is basically just installing the software I want to be available out of the box.
I use &lt;code&gt;rig&lt;&#x2F;code&gt; for R installation management, and rig provides an RPM package for Fedora 43, making installation a breeze.
Using rig, I make sure I have R 4.4.x and 4.5.x available in the container, the two versions I have projects with dependencies on.
The rest is fairly straightforward if you know the shape of my workflow from previous posts.
&lt;a href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;&quot;&gt;Neovim&lt;&#x2F;a&gt; for editing, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jesseduffield&#x2F;lazygit&quot;&gt;lazygit&lt;&#x2F;a&gt; for lazy git, &lt;a href=&quot;https:&#x2F;&#x2F;quarto.org&#x2F;&quot;&gt;Quarto&lt;&#x2F;a&gt; for computational notebooks, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;astral-sh&#x2F;uv&quot;&gt;uv&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;A2-ai&#x2F;rv&quot;&gt;rv&lt;&#x2F;a&gt; for managing Python and R projects.
I chose to use the new kid on the block &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;eitsupi&#x2F;arf&quot;&gt;arf&lt;&#x2F;a&gt; as the R REPL, since it comes as a single binary that&#x27;s a bit easier to install than &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;randy3k&#x2F;radian&quot;&gt;radian&lt;&#x2F;a&gt;, which is a Python package (and is also no longer being actively maintained, unfortunately).
After using arf for a few months, this was a good decision - it&#x27;s great software.&lt;&#x2F;p&gt;
&lt;p&gt;Normally, I&#x27;d install install a lot of these tools on my system by symlinking the binaries into &lt;code&gt;~&#x2F;.local&#x2F;bin&lt;&#x2F;code&gt;, but since we need to stay out of the home directory, I instead target &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&lt;&#x2F;code&gt; in the Containerfile.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s it, really.
Not much else needs to be done.
Toolbx or Distrobox handle all the configuration of entrypoints and mounts etc.
Environment variables can be picked up from your dotfiles later.
As long as I clone &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;neovim_config&quot;&gt;my Neovim config&lt;&#x2F;a&gt; into &lt;code&gt;~&#x2F;.config&#x2F;nvim&lt;&#x2F;code&gt; at some point (note that I could do this from the host), then when I run &lt;code&gt;nvim&lt;&#x2F;code&gt; for the first time inside the toolbox, it will configure itself how I like and get all my plugins installed.&lt;&#x2F;p&gt;
&lt;p&gt;If you really want to pre-configure some of the software, and the software allows config files to be placed in a system-level config file location, you could handle putting your config files there within the Containerfile.
Just bear in mind that if you also have a config file in the user-level config file location, that will usually take precedence.&lt;&#x2F;p&gt;
&lt;p&gt;I suppose there&#x27;s also the question of pre-installing R packages somewhere outside of the home directory and making sure that library is added to your R profile.
But I decided I&#x27;d rather just do a supervised installation of R packages after setup.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deployment&quot;&gt;Deployment&lt;&#x2F;h3&gt;
&lt;p&gt;You can build the image from the Containerfile by running:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;podman&lt;&#x2F;span&gt;&lt;span&gt; build&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt; --squash --tag&lt;&#x2F;span&gt;&lt;span&gt; localhost&#x2F;f43custom .
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;from the directory with the Containerfile in it.&lt;&#x2F;p&gt;
&lt;p&gt;Then, if everything builds smoothly, you create your Toolbx with&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;toolbox&lt;&#x2F;span&gt;&lt;span&gt; create&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt; --image&lt;&#x2F;span&gt;&lt;span&gt; f43custom workbox
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or, in my case (the &lt;code&gt;--unshare-process&lt;&#x2F;code&gt; flag is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;89luca89&#x2F;distrobox&#x2F;pull&#x2F;1982&quot;&gt;needed&lt;&#x2F;a&gt; on a &lt;code&gt;systemd&lt;&#x2F;code&gt;-free system):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;distrobox&lt;&#x2F;span&gt;&lt;span&gt; create&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt; --image&lt;&#x2F;span&gt;&lt;span&gt; f43custom&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt; --name&lt;&#x2F;span&gt;&lt;span&gt; workbox&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt; --unshare-process
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and enter it with &lt;code&gt;toolbox enter workbox&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;distrobox enter workbox&lt;&#x2F;code&gt;.
I also have an alias set up so that I can run &lt;code&gt;distrobox enter workbox &amp;amp;&amp;amp; nvim&lt;&#x2F;code&gt; in a brief command.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;&#x2F;h2&gt;
&lt;p&gt;I should point out that the Containerfile above is still only an early attempt at this, and I&#x27;ll probably continue to tinker around the edges of my setup, as usual.
I am interested in whether I can get the size of the uncompressed image down, though I don&#x27;t have the spare time to go down that rabbit hole just yet.
For now, I&#x27;m pretty happy just to have something that works as intended.&lt;&#x2F;p&gt;
&lt;p&gt;For my use case, the goal is &lt;strong&gt;not&lt;&#x2F;strong&gt; to constantly update the Containerfile and rebuild the container with the latest and greatest versions of the software.
When a new version of arf or rv or Quarto is released and I want to move to it, I simply download it, enter the toolbox, and move the new version to &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&lt;&#x2F;code&gt; etc in the toolbox.
No need to rebuild or anything.
In general, when a new tool altogether is added to the container or a major change is made, then it&#x27;s time to update the Containerfile to reflect that.
It&#x27;s about keeping the Containerfile in sync with the state of the container, so that I can feel ready to rebuild it quickly if I needed to.&lt;&#x2F;p&gt;
&lt;p&gt;Obviously, this kind of thing is always going to end up being pretty specific to the needs and preferences of the individual user.
But if it turns out that I&#x27;m not the only person that finds this approach useful, I wonder whether having a few curated starting images available would be a nice resource for the R&#x2F;data science&#x2F;computational social science community.
The &lt;a href=&quot;https:&#x2F;&#x2F;rocker-project.org&#x2F;&quot;&gt;rocker&lt;&#x2F;a&gt; project has been a great resource for people, and I note that there is already some pretty good representation in the &lt;a href=&quot;https:&#x2F;&#x2F;containers.dev&#x2F;features?search=rocker&quot;&gt;devcontainer&lt;&#x2F;a&gt; spec space for features from the data science world.
Maybe a goal could be to build a stock of tried and tested Toolbx-compatible images that are tailored to data science workflows, and push these out to a container registry for others to use as a starting point.&lt;&#x2F;p&gt;
&lt;p&gt;In the meantime, I&#x27;ve &lt;a href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;repository&#x2F;docker&#x2F;petejonesphd&#x2F;quarto_toolbox&#x2F;general&quot;&gt;pushed mine to Docker Hub&lt;&#x2F;a&gt; in case anyone wants to try it out without having to build the image from the Containerfile.
The &lt;a href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;repository&#x2F;docker&#x2F;petejonesphd&#x2F;quarto_toolbox&#x2F;general&quot;&gt;repo&lt;&#x2F;a&gt; has the Fedora 43-based image, which is tagged f43, and it has an equivalent image which is Debian-based, tagged debian13.&lt;&#x2F;p&gt;
&lt;p&gt;In any case, let me know if you found this post useful, or if you know of other tools that complement the kind of approach I&#x27;ve described here.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A brief guide to using Neovim as an R (and Quarto) development environment</title>
        <published>2025-01-29T00:00:00+00:00</published>
        <updated>2025-01-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Pete Jones
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://petejon.es/posts/2025-01-29-using-neovim-for-r/"/>
        <id>https://petejon.es/posts/2025-01-29-using-neovim-for-r/</id>
        
        <content type="html" xml:base="https://petejon.es/posts/2025-01-29-using-neovim-for-r/">&lt;p&gt;For the last year or so I&#x27;ve been using &lt;a href=&quot;https:&#x2F;&#x2F;neovim.io&quot;&gt;Neovim&lt;&#x2F;a&gt; as my daily R programming environment after years of using Posit&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;posit.co&#x2F;products&#x2F;open-source&#x2F;rstudio&#x2F;&quot;&gt;RStudio&lt;&#x2F;a&gt;.
I was mostly just exploring alternative environments for the sake of exploring to begin with, but I found it such an effective editing experience that I&#x27;ve never looked back.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike RStudio, Neovim isn&#x27;t specialised for R, or for data science more generally, but it&#x27;s a general purpose tool for coding work and plain text editing. This is great, because it means the user base is huge, and the chances that somebody has already solved whatever problem or pain-point you might run into are high. However, it also means that the information available for how to get up and running with Neovim isn&#x27;t super tailored to the kinds of features and workflows somebody coming from an RStudio-type environment might expect.&lt;&#x2F;p&gt;
&lt;p&gt;Here, I want to talk a little about my experience with making this shift and provide some advice in the hopes that somebody else might be able to make the transition relatively smoothly. It&#x27;s a kind of &quot;what I wish I knew when I started out&quot; post.&lt;&#x2F;p&gt;
 &lt;!----&gt;


&lt;div
  class=&quot;my-4 flex flex-col rounded-lg bg-[var(--admonition-bg)]&quot;
  style=&quot;--admonition-bg: rgba(83, 211, 230, 0.1)&quot;
&gt;
  &lt;div class=&quot;flex items-center rounded-t-lg bg-[var(--admonition-bg)] p-1&quot;&gt;
    &lt;div
      class=&quot;mx-2 h-4 w-4 text-[0] [background:var(--url)_center_center_no-repeat] dark:invert&quot;
      style=&quot;--url: url(.&#x2F;icons&#x2F;info.svg)&quot;
    &gt;
      info
    &lt;&#x2F;div&gt;
    &lt;span&gt;&lt;strong&gt;Update from May 2025&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;pl-4&quot;&gt;&lt;p&gt;This post is only a few months old, but already some of the details I discuss here are a little outdated.
Neovim version 0.11 introduced new built-in LSP configuration features which have had knock-on effects on the plugin ecosystem.
In particular, the plugins &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;nvim-lspconfig&quot;&gt;&lt;code&gt;nvim-lspconfig&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mason-org&#x2F;mason-lspconfig.nvim&quot;&gt;&lt;code&gt;mason-lspconfig&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; have scaled back their role, and you can now configure LSP in Neovim without those plugins.&lt;&#x2F;p&gt;
&lt;p&gt;Everything else in this post not related to LSP should remain valid.
Personally, I&#x27;ve since migrated to use &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Saghen&#x2F;blink.cmp&quot;&gt;&lt;code&gt;blink.cmp&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; as my completion engine, but at the time of writing &lt;code&gt;kickstart&lt;&#x2F;code&gt; continues to ship with &lt;code&gt;nvim-cmp&lt;&#x2F;code&gt;, so this post remains in line with the &lt;code&gt;kickstart&lt;&#x2F;code&gt;-based approach.&lt;&#x2F;p&gt;
&lt;p&gt;I will probably write an updated post at some point, but until then I recommend &lt;a href=&quot;https:&#x2F;&#x2F;gpanders.com&#x2F;blog&#x2F;whats-new-in-neovim-0-11&#x2F;&quot;&gt;this post&lt;&#x2F;a&gt; to learn more about the v0.11 changes.
See also the note on &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;neovim_config&quot;&gt;my personal Neovim config repo&lt;&#x2F;a&gt; about where the commit history becomes dependent on Neovim v0.11+ and deviates from this post.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;some-preliminary-notes&quot;&gt;Some preliminary notes&lt;&#x2F;h2&gt;
&lt;p&gt;Before we get stuck in, let&#x27;s just do some quick expectation management, both for this post and for switching to Neovim.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;is-neovim-for-you&quot;&gt;Is Neovim for you?&lt;&#x2F;h3&gt;
&lt;p&gt;From my perspective, one of the key reasons for using Neovim is that it offers you the flexibility and control to turn it into the tool you want it to be. Rather than presenting an off-the-shelf experience where the details of how everything works are abstracted away from the user, Neovim offers an initially sparse tool. Through building from that starting point to your own personalised development environment, you learn how the tools you&#x27;re using every day work, and can cherry pick and tune based on how you would &lt;em&gt;like&lt;&#x2F;em&gt; them all to work.&lt;&#x2F;p&gt;
&lt;p&gt;These reasons why I&#x27;m drawn to Neovim might be the same reasons that it&#x27;s not right for you. There is an undeniable learning curve, and if you&#x27;re not interested in these aspects of your relationship to your development environment, it may not be worth it to you. In the rest of this post, I&#x27;m going to assume that you&#x27;re at least curious.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;disclaimer-1-i-can-t-speak-for-all-r-users&quot;&gt;Disclaimer 1: I can&#x27;t speak for all R users&lt;&#x2F;h3&gt;
&lt;p&gt;My experience and my advice is based on my own way of working with data in R, which isn&#x27;t going to be the same as everyone else&#x27;s. In particular, my workflow is generally built around interactive local work, with lots of data wrangling and exploratory analysis. Write some code, send it to the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Read%E2%80%93eval%E2%80%93print_loop&quot;&gt;REPL&lt;&#x2F;a&gt;, see how its output looks, tweak if necessary, repeat.&lt;&#x2F;p&gt;
&lt;p&gt;I also increasingly use &lt;a href=&quot;https:&#x2F;&#x2F;quarto.org&quot;&gt;Quarto&lt;&#x2F;a&gt; notebooks rather than R scripts for a lot of my work, as I usually need to share what I find with non-technical colleagues who are only interested in the results, and Quarto is ideal for this.&lt;&#x2F;p&gt;
&lt;p&gt;My Neovim set-up is built around these two aspects of my workflow, and it might not cover the tooling that others with different needs require. That doesn&#x27;t mean it&#x27;s not possible to get what you need in Neovim, only that I can&#x27;t personally speak to it!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;disclaimer-2-don-t-expect-a-drop-in-replacement-for-every-feature-you-use-now&quot;&gt;Disclaimer 2: Don&#x27;t expect a drop-in replacement for every feature you use now&lt;&#x2F;h3&gt;
&lt;p&gt;This isn&#x27;t a post about how to turn Neovim into a clone of RStudio or VSCode&#x2F;Positron.
If you want that, it would make more sense to just use those tools and enable their settings for vim keybindings.&lt;&#x2F;p&gt;
&lt;p&gt;Most of what those apps offer can be done in Neovim, but one of the inevitable costs of using a TUI-based setup is that some of their features are out of scope.
In particular, things like the built-in image&#x2F;plot viewer, the nicely-formatted dataframe viewer, and the web page browser are not easily replicable in Neovim.&lt;&#x2F;p&gt;
&lt;p&gt;For me, this isn&#x27;t a big deal, because you can just use your window manager to handle those tasks as and when you need them (except for the dataframe viewer - the X window that &lt;code&gt;View()&lt;&#x2F;code&gt; invokes in R is hideous and if anyone knows of a better option, I&#x27;d love to know).
If you really want them all to be contained within a single application window though, you might not adjust well to Neovim.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;first-steps-with-neovim&quot;&gt;First steps with Neovim&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;vim-basics&quot;&gt;Vim basics&lt;&#x2F;h3&gt;
&lt;p&gt;Neovim is a based on &lt;a href=&quot;https:&#x2F;&#x2F;www.vim.org&#x2F;&quot;&gt;vim&lt;&#x2F;a&gt;, with an added focus on making vim&#x27;s capabilities customisable and extensible through the embedded &lt;a href=&quot;https:&#x2F;&#x2F;www.lua.org&quot;&gt;Lua&lt;&#x2F;a&gt; language runtime, as well as providing more built-in tooling (like an LSP client and the Tree-sitter library, more on which &lt;a href=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2025-01-29-using-neovim-for-r&#x2F;#static-code-analysis-lsp-and-tree-sitter&quot;&gt;later&lt;&#x2F;a&gt;).
In order to get started with Neovim, you need to wrap your head around vim and the idea of &lt;em&gt;editing modes&lt;&#x2F;em&gt; and &lt;em&gt;motions&lt;&#x2F;em&gt; if you haven&#x27;t encountered these before.
I won&#x27;t go into that here, because there are far better &lt;a href=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2025-01-29-using-neovim-for-r&#x2F;#useful-links-and-resources&quot;&gt;resources for learning vim&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My advice would be to start with the built-in &lt;code&gt;vimtutor&lt;&#x2F;code&gt; tutorial (in Neovim, type &lt;code&gt;:Tutor&lt;&#x2F;code&gt; and hit enter), which walks you through the basics.
After that, keep practising by trying to do what you normally do with your code in the vim way for a few days.
Expect to forget key bindings etc., and to find things much slower at first.
But if you stick with it, you&#x27;ll quickly notice that you have more tools at your fingertips for doing all the most common things you do when editing text files (e.g. changing words and lines, jumping to specific points in the document, repeating changes) naturally and quickly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;neovim-distributions&quot;&gt;Neovim distributions&lt;&#x2F;h3&gt;
&lt;p&gt;Because Neovim (like vim) is rather spartan out of the box, you don&#x27;t get IDE-like functionality until you start configuring and extending it to do more.
This is a challenge for newcomers, as it takes time to build the knowledge and confidence you need to start personalising the experience based on your preferences.
For this reason, it&#x27;s common for people to use &quot;Neovim distributions&quot; - which really just means a set of plugins and config files that provide a more ready-to-go (and opinionated) Neovim experience.&lt;&#x2F;p&gt;
&lt;p&gt;I personally recommend avoiding these options at first, and instead starting with the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvim-lua&#x2F;kickstart.nvim&quot;&gt;&lt;code&gt;kickstart&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; setup, which is designed to achieve the same thing while teaching you how everything works along the way.
My recommendation is to start with &lt;code&gt;kickstart&lt;&#x2F;code&gt; (I personally prefer the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dam9000&#x2F;kickstart-modular.nvim&quot;&gt;modular variant&lt;&#x2F;a&gt; which splits the setup over multiple files) and tweak it as you learn, eventually making it your own.
That&#x27;s the path I took, and it informs my suggestions throughout this post.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;neovim-s-plugin-ecosystem&quot;&gt;Neovim&#x27;s plugin ecosystem&lt;&#x2F;h3&gt;
&lt;p&gt;The key to Neovim&#x27;s power is its plugin ecosystem.
Plugins are written in Lua, and they add new features, customisations and user commands to the base Neovim experience.&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re following the &lt;code&gt;kickstart&lt;&#x2F;code&gt; path, you&#x27;ll use the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;folke&#x2F;lazy.nvim&quot;&gt;&lt;code&gt;Lazy.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin as your tool for installing and configuring plugins.
The general workflow for this is to create Lua files in a plugin directory within your Neovim config.
In these files, you use Lua tables to provide the location of the repository containing the plugin and the configuration options you want to use, and then &lt;code&gt;Lazy&lt;&#x2F;code&gt; will set everything up when you launch Neovim.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;adding-in-features&quot;&gt;Adding in features&lt;&#x2F;h2&gt;
&lt;p&gt;Up until now we&#x27;ve focused on generic Neovim familiarity, but now let&#x27;s talk about turning Neovim into something useful for doing interactive data analysis work.&lt;&#x2F;p&gt;
&lt;p&gt;The key here is understanding what the useful features that an IDE like RStudio offers are and how they work.
In brief, advanced editors offer static code analysis tooling (which is used for features like auto-indentation, diagnostics and auto-completion), a way of sending code from a source file to a REPL and running it, easy access to a file browser, and other quality of life touches.
Each of these can be added to Neovim.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;static-code-analysis-lsp-and-tree-sitter&quot;&gt;Static code analysis: LSP and Tree-sitter&lt;&#x2F;h3&gt;
&lt;p&gt;Many of the most useful features that editors offer are based on parsing and understanding your code in order to highlight it, lint it, keep track of document symbols, suggest completions and let you know if something doesn&#x27;t look right.&lt;&#x2F;p&gt;
&lt;p&gt;Neovim has built-in support for all of this, and it takes two different forms.
First, Neovim contains an &lt;a href=&quot;https:&#x2F;&#x2F;microsoft.github.io&#x2F;language-server-protocol&#x2F;&quot;&gt;LSP&lt;&#x2F;a&gt; client that can receive information from language servers and report it back to you.
Second, Neovim ships with &lt;a href=&quot;https:&#x2F;&#x2F;tree-sitter.github.io&#x2F;&quot;&gt;Tree-sitter&lt;&#x2F;a&gt;, an incremental parsing library that builds an abstract syntax tree (AST) from code.
Together, LSP support and Tree-sitter provide the information that the editor can use to &quot;understand&quot; your code and make suggestions, and many plugins take advantage of this information.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;syntax-highlighting&quot;&gt;Syntax highlighting&lt;&#x2F;h4&gt;
&lt;p&gt;Neovim does provide its own default syntax highlighting, but the highlighting based on Tree-sitter&#x27;s AST is much better.
The way to take advantage of this is to use the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvim-treesitter&#x2F;nvim-treesitter&quot;&gt;&lt;code&gt;nvim-treesitter&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin to install the R parser and configure it.
Most of the work for setting this up is already handled in &lt;code&gt;kickstart&lt;&#x2F;code&gt;, so you just need to make sure the R parser is installed.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;the-r-language-server&quot;&gt;The R language server&lt;&#x2F;h4&gt;
&lt;p&gt;To take advantage of LSP for R, you just need to make sure you have the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;REditorSupport&#x2F;languageserver&#x2F;&quot;&gt;&lt;code&gt;languageserver&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; package installed and then configure it with &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;nvim-lspconfig&quot;&gt;&lt;code&gt;nvim-lspconfig&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
The {languageserver} package incorporates several different R packages that handle things like linting and formatting of R code, and covers a lot of LSP capabilities.&lt;&#x2F;p&gt;
&lt;p&gt;In general, the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;williamboman&#x2F;mason.nvim&quot;&gt;&lt;code&gt;mason.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin is a great way to handle the installation of language-specific LSP-related tools, as it provides a centralised registry and will do all the work for you.
However, as R&#x27;s language server is implemented in R as an R package, I&#x27;ve found that it&#x27;s best to just install it however you normally install R packages.
The important thing is that you tell &lt;code&gt;nvim-lspconfig&lt;&#x2F;code&gt; that &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;nvim-lspconfig&#x2F;blob&#x2F;master&#x2F;doc&#x2F;configs.md#r_language_server&quot;&gt;the command to run it is &lt;code&gt;R --no-echo -e languageserver::run()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;completion&quot;&gt;Completion&lt;&#x2F;h4&gt;
&lt;p&gt;The primary approach to implementing auto-completion is via the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hrsh7th&#x2F;nvim-cmp&quot;&gt;&lt;code&gt;nvim-cmp&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin.
This plugin draws on various sources such as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hrsh7th&#x2F;cmp-nvim-lsp&quot;&gt;LSP&lt;&#x2F;a&gt; and the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hrsh7th&#x2F;cmp-path&quot;&gt;file system&lt;&#x2F;a&gt; to offer a highly customisable list of completion suggestions as you type.
You can also integrate code snippets (e.g. via &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;L3MON4D3&#x2F;LuaSnip&quot;&gt;&lt;code&gt;luasnip&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;) so that when you confirm a snippet completion suggestion, it will enact a whole snippet insertion.&lt;&#x2F;p&gt;
&lt;p&gt;There does seem to be some buzz around an alternative completion plugin called &lt;a href=&quot;https:&#x2F;&#x2F;cmp.saghen.dev&#x2F;&quot;&gt;&lt;code&gt;Blink&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which claims to be much faster.
However, I haven&#x27;t tried it yet, so I can&#x27;t vouch for it.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;diagnostics&quot;&gt;Diagnostics&lt;&#x2F;h4&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;folke&#x2F;trouble.nvim&quot;&gt;&lt;code&gt;trouble.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin provides a nice way of working with the diagnostics provided by linters and language servers.
Just make sure you customise your &lt;a href=&quot;https:&#x2F;&#x2F;lintr.r-lib.org&#x2F;articles&#x2F;lintr.html#the--lintr-file&quot;&gt;.lintr file&lt;&#x2F;a&gt; to suit your preferences, otherwise you might be overwhelmed by notes and complaints.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;document-overview-and-navigation&quot;&gt;Document overview and navigation&lt;&#x2F;h4&gt;
&lt;p&gt;LSP and Tree-sitter provide an outline of your document which can be helpful in a few ways.
One is that you can quickly get a sense of the document symbols (i.e. R variables and objects) in your document.
Another is that you can quickly navigate to different points in your document based on these symbols.&lt;&#x2F;p&gt;
&lt;p&gt;For both of these functions, I use the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stevearc&#x2F;aerial.nvim&quot;&gt;&lt;code&gt;aerial.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin.
It&#x27;s really useful in Quarto&#x2F;RMarkdown documents in conjunction with a Markdown language server like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;artempyanykh&#x2F;marksman&quot;&gt;&lt;code&gt;marksman&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, because it provides a document outline of headings and subheadings, similar to RStudio&#x27;s toggleable outline tree.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;code-runners&quot;&gt;Code runners&lt;&#x2F;h3&gt;
&lt;p&gt;For me, the key to a good interactive workflow is being able to effortlessly send code to run in the REPL.
In Neovim, there are a few options for replicating this type of behaviour.&lt;&#x2F;p&gt;
&lt;p&gt;The first one that I used for a while is the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jpalardy&#x2F;vim-slime&quot;&gt;&lt;code&gt;vim-slime&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin, which is itself based on an &lt;a href=&quot;https:&#x2F;&#x2F;slime.common-lisp.dev&quot;&gt;Emacs feature&lt;&#x2F;a&gt;.
That worked pretty well for a while (it&#x27;s particularly useful for users of terminal multiplexers like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tmux&#x2F;tmux&quot;&gt;tmux&lt;&#x2F;a&gt;), but it failed to do what I needed often enough that I kept looking for other options.&lt;&#x2F;p&gt;
&lt;p&gt;And then I found &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Vigemus&#x2F;iron.nvim&quot;&gt;&lt;code&gt;iron.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and I have never looked back.
&lt;code&gt;Iron&lt;&#x2F;code&gt; does exactly what I want: it takes some text, and feeds it to a built-in Neovim terminal running an R session where it is executed.
Most importantly, it has customisable keybindings for selecting which text to send, so you can have different shortcuts for sending the current selection, or a line, a paragraph, from the cursor position to the end of the document, and so on.
By integrating vim motions into the &quot;send to REPL&quot; process, &lt;code&gt;Iron&lt;&#x2F;code&gt; actually provides a way more powerful version of this key feature than you typically find in other IDEs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Iron&lt;&#x2F;code&gt; has some other nice features, like being able to map file types to REPL programs, so you can send R code to &lt;code&gt;radian&lt;&#x2F;code&gt;, Julia code to &lt;code&gt;julia&lt;&#x2F;code&gt;, Python code to &lt;code&gt;ipython&lt;&#x2F;code&gt;, and so on.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;quarto-specific-features&quot;&gt;Quarto-specific features&lt;&#x2F;h3&gt;
&lt;p&gt;The key to a smooth Quarto experience in Neovim is the fabulous &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jmbuhr&#x2F;otter.nvim&quot;&gt;&lt;code&gt;otter.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin by Jannik Buhr.
&lt;code&gt;otter&lt;&#x2F;code&gt; takes a notebook document and creates hidden buffers (one per embedded language) containing all the code from inside that language&#x27;s code chunks.
Then, the language server for that language is run on the buffer, and the responses are passed back to the initial notebook document buffer.
It also provides a completion source for tools like &lt;code&gt;nvim-cmp&lt;&#x2F;code&gt;.
The upshot of this is that, when you&#x27;re outside of a code block, you&#x27;ll get Markdown-based results from LSP-interfacing features like completion, but inside a code block, you&#x27;ll get responses for the language of the code block.
Thus, when you&#x27;re working on R code in a .qmd file, and you start typing inside a chunk, the autocompletion suggestions will work as they would in a regular .R file.&lt;&#x2F;p&gt;
&lt;p&gt;Another nice feature is that Tree-sitter knows what a fenced code block looks like in a markdown-based document, which means you can set up your own keybindings for jumping to the next&#x2F;previous code chunk (I use &quot;[[&quot; and &quot;]]&quot; for this), which makes navigating Quarto notebooks a breeze.
It also means you can highlight your code chunks to keep them visually distinct, and you can use the contents of a code chunk as the text object selection for &lt;code&gt;Iron&lt;&#x2F;code&gt; (i.e. you can &quot;run code chunk&quot;).&lt;&#x2F;p&gt;
&lt;p&gt;Finally, one feature that makes RStudio a great editor for Quarto documents is that there are commands for &quot;Run all chunks&quot;, &quot;Run all chunks above&quot;, etc., which execute the code inside code blocks in the REPL.
This is really useful for jumping into a notebook and catching up the REPL&#x27;s active R session to a certain point in the notebook (for example, to run a data cleaning pipeline before continuing to explore a dataset).
Unfortunately, this being an editor-based feature means that it&#x27;s not easily replicable in other editors like Neovim where the workflow (e.g. choice of code runner) is more variable between users.
Instead of thinking of running the chunks in a notebook as an editor-specific feature, we can instead think of it as a language-based feature that doesn&#x27;t depend on editor.
This is what the &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;catchup&quot;&gt;{catchup}&lt;&#x2F;a&gt; package is for.
You call the &lt;code&gt;catchup()&lt;&#x2F;code&gt; function from inside R, telling it which notebook to run (and, optionally, which parts to run) and it will do it.
This effectively recreates the &quot;Run all chunks...&quot; family of features, making it accessible in Neovim or any other development environment.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;other-utilities&quot;&gt;Other utilities&lt;&#x2F;h3&gt;
&lt;p&gt;Finally, here&#x27;s a quick roundup of some other quality-of-life things that I recommend.&lt;&#x2F;p&gt;
&lt;p&gt;First of all, if you are using R outside of RStudio, you will probably have a nicer time if you use &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;randy3k&#x2F;radian&quot;&gt;&lt;code&gt;radian&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; as your REPL instead of the base R interpreter.
&lt;code&gt;radian&lt;&#x2F;code&gt; takes inspiration from the excellent &lt;a href=&quot;https:&#x2F;&#x2F;docs.julialang.org&#x2F;en&#x2F;v1&#x2F;stdlib&#x2F;REPL&#x2F;&quot;&gt;Julia REPL&lt;&#x2F;a&gt;, and has lots of nice features: it&#x27;s very configurable, it has built-in syntax highlighting and auto-completion, and it has a super convenient shell mode.
I find the shell mode particularly convenient for Quarto, because the Quarto CLI is just a keystroke away.&lt;&#x2F;p&gt;
&lt;p&gt;Next, you probably want a file browser solution.
There are plenty of popular choices for interacting with the filesystem in Neovim.
If you like a toggleable tree-like sidebar, there&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvim-tree&#x2F;nvim-tree.lua&quot;&gt;&lt;code&gt;nvim-tree&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvim-neo-tree&#x2F;neo-tree.nvim&quot;&gt;&lt;code&gt;Neo-tree&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
I personally use the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;echasnovski&#x2F;mini.nvim&#x2F;blob&#x2F;main&#x2F;readmes&#x2F;mini-files.md&quot;&gt;&lt;code&gt;files&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; module from &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;echasnovski&#x2F;mini.nvim&quot;&gt;&lt;code&gt;mini.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which is a simple dropdown that enables quickly navigating and editing the filesystem.
A similar plugin that is incredibly popular is &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stevearc&#x2F;oil.nvim&quot;&gt;&lt;code&gt;oil.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For git integration, there are popular plugins such as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tpope&#x2F;vim-fugitive&quot;&gt;&lt;code&gt;vim-fugitive&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which may be a good choice for some workflows.
However, I tend to use &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jesseduffield&#x2F;lazygit&quot;&gt;&lt;code&gt;lazygit&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for most git operations, and there is a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kdheepak&#x2F;lazygit.nvim&quot;&gt;&lt;code&gt;lazygit.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin that integrates it beautifully into Neovim.&lt;&#x2F;p&gt;
&lt;p&gt;I haven&#x27;t covered debugging here, but there are a lot of tools in this area.
A good place to start is probably &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mfussenegger&#x2F;nvim-dap&quot;&gt;&lt;code&gt;nvim-dap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, and I recommend setting up a session manager which can keep track of your Neovim workspace (working directory, active buffers, window layout etc.) and give you a quick way of jumping into projects.
Neovim (via vim) has built-in support for saving and restoring workspace sessions, but plugins like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Shatur&#x2F;neovim-session-manager&quot;&gt;&lt;code&gt;neovim-session-manager&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; help make the process of interacting with that feature more user-friendly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;When trying to figure out whether you can do something in Neovim, the general rule of thumb is this:
if your need is related to a general programming&#x2F;text editing problem, there will certainly be a solution in Neovim (usually via plugins), because it&#x27;s used by millions of developers from a wide range of languages and domains.
If the need is related to a data science&#x2F;data analysis problem or is specific to R, there may well be a Neovim solution developed, but it&#x27;s a little less likely as the user base for those domains just isn&#x27;t as big.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to take a look at my Neovim config files for inspiration or to try and learn more, they&#x27;re available &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;neovim_config&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If I didn&#x27;t cover something in this post that you&#x27;d like to know more about, let me know and I can update it or maybe do a follow-up post.
Likewise, if you know of a better or different way of doing something than the one I suggested in this post, I&#x27;d love to hear about it.
The best way to get in touch is either on the &lt;a href=&quot;https:&#x2F;&#x2F;fedi.petejon.es&#x2F;@pete&quot;&gt;Fediverse&lt;&#x2F;a&gt; or via &lt;a href=&quot;mailto:pete@petejon.es&quot;&gt;email&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;useful-links-and-resources&quot;&gt;Useful links and resources&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s some useful resources and further reading that should help if you&#x27;re interested in embarking on your own Neovim journey:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Vim creator Bram Moolenaar&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.moolenaar.net&#x2F;habits.html&quot;&gt;&quot;Seven habits of effective text editing&quot;&lt;&#x2F;a&gt; is a common entry point for the vim approach to text editing, as is &lt;a href=&quot;http:&#x2F;&#x2F;www.viemu.com&#x2F;a-why-vi-vim.html&quot;&gt;&quot;Why, oh WHY, do those #?@! nutheads use vi?&quot;&lt;&#x2F;a&gt; by Jon Beltran de Heredia.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yannesposito.com&#x2F;Scratch&#x2F;en&#x2F;blog&#x2F;Learn-Vim-Progressively&#x2F;&quot;&gt;&quot;Learn Vim Progressively&quot;&lt;&#x2F;a&gt; by Yann Esposito offers a useful perspective on building up to being comfortable in vim.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;m8C0Cq9Uv9o?si=sdJfWClsGmHxgqFP&quot;&gt;&quot;The Only Video You Need to Get Started with Neovim&quot;&lt;&#x2F;a&gt; by Neovim contributor TJ DeVries serves as a great introduction to the &lt;code&gt;kickstart&lt;&#x2F;code&gt; approach to learning the ropes.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=87AXw9Quy9U&amp;amp;list=PLx2ksyallYzW4WNYHD9xOFrPRYGlntAft&quot;&gt;&quot;Understanding Neovim&quot;&lt;&#x2F;a&gt; series by Vhyrro on YouTube is the best entry-level series I&#x27;ve found for learning how Neovim works; I think it&#x27;s a fantastic resource when learning to customise and configure your setup.&lt;&#x2F;li&gt;
&lt;li&gt;For Quarto specifically, Jannik Buhr&#x27;s YouTube &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=3sj7clNowlA&amp;amp;list=PLabWm-zCaD1axcMGvf7wFxJz8FZmyHSJ7&quot;&gt;video series on Quarto in Neovim&lt;&#x2F;a&gt; covers lots of ground excellently. I learned a lot from seeing Jannik&#x27;s approach to building a good Quarto experience in Neovim.&lt;&#x2F;li&gt;
&lt;li&gt;There is a long-running and actively maintained plugin called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;R-nvim&#x2F;R.nvim&quot;&gt;&lt;code&gt;R.nvim&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; which bundles lots of R-specific development features into a single package. I don&#x27;t use it as I prefer the flexibility of managing each of its bundled features separately, but for users just wanting to get up and running with an R workflow in Neovim as quickly as possible, it may be a good option.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Using project scripts to keep Quarto source and output files organised</title>
        <published>2024-10-14T14:00:00+00:00</published>
        <updated>2024-10-14T14:00:00+00:00</updated>
        
        <author>
          <name>
            
              Pete Jones
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://petejon.es/posts/2024-10-14-move-quarto-output/"/>
        <id>https://petejon.es/posts/2024-10-14-move-quarto-output/</id>
        
        <content type="html" xml:base="https://petejon.es/posts/2024-10-14-move-quarto-output/">&lt;p&gt;In this post I just want to share a quick tip for how to solve a very specific problem when working with &lt;a href=&quot;https:&#x2F;&#x2F;quarto.org&quot;&gt;Quarto&lt;&#x2F;a&gt; projects: you want to keep your notebook source (.qmd) files and your notebook output (.pdf, .html etc) files separate, and you keep your source files in a subdirectory within the project. I&#x27;ll talk a little bit about why that&#x27;s a problem, and how to leverage one of Quarto&#x27;s cool but lesser-known features to get around it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;project-based-workflows&quot;&gt;Project-based workflows&lt;&#x2F;h3&gt;
&lt;p&gt;If you&#x27;re working with computational notebooks, you&#x27;re probably also working with a project-based workflow. By this I really just mean you have a base directory for your project, you organise the files for your project in subdirectories, and you specify paths to files relative to the project base directory.&lt;&#x2F;p&gt;
&lt;p&gt;For an R user, the structure of a simple data analysis project called &lt;code&gt;my_project&lt;&#x2F;code&gt; might look something like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;my_project&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;├── data&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;│   ├── raw&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;│   │   └── raw_data.csv
&lt;&#x2F;span&gt;&lt;span&gt;│   └── processed&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;│       └── cleaned_data.csv
&lt;&#x2F;span&gt;&lt;span&gt;├── scripts&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;│   └── clean_raw_data.R
&lt;&#x2F;span&gt;&lt;span&gt;├── figs&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;│   └── fig1.png
&lt;&#x2F;span&gt;&lt;span&gt;├── .Rprofile
&lt;&#x2F;span&gt;&lt;span&gt;└── README.md
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Generally, it&#x27;s a good idea to keep different types of files used in the project in their own semantic subdirectories like this, rather than keeping them in the project base directory.&lt;&#x2F;p&gt;
&lt;p&gt;The same principle applies to projects that make use of Quarto notebooks too, and Quarto actually has built-in functionality for defining projects. &lt;a href=&quot;https:&#x2F;&#x2F;quarto.org&#x2F;docs&#x2F;projects&#x2F;quarto-projects.html&quot;&gt;Quarto projects&lt;&#x2F;a&gt; are marked by a &lt;code&gt;_quarto.yml&lt;&#x2F;code&gt; file in the project base directory, with project-level options and preferences being defined in this file.&lt;&#x2F;p&gt;
&lt;p&gt;However, if you keep your notebook source files in a subdirectory, similar to the &lt;code&gt;scripts&#x2F;&lt;&#x2F;code&gt; example above, Quarto&#x27;s default behaviour will make it a little harder to keep the notebook files organised.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;so-what-s-the-issue-with-quarto-projects-and-subdirectories&quot;&gt;So what&#x27;s the issue with Quarto projects and subdirectories?&lt;&#x2F;h3&gt;
&lt;p&gt;When you &lt;code&gt;render&lt;&#x2F;code&gt; a Quarto notebook, the rendered output file will by default be placed alongside the notebook source file. For small projects, this may not be a problem. However, as the number of notebooks and&#x2F;or output formats starts to grow, the situation can quickly become quite messy. In these situations, it&#x27;s helpful to have the rendered documents live in one folder, and the notebook source files that you edit in another folder.&lt;&#x2F;p&gt;
&lt;p&gt;This is where the problem lies for Quarto projects. Quarto allows you to &lt;a href=&quot;https:&#x2F;&#x2F;quarto.org&#x2F;docs&#x2F;reference&#x2F;projects&#x2F;options.html&quot;&gt;specify an output directory&lt;&#x2F;a&gt; in your project&#x27;s metadata, in which case it will move output to that directory after rendering. However, it always considers any project subdirectories containing the notebook source file as part of the notebook&#x27;s file name, so it will reproduce the subdirectory structure &lt;em&gt;inside the output directory&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s illustrate what I mean by this with an example. If you want your rendered notebooks to live in the &lt;code&gt;quarto_output&#x2F;&lt;&#x2F;code&gt; folder, you can specify &lt;code&gt;output-dir: quarto_output&lt;&#x2F;code&gt; in the &lt;code&gt;_quarto.yml&lt;&#x2F;code&gt; file. If you put your notebook &lt;code&gt;my_notebook.qmd&lt;&#x2F;code&gt; in the project base directory and &lt;code&gt;render&lt;&#x2F;code&gt; it to, say, a PDF document using Quarto, Quarto will place &lt;code&gt;my_notebook.pdf&lt;&#x2F;code&gt; in &lt;code&gt;quarto_output&#x2F;&lt;&#x2F;code&gt;, which is great.&lt;&#x2F;p&gt;
&lt;p&gt;However, if your source file is in &lt;code&gt;scripts&#x2F;my_notebook.qmd&lt;&#x2F;code&gt;, Quarto will place the rendered notebook in &lt;code&gt;quarto_output&#x2F;scripts&#x2F;my_notebook.pdf&lt;&#x2F;code&gt;, which is less great, and probably isn&#x27;t what most people meant when they specified &lt;code&gt;output-dir: quarto_output&lt;&#x2F;code&gt;. It is, however, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;quarto-dev&#x2F;quarto-cli&#x2F;issues&#x2F;1691&quot;&gt;the intended behaviour&lt;&#x2F;a&gt;, and the Quarto devs have not indicated any intention to make the &lt;code&gt;output-dir&lt;&#x2F;code&gt; option behave more like the user is likely to expect.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-solve-the-problem&quot;&gt;How to solve the problem&lt;&#x2F;h2&gt;
&lt;p&gt;Hopefully, Quarto will eventually add a feature that provides a smoother way of keeping output and source files for notebooks separate in projects using a subdirectory for the notebook source. Until then, we can make use of Quarto&#x27;s project script capabilities to take care of this.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;project-scripts&quot;&gt;Project scripts&lt;&#x2F;h3&gt;
&lt;p&gt;As part of the rendering pipeline, Quarto allows users to specify &lt;a href=&quot;https:&#x2F;&#x2F;quarto.org&#x2F;docs&#x2F;projects&#x2F;scripts.html#pre-and-post-render&quot;&gt;pre- and post-render scripts&lt;&#x2F;a&gt;, which can integrate additional tasks into the process.&lt;&#x2F;p&gt;
&lt;p&gt;There are lots of possible uses for these scripts, and one particularly helpful one for our purposes is automatically organising your project files after each render. To do this, all we need to do is create a script called, say, &lt;code&gt;_move_quarto_output.R&lt;&#x2F;code&gt; that moves rendered notebooks from the source folder to a separate output folder. Then we just make sure that script is located in the project base directory and point &lt;code&gt;post-render&lt;&#x2F;code&gt; to it in the project&#x27;s &lt;code&gt;_quarto.yml&lt;&#x2F;code&gt; metadata:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#59c2ff;&quot;&gt;project&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#59c2ff;&quot;&gt;post-render&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;_move_quarto_output.R
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The script will be called each time &lt;code&gt;quarto render&lt;&#x2F;code&gt; is run, at the end of &lt;a href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;&quot;&gt;pandoc&lt;&#x2F;a&gt;&#x27;s rendering of the notebook to the specified output format.&lt;&#x2F;p&gt;
&lt;p&gt;Note that pre- and post-render scripts in Quarto projects can be written in any language that Quarto can interpret, or can just be shell commands, giving you a tonne of flexibility.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-my-post-render-script-looks&quot;&gt;How my post-render script looks&lt;&#x2F;h3&gt;
&lt;p&gt;Here is the rather clunky script I use in my Quarto projects, which makes the following assumptions based on my own typical workflow (each of these assumptions can be relaxed by modifying the script):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;notebook source files are stored in the project subdirectory &lt;code&gt;scripts_and_notebooks&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;we want to move the rendered notebooks to a project subdirectory &lt;code&gt;quarto_output&#x2F;&lt;&#x2F;code&gt;, and we don&#x27;t want to nest rendered notebooks in further subdirectories of &lt;code&gt;quarto_output&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;all rendered notebooks are HTML files.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Give quarto&#x2F;pandoc time to ensure the creation of .html files is finished
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;Sys.sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Create `quarto_output` if it doesn&amp;#39;t exist
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dir.exists&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;quarto_output&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dir.create&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;quarto_output&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Grab the full file paths, allowing for a couple levels of directory nesting
&lt;&#x2F;span&gt;&lt;span&gt;old_html_files &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;Sys.glob&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;scripts_and_notebooks&#x2F;*.html&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;Sys.glob&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;scripts_and_notebooks&#x2F;*&#x2F;*.html&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;Sys.glob&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;scripts_and_notebooks&#x2F;*&#x2F;*&#x2F;*.html&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(old_html_files) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Convert the old file paths to where we want them to go, 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;#   collapsing nested directories into the new file name
&lt;&#x2F;span&gt;&lt;span&gt;  new_html_files &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; old_html_files &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;|&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    stringr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;str_replace_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;scripts_and_notebooks&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;quarto_output&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;|&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    stringr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;str_replace_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;(quarto_output&#x2F;.*)(&#x2F;)(.*)&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#95e6cb;&quot;&gt;\\&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;1_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#95e6cb;&quot;&gt;\\&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Move the files (stored in a var as file.rename returns a logical vector)
&lt;&#x2F;span&gt;&lt;span&gt;  renamed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;file.rename&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; old_html_files&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; new_html_files)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Print the outcome to the screen
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;FALSE &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%in%&lt;&#x2F;span&gt;&lt;span&gt; renamed) {
&lt;&#x2F;span&gt;&lt;span&gt;    cli&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;cli_alert_success&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;{length(renamed)} file{?s} moved successfully:&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(renamed)) {
&lt;&#x2F;span&gt;&lt;span&gt;      cli&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;cli_bullets&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        {old_html_files[i]}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;&amp;gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; cli&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;col_green&lt;&#x2F;span&gt;&lt;span&gt;({new_html_files[i]})
&lt;&#x2F;span&gt;&lt;span&gt;      ))
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  cli&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;cli_alert_danger&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Tried moving generated .html files but none were found.&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What the script does is grab the project-relative file paths of the rendered HTML files using &lt;code&gt;base::Sys.glob()&lt;&#x2F;code&gt;, and then uses &lt;code&gt;base::file.rename()&lt;&#x2F;code&gt; to modify these paths, effectively moving the files. Regular expressions are used (via &lt;a href=&quot;https:&#x2F;&#x2F;stringr.tidyverse.org&#x2F;&quot;&gt;stringr&lt;&#x2F;a&gt;) to incorporate any nested source subdirectories into the output file name (such that &lt;code&gt;source&#x2F;subdir&#x2F;notebook1.qmd&lt;&#x2F;code&gt; results in &lt;code&gt;output&#x2F;subdir_notebook1.html&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;The output from the script will be appended at the end of &lt;code&gt;quarto render&lt;&#x2F;code&gt;&#x27;s CLI output, which is why I use functions from the &lt;a href=&quot;https:&#x2F;&#x2F;cli.r-lib.org&#x2F;&quot;&gt;cli&lt;&#x2F;a&gt; package to print a summary of the operation:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2024-10-14-move-quarto-output&#x2F;img&#x2F;console_screencast.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s it! Let me know &lt;a href=&quot;https:&#x2F;&#x2F;fedi.petejon.es&#x2F;@pete&quot;&gt;@pete@fedi.petejon.es&lt;&#x2F;a&gt; if this helps or if there are even easier ways of dealing with this.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>charinet: A package for character interaction network analysis</title>
        <published>2021-09-24T10:18:00+00:00</published>
        <updated>2021-09-24T10:18:00+00:00</updated>
        
        <author>
          <name>
            
              Pete Jones
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://petejon.es/posts/2021-09-24-charinet/"/>
        <id>https://petejon.es/posts/2021-09-24-charinet/</id>
        
        <content type="html" xml:base="https://petejon.es/posts/2021-09-24-charinet/">&lt;img src=&quot;hex-logo.png&quot; align=&quot;right&quot; width=&quot;160&quot; &#x2F;&gt;
&lt;p&gt;As part of my ESRC postdoc fellowship I have been working on turning the tools I use in my research to analyse character interaction networks into an R package called &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;charinet&quot;&gt;charinet&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t go into detail here about what the package does and how it works because the project README contains a pretty extensive demo. But the main things it offers are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Functions for quickly reading in and reshaping lists of character interactions in common data structures.&lt;&#x2F;li&gt;
&lt;li&gt;A screenplay parser which will extract a relational event list from a well-formatted PDF of a screenplay.&lt;&#x2F;li&gt;
&lt;li&gt;An implementation of the dynamic narrative centrality measure proposed in our &lt;em&gt;Social Networks&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.1016&#x2F;j.socnet.2020.03.003&quot;&gt;paper&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Functions for visualising the character interaction data as heatmaps, networks and dynamic centrality trajectories.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I&#x27;ve been using the package myself for the last few months and it has really improved my workflow for the common tasks that I usually want to do when analysing character interaction data.&lt;&#x2F;p&gt;
&lt;p&gt;It also works well in conjunction with the data already available in the &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;movienetdata&quot;&gt;movienetdata&lt;&#x2F;a&gt; package.&lt;&#x2F;p&gt;
&lt;p&gt;With just a few lines of code, you can get a good sense of the character dynamics of a given narrative:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;iron_man &amp;lt;- movienetdata::mcu01_ironman
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# Plot as a network:
&lt;&#x2F;span&gt;&lt;span&gt;plot_charinet(adjacency = iron_man$adjacency, 
&lt;&#x2F;span&gt;&lt;span&gt;              char_names = iron_man$node_list$char_name, 
&lt;&#x2F;span&gt;&lt;span&gt;              degree = iron_man$node_list$nlines, 
&lt;&#x2F;span&gt;&lt;span&gt;              node_fill = ifelse(iron_man$node_list$char_female, 
&lt;&#x2F;span&gt;&lt;span&gt;                                 &amp;quot;#ded649&amp;quot;, &amp;quot;#55467a&amp;quot;), 
&lt;&#x2F;span&gt;&lt;span&gt;              parallel_edges = TRUE, 
&lt;&#x2F;span&gt;&lt;span&gt;              title = &amp;quot;Dialogue in Iron Man (2008)&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# Plot as a character activity heatmap:
&lt;&#x2F;span&gt;&lt;span&gt;iron_man$event_list %&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;    activity_heatmap(char_names = iron_man$node_list$char_name, 
&lt;&#x2F;span&gt;&lt;span&gt;                     story_chunk_col = 2, 
&lt;&#x2F;span&gt;&lt;span&gt;                     from = 3) %&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;    plot_heatmap(title = &amp;quot;Activity heatmap for Iron Man by scene&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# Plot dynamic centrality scores:
&lt;&#x2F;span&gt;&lt;span&gt;iron_man$event_list %&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;    narrative_centrality(char_names = iron_man$node_list$char_name,
&lt;&#x2F;span&gt;&lt;span&gt;                         mode = &amp;quot;out&amp;quot;, 
&lt;&#x2F;span&gt;&lt;span&gt;                         wp = 0.01,
&lt;&#x2F;span&gt;&lt;span&gt;                         normalised = TRUE, 
&lt;&#x2F;span&gt;&lt;span&gt;                         from = 3) %&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;    plot_nc(title = &amp;quot;Speaking centrality scores for characters in Iron Man (2008)&amp;quot;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;d love for people to try it out and let me know if it works for them and if there&#x27;s anything else they&#x27;d like a package like this to do. I&#x27;ve tried to document everything clearly in the package, but do let me know if any of the functions or arguments aren&#x27;t clear.&lt;&#x2F;p&gt;
 &lt;!----&gt;


&lt;div
  class=&quot;my-4 flex flex-col rounded-lg bg-[var(--admonition-bg)]&quot;
  style=&quot;--admonition-bg: rgba(83, 211, 230, 0.1)&quot;
&gt;
  &lt;div class=&quot;flex items-center rounded-t-lg bg-[var(--admonition-bg)] p-1&quot;&gt;
    &lt;div
      class=&quot;mx-2 h-4 w-4 text-[0] [background:var(--url)_center_center_no-repeat] dark:invert&quot;
      style=&quot;--url: url(.&#x2F;icons&#x2F;info.svg)&quot;
    &gt;
      info
    &lt;&#x2F;div&gt;
    &lt;span&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;pl-4&quot;&gt;&lt;p&gt;This post was edited to update the various references to the package source repository, which is now hosted on &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&quot;&gt;Codeberg&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Implementing narrative centrality for character interaction networks: a practical walkthrough</title>
        <published>2020-04-30T12:05:15+01:00</published>
        <updated>2020-04-30T12:05:15+01:00</updated>
        
        <author>
          <name>
            
              Pete Jones
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://petejon.es/posts/2020-04-30-narrative-centrality/"/>
        <id>https://petejon.es/posts/2020-04-30-narrative-centrality/</id>
        
        <content type="html" xml:base="https://petejon.es/posts/2020-04-30-narrative-centrality/"> &lt;!----&gt;


&lt;div
  class=&quot;my-4 flex flex-col rounded-lg bg-[var(--admonition-bg)]&quot;
  style=&quot;--admonition-bg: rgba(255, 145, 0, 0.1)&quot;
&gt;
  &lt;div class=&quot;flex items-center rounded-t-lg bg-[var(--admonition-bg)] p-1&quot;&gt;
    &lt;div
      class=&quot;mx-2 h-4 w-4 text-[0] [background:var(--url)_center_center_no-repeat] dark:invert&quot;
      style=&quot;--url: url(.&#x2F;icons&#x2F;warning.svg)&quot;
    &gt;
      warning
    &lt;&#x2F;div&gt;
    &lt;span&gt;&lt;strong&gt;Note from the future!&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;pl-4&quot;&gt;&lt;p&gt;I later implemented the centrality measures discussed in this post in the &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;charinet&quot;&gt;{charinet}&lt;&#x2F;a&gt; package, and &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;charinet#narrative-centrality&quot;&gt;the functions there&lt;&#x2F;a&gt; provide a better and easier to use implementation which should supercede the code in this post.&lt;&#x2F;p&gt;
&lt;p&gt;Even though this post is outdated now, I&#x27;ll leave it up because the discussion around the measures covers some slightly different ground to what&#x27;s covered in the {charinet} README.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;In this post I&#x27;ll provide a practical walkthrough to complement a paper I wrote with my co-authors Johan Koskinen and Eithne Quinn on measuring centrality in character interaction networks, which has now been published in &lt;em&gt;Social Networks&lt;&#x2F;em&gt; (read the published version &lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.1016&#x2F;j.socnet.2020.03.003&quot;&gt;here&lt;&#x2F;a&gt; or the accepted author manuscript &lt;a href=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-04-30-narrative-centrality&#x2F;Jones-Quinn-Koskinen-2020-accepted-manuscript.pdf&quot;&gt;here&lt;&#x2F;a&gt;.).&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve been presenting this work at conferences for a while now, and have received some great feedback along the way. Now that the paper is finalised and published, it seemed like a good opportunity to share the code I use to implement the measure in R and show how to use it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-paper-in-a-nutshell&quot;&gt;The paper in a nutshell&lt;&#x2F;h2&gt;
&lt;p&gt;I won&#x27;t try to recreate the paper within this post, as I&#x27;d rather stick to the practical side here and let readers learn more about the measure from the paper where it is properly explained and contextualised.&lt;&#x2F;p&gt;
&lt;p&gt;However, a very brief nutshell summary might help inform what follows. Broadly speaking, the paper reflects on the relationship between network centrality and narrative centrality. In particular, it argues that in order for a network analytic measure to tell us about a narrative text, it needs to be able to reflect the sequence of events that take place in the narrative. In other words, we need to represent the narrative as a dynamic network, and our measures ought to be designed to work on such a dynamic representation.&lt;&#x2F;p&gt;
&lt;p&gt;To this end, we propose a simple dynamic measure which allows characters&#x27; scores to increase when they either send or receive a relational event (in our case, when they either speak or are spoken to) in a way that reflects the characters with whom they interact as well as the sequence of such interactions.&lt;&#x2F;p&gt;
&lt;p&gt;This measure, which has an &quot;out&quot; version and an &quot;in&quot; version to reflect the directionality of interaction data, looks like so:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-04-30-narrative-centrality&#x2F;figs&#x2F;equations.PNG&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We argue that this approach reveals much more about the dynamics of a narrative text because it allows us to say something meaningful about the interlocking trajectories which characters take through narratives - trajectories which are often extremely difficult to summarise using a single static value.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-does-applying-the-measure-look-like-in-practice&quot;&gt;What does applying the measure look like in practice?&lt;&#x2F;h2&gt;
&lt;p&gt;The easiest way to explain how to use the measure is to work through a practical example. So, following the paper, I&#x27;ll use the measure to calculate the narrative centrality of characters in &lt;em&gt;Star Wars: The Force Awakens&lt;&#x2F;em&gt; (2015) using character interaction data I collected in my PhD research. &lt;em&gt;The Force Awakens&lt;&#x2F;em&gt; is one of 30 films available in the &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;movienetdata&quot;&gt;{movienetdata}&lt;&#x2F;a&gt; package, so it will make for an easy demonstration.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;defining-the-function&quot;&gt;Defining the function&lt;&#x2F;h4&gt;
&lt;p&gt;First, we need to define a function for calculating the centralities. The goal is to calculate a score for each character at each time point, so essentially we want an &lt;em&gt;N&lt;&#x2F;em&gt;-by-&lt;em&gt;T&lt;&#x2F;em&gt; matrix, where &lt;em&gt;N&lt;&#x2F;em&gt; is the total number of named speaking characters and &lt;em&gt;T&lt;&#x2F;em&gt; is the total number of narrative events (in my case, dialogue interactions). In fact, we want two such matrices - one for the speaking scores and one for the spoken-to scores.&lt;&#x2F;p&gt;
&lt;p&gt;I define the function in a way that allows the user to specify which matrix they want via the &lt;code&gt;mode&lt;&#x2F;code&gt; argument, which can take the values &quot;in&quot; (for the spoken-to scores), &quot;out&quot; (for the speaking scores) or &quot;both&quot;. In the case of &quot;both&quot;, which is the default option, a named list is returned containing first the &quot;out&quot; matrix and then the &quot;in&quot; matrix. For either &quot;out&quot; or &quot;in&quot;, a single matrix is returned.&lt;&#x2F;p&gt;
&lt;p&gt;The weighting parameter lambda can be specified via the argument &lt;code&gt;wp&lt;&#x2F;code&gt;, which has a &quot;sensible default&quot; of 0.01 (see the Appendix of the paper for a detailed discussion of this).&lt;&#x2F;p&gt;
&lt;p&gt;The argument &lt;code&gt;normalised&lt;&#x2F;code&gt; allows the user to specify whether to return the normalised scores (&lt;code&gt;normalised = TRUE&lt;&#x2F;code&gt;) or the absolute scores (&lt;code&gt;normalised = FALSE&lt;&#x2F;code&gt;). Normalising the scores here refers to dividing each character&#x27;s score at time &lt;em&gt;t&lt;&#x2F;em&gt; by the sum of all character scores at time &lt;em&gt;t&lt;&#x2F;em&gt;. The default value is &lt;code&gt;TRUE&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, I want the function to be flexible with regard to the structure of the event list on which it is applied. To provide a balance between this flexibility and creating some predictability regarding the input data structure, the function assumes an event list (given via the &lt;code&gt;event_list&lt;&#x2F;code&gt; argument) containing a column of speaker IDs in the first column and dummy variables for each potential receiver in column &lt;code&gt;recipient ID + 1&lt;&#x2F;code&gt;. So Character 3 will be represented by column 4, such that a value of 1 in cell &lt;code&gt;[3, 4]&lt;&#x2F;code&gt; means that Character 3 was the recipient of the line of dialogue spoken at time &lt;code&gt;t=3&lt;&#x2F;code&gt;. In some cases, the input data will contain other columns. For example, the {movienetData} event lists also contain columns &lt;code&gt;eventID&lt;&#x2F;code&gt; and &lt;code&gt;sceneID&lt;&#x2F;code&gt;. The argument &lt;code&gt;start_at&lt;&#x2F;code&gt; allows the user to skip any such columns so long as they are positioned prior to the speaker ID. Basically, the value given for this argument should be the speaker ID column. So if the speaker ID column is first in the input event list, &lt;code&gt;start_at&lt;&#x2F;code&gt; should be set at 1 (which is the default), but if the speaker ID column is column 3 in the input event list (as, for example, in the {movienetData} data), &lt;code&gt;start_at&lt;&#x2F;code&gt; should be set at 3. This will become clearer in the practical examples below.&lt;&#x2F;p&gt;
&lt;p&gt;This might seem at first like an unusual assumed structure, but I prefer this dummy-based event list format to a (perhaps more conventional) senderID-recipientID edgelist-style format because the data is characterised by sender exclusivity and receiver non-exclusivity. That is, there is only ever one sender per event, but they might be addressing multiple recipients simultaneously (as is the case, for example, with e-mail or tweet data). The event list allows this multi-recipient structure to be reflected clearly in the data - one row per event - and streamlines both the data collection process and the actual computation when using the measure. Any additional variables for each event (for example, &lt;em&gt;weight&lt;&#x2F;em&gt; or &lt;em&gt;type&lt;&#x2F;em&gt; may be relevant in other contexts) can easily be included before the speaker ID column, and &lt;code&gt;start_at&lt;&#x2F;code&gt; ensures that differences in the number or name of such variables won&#x27;t make analysis any more complicated.&lt;&#x2F;p&gt;
&lt;p&gt;An optional character vector containing the names of the characters corresponding to the node IDs can be passed in via the &lt;code&gt;chars&lt;&#x2F;code&gt; argument, and these names will be used to supply column names in the returned matrices. If these are not provided, character names will be inferred from the input event list.&lt;&#x2F;p&gt;
&lt;p&gt;All together, this looks like so (I&#x27;ve also made this available as a &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;pj398&#x2F;7b149797e2cdc665ad52a7232fd3dfb8&quot;&gt;gist&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;narrative_centrality &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;event_list&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;chars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;mode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;both&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;wp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;01&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;normalised &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;TRUE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;start_at &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  C_in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;matrix&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;nrow&lt;&#x2F;span&gt;&lt;span&gt;(event_list)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(chars))
&lt;&#x2F;span&gt;&lt;span&gt;  C_out &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;matrix&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;nrow&lt;&#x2F;span&gt;&lt;span&gt;(event_list)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(chars))
&lt;&#x2F;span&gt;&lt;span&gt;  C_in_norm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;matrix&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;nrow&lt;&#x2F;span&gt;&lt;span&gt;(event_list)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(chars))
&lt;&#x2F;span&gt;&lt;span&gt;  C_out_norm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;matrix&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;nrow&lt;&#x2F;span&gt;&lt;span&gt;(event_list)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(chars))
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;is.null&lt;&#x2F;span&gt;&lt;span&gt;(chars)) {
&lt;&#x2F;span&gt;&lt;span&gt;    chars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;colnames&lt;&#x2F;span&gt;&lt;span&gt;(event_list)[start_at &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;ncol&lt;&#x2F;span&gt;&lt;span&gt;(event_list)]
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;colnames&lt;&#x2F;span&gt;&lt;span&gt;(C_in) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; chars
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;colnames&lt;&#x2F;span&gt;&lt;span&gt;(C_in_norm) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; chars
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;colnames&lt;&#x2F;span&gt;&lt;span&gt;(C_out) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; chars
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;colnames&lt;&#x2F;span&gt;&lt;span&gt;(C_out_norm) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; chars
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Compute the scores
&lt;&#x2F;span&gt;&lt;span&gt;  C_in_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;matrix&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(chars)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  C_out_t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;matrix&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(chars)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(t &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;nrow&lt;&#x2F;span&gt;&lt;span&gt;(event_list)) {
&lt;&#x2F;span&gt;&lt;span&gt;    speaker &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; event_list[t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; start_at]
&lt;&#x2F;span&gt;&lt;span&gt;    receivers &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;which&lt;&#x2F;span&gt;&lt;span&gt;(event_list[t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;(start_at &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dim&lt;&#x2F;span&gt;&lt;span&gt;(event_list)[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    C_in_t[receivers] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; C_in_t[receivers] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span&gt;(wp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; C_in_t[speaker])
&lt;&#x2F;span&gt;&lt;span&gt;    C_out_t[speaker] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; C_out_t[speaker] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;      ((wp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(receivers)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(C_out_t[receivers]))
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(chars)) {
&lt;&#x2F;span&gt;&lt;span&gt;      C_in[t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; c] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; C_in_t[c]
&lt;&#x2F;span&gt;&lt;span&gt;      C_out[t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; c] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; C_out_t[c]
&lt;&#x2F;span&gt;&lt;span&gt;      C_in_norm[t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; c] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; C_in_t[c] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(C_in_t)
&lt;&#x2F;span&gt;&lt;span&gt;      C_out_norm[t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; c] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; C_out_t[c] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(C_out_t)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Return the requested values according to `normalised` and `mode`
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(normalised &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;TRUE&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(mode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;both&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;out_scores&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; C_out_norm&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;in_scores&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; C_in_norm))
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(mode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;in&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt;(C_in_norm)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(mode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;out&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt;(C_out_norm)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(mode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;both&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;(C_out&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; C_in))
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(mode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;in&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt;(C_in)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(mode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;out&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt;(C_out)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So to get the centralities for &lt;em&gt;The Force Awakens&lt;&#x2F;em&gt;, we need to read in the film data:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# remotes::install_git(&amp;quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;movienetdata.git&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;tfa &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; movienetdata&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;starwars_tfa
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and, just to be clear, this event list is structured like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;tfa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;event_list[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;##      eventID sceneID speakerID Lor.San.Tekka..1. Poe.Dameron..2. Kylo.Ren..3. Captain.Phasma..4.
&lt;&#x2F;span&gt;&lt;span&gt;## [1,]       1       1         1                 0               1            0                  0
&lt;&#x2F;span&gt;&lt;span&gt;## [2,]       2       1         2                 1               0            0                  0
&lt;&#x2F;span&gt;&lt;span&gt;## [3,]       3       1         1                 0               1            0                  0
&lt;&#x2F;span&gt;&lt;span&gt;## [4,]       4       1         2                 1               0            0                  0
&lt;&#x2F;span&gt;&lt;span&gt;## [5,]       5       1         2                 1               0            0                  0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;our speaker ID column is column 3, and our dummy variables for each recipient start at column 4 and occupy the remaining columns in the dataset (here I only show the first few for readability).&lt;&#x2F;p&gt;
&lt;p&gt;So now we can run the function, remembering to start at column 3:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;tfa_scores &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;narrative_centrality&lt;&#x2F;span&gt;&lt;span&gt;(tfa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;event_list&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;chars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; tfa[[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;char_name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;wp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;01&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;start_at &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On its own, the returned matrix is a little too unwieldy to offer immediate insights into what&#x27;s going on. So we can plot the scores to see the character trajectories more clearly.&lt;&#x2F;p&gt;
&lt;p&gt;First, I&#x27;ll put the data into a &lt;a href=&quot;https:&#x2F;&#x2F;r4ds.had.co.nz&#x2F;tidy-data.html&quot;&gt;tidy&lt;&#x2F;a&gt; format to make things easier. In the process, I&#x27;ll add a variable which makes sure that only those characters whose share of scores at the end of the film is greater than their share at the start of the film are labelled, which will make the graph a little more readable.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(tidyverse)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;tfa_out_tidy &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;cbind.data.frame&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Event&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;seq.int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dim&lt;&#x2F;span&gt;&lt;span&gt;(tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;out_scores)[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                 tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;out_scores) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;% 
&lt;&#x2F;span&gt;&lt;span&gt;  tidyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;pivot_longer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;cols &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= -&lt;&#x2F;span&gt;&lt;span&gt;Event&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;names_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Character&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;values_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Score&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;mutate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;Label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;ifelse&lt;&#x2F;span&gt;&lt;span&gt;(Character &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%in% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;names&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;which&lt;&#x2F;span&gt;&lt;span&gt;(tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;out_scores[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;out_scores[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dim&lt;&#x2F;span&gt;&lt;span&gt;(tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;out_scores)[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;]))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                        Character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;NA&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;tfa_in_tidy &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;cbind.data.frame&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Event&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;seq.int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dim&lt;&#x2F;span&gt;&lt;span&gt;(tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;in_scores)[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                 tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;in_scores) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;% 
&lt;&#x2F;span&gt;&lt;span&gt;  tidyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;pivot_longer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;cols &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= -&lt;&#x2F;span&gt;&lt;span&gt;Event&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;names_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Character&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;values_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Score&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;mutate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;Label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;ifelse&lt;&#x2F;span&gt;&lt;span&gt;(Character &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%in% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;names&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;which&lt;&#x2F;span&gt;&lt;span&gt;(tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;in_scores[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;in_scores[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dim&lt;&#x2F;span&gt;&lt;span&gt;(tfa_scores&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;in_scores)[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;]))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                        Character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;NA&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So the data now looks like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;tfa_out_tidy
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;## # A tibble: 21,328 x 4
&lt;&#x2F;span&gt;&lt;span&gt;##    Event Character          Score Label      
&lt;&#x2F;span&gt;&lt;span&gt;##    &amp;lt;int&amp;gt; &amp;lt;chr&amp;gt;              &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;      
&lt;&#x2F;span&gt;&lt;span&gt;##  1     1 Lor San Tekka     0.0326 &amp;lt;NA&amp;gt;       
&lt;&#x2F;span&gt;&lt;span&gt;##  2     1 Poe Dameron       0.0322 Poe Dameron
&lt;&#x2F;span&gt;&lt;span&gt;##  3     1 Kylo Ren          0.0322 Kylo Ren   
&lt;&#x2F;span&gt;&lt;span&gt;##  4     1 Captain Phasma    0.0322 &amp;lt;NA&amp;gt;       
&lt;&#x2F;span&gt;&lt;span&gt;##  5     1 Finn              0.0322 Finn       
&lt;&#x2F;span&gt;&lt;span&gt;##  6     1 Unkar             0.0322 &amp;lt;NA&amp;gt;       
&lt;&#x2F;span&gt;&lt;span&gt;##  7     1 Rey               0.0322 Rey        
&lt;&#x2F;span&gt;&lt;span&gt;##  8     1 General Hux       0.0322 &amp;lt;NA&amp;gt;       
&lt;&#x2F;span&gt;&lt;span&gt;##  9     1 Lieutenant Mitaka 0.0322 &amp;lt;NA&amp;gt;       
&lt;&#x2F;span&gt;&lt;span&gt;## 10     1 Han Solo          0.0322 Han Solo   
&lt;&#x2F;span&gt;&lt;span&gt;## # ... with 21,318 more rows
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then this can be plotted. First, the speaking scores:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(directlabels)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;tfa_out_tidy &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;ggplot&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;aes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Event&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Score&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;group &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Label)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_line&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;show.legend &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;FALSE&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;scale_x_continuous&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;expand &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;expand_scale&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;))) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_dl&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;aes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Label)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;method &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;last.bumpup&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;fontface &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;bold&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme_light&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;axis.line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_line&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;black&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.grid.major &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.grid.minor &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.border &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.background &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-04-30-narrative-centrality&#x2F;figs&#x2F;sw_out_001.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;and then the spoken-to scores:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;tfa_in_tidy &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;ggplot&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;aes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Event&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Score&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;group &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Label)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_line&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;show.legend &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;FALSE&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;scale_x_continuous&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;expand &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;expand_scale&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;))) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_dl&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;aes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Label)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;method &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;last.bumpup&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;fontface &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;bold&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme_light&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;axis.line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_line&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;black&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.grid.major &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.grid.minor &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.border &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.background &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-04-30-narrative-centrality&#x2F;figs&#x2F;sw_in_001.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here we can see the same graphs used in the paper. They illustrate many of the strengths of the measure. For example, we can see that some characters&#x27; importance is very much temporally situated - as with Poe Dameron, who is pivotal in initiating the action, but disappears after the first act to return later in the film after other characters have established themselves as the primary narrative actors. This illustrates a second desirable property of the measure: when a character stops participating (in this case vocally), their share of the &quot;character space&quot; declines, as we see with characters like Poe and Maz Kanata, who come and go, but also with Rey when she is kidnapped and becomes temporarily much more passive in the second act of the film.&lt;&#x2F;p&gt;
&lt;p&gt;To illustrate the effect of different values of the weighting parameter lambda (again, see the paper for full discussion of this), let&#x27;s recalculate and re-plot the scores with a higher lambda value of 0.05.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;tfa_scores_2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;narrative_centrality&lt;&#x2F;span&gt;&lt;span&gt;(tfa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;event_list&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;chars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; tfa[[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;char_name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;mode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;out&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;wp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;05&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;start_at &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;cbind.data.frame&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Event&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;seq.int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dim&lt;&#x2F;span&gt;&lt;span&gt;(tfa_scores_2)[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; tfa_scores_2) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;% 
&lt;&#x2F;span&gt;&lt;span&gt;  tidyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;pivot_longer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;cols &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= -&lt;&#x2F;span&gt;&lt;span&gt;Event&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;names_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Character&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;values_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Score&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;mutate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;Label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;ifelse&lt;&#x2F;span&gt;&lt;span&gt;(Character &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%in% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;names&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;which&lt;&#x2F;span&gt;&lt;span&gt;(tfa_scores_2[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; tfa_scores_2[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dim&lt;&#x2F;span&gt;&lt;span&gt;(tfa_scores_2)[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;]))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                        Character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;NA&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;ggplot&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;aes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Event&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Score&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;group &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Label)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_line&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;show.legend &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;FALSE&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;scale_x_continuous&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;expand &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;expand_scale&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;))) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_dl&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;aes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Label)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;method &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;last.bumpup&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;fontface &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;bold&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme_light&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;axis.line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_line&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;black&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.grid.major &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.grid.minor &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.border &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.background &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-04-30-narrative-centrality&#x2F;figs&#x2F;sw_out_005.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here, the number of interactions required for one character to catch up to another character is vastly reduced, rendering the measure much more sensitive to the effect of each interaction as reflected in the spiky lines. This means that characters both climb and decline more quickly, allowing characters to &quot;steal the show&quot; by becoming active late in the film (particularly if they interact with hitherto central characters), and be forgotten quickly by leaving the action early.&lt;&#x2F;p&gt;
&lt;p&gt;Personally, having experimented with running the measure on many different films, I find that the trajectories given by the measure tend to align much more closely with my mental model of a narrative when the value is lower than in the above example, as I think my understanding of the narrative is much less volatile than the spiky picture painted by scores calculated with higher lambda values. Some exploratory work will be needed to find appropriate values in different contexts and cases.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;computational-extraction-and-data-caught-in-the-wild&quot;&gt;Computational extraction and data caught in the wild&lt;&#x2F;h2&gt;
&lt;p&gt;I make the point in the paper that the principles of the measure are independent from the particular data extraction method we use to illustrate them. In other words, all the arguments are just as applicable to computationally extracted character networks, which are the most commonly pursued in the data science and digital humanities communities.&lt;&#x2F;p&gt;
&lt;p&gt;What&#x27;s important is not whether data are extracted manually or computationally, but rather that extracted data are stored in an event list format rather than going straight into a static edgelist or adjacency matrix. The edgelist and adjacency matrix can be derived from the event list later, but the event list can never be reverse-engineered from the static representations.&lt;&#x2F;p&gt;
&lt;p&gt;To illustrate this, I&#x27;ll provide a final example of the measure at work using data from the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bradlindblad&#x2F;schrute&quot;&gt;{schrute}&lt;&#x2F;a&gt; package which contains dialogue from episodes of the US version of &lt;em&gt;The Office&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# install.packages(&amp;quot;schrute&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;office_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; schrute&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;theoffice
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which is formatted like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt; office_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  dplyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(season &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  dplyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(episode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  dplyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;## # A tibble: 3 x 12
&lt;&#x2F;span&gt;&lt;span&gt;##   index season episode episode_name director writer character text 
&lt;&#x2F;span&gt;&lt;span&gt;##   &amp;lt;int&amp;gt;  &amp;lt;int&amp;gt;   &amp;lt;int&amp;gt; &amp;lt;chr&amp;gt;        &amp;lt;chr&amp;gt;    &amp;lt;chr&amp;gt;  &amp;lt;chr&amp;gt;     &amp;lt;chr&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;## 1     1      1       1 Pilot        Ken Kwa~ Ricky~ Michael   All ~
&lt;&#x2F;span&gt;&lt;span&gt;## 2     2      1       1 Pilot        Ken Kwa~ Ricky~ Jim       Oh, ~
&lt;&#x2F;span&gt;&lt;span&gt;## 3     3      1       1 Pilot        Ken Kwa~ Ricky~ Michael   So y~
&lt;&#x2F;span&gt;&lt;span&gt;## # ... with 4 more variables: text_w_direction &amp;lt;chr&amp;gt;, imdb_rating &amp;lt;dbl&amp;gt;,
&lt;&#x2F;span&gt;&lt;span&gt;## #   total_votes &amp;lt;int&amp;gt;, air_date &amp;lt;fct&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can create a character network for the first episode by first subsetting the data:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;ep_1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; office_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  dplyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(season &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt; episode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  dplyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;select&lt;&#x2F;span&gt;&lt;span&gt;(index&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; character) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# This next line just fixes a typo I found in the data for a character name
&lt;&#x2F;span&gt;&lt;span&gt;  dplyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;mutate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;character &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;str_replace&lt;&#x2F;span&gt;&lt;span&gt;(character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Michel&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Michael&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we need to transform this into an event list. As we only have the speaker and not the direct recipient of the data, how should we determine which characters are the &lt;em&gt;j&lt;&#x2F;em&gt;s to use when increasing speaker &lt;em&gt;i&lt;&#x2F;em&gt;&#x27;s score? We can approximate receipt of dialogue by assigning any other characters who spoke within some number of lines (here, I&#x27;ll use 3) either side of the speaker as a &quot;receiver&quot; of the dialogue.&lt;&#x2F;p&gt;
&lt;p&gt;This transformation looks like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;to_events &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  num_chars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character))
&lt;&#x2F;span&gt;&lt;span&gt;  
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;get_id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;char_name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;which&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span&gt; char_name)
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  
&lt;&#x2F;span&gt;&lt;span&gt;  events &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;matrix&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;nrow &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;nrow&lt;&#x2F;span&gt;&lt;span&gt;(data)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;ncol &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; num_chars)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;colnames&lt;&#x2F;span&gt;&lt;span&gt;(events) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;eventID&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;speakerID&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character))
&lt;&#x2F;span&gt;&lt;span&gt;  
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;nrow&lt;&#x2F;span&gt;&lt;span&gt;(data)) {
&lt;&#x2F;span&gt;&lt;span&gt;    events[x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; x
&lt;&#x2F;span&gt;&lt;span&gt;    events[x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;get_id&lt;&#x2F;span&gt;&lt;span&gt;(data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character[x])
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt;(c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character)) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%in%&lt;&#x2F;span&gt;&lt;span&gt; data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;max&lt;&#x2F;span&gt;&lt;span&gt;(x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;min&lt;&#x2F;span&gt;&lt;span&gt;(x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;nrow&lt;&#x2F;span&gt;&lt;span&gt;(data))]) {
&lt;&#x2F;span&gt;&lt;span&gt;        events[x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;get_id&lt;&#x2F;span&gt;&lt;span&gt;(c)] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;        events[x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; events[x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# No self-ties!
&lt;&#x2F;span&gt;&lt;span&gt;      }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt;(events)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which produces a familiar data structure:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;ep_1_events &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;to_events&lt;&#x2F;span&gt;&lt;span&gt;(ep_1)
&lt;&#x2F;span&gt;&lt;span&gt;ep_1_events[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;##      eventID speakerID Michael Jim Pam Dwight Jan
&lt;&#x2F;span&gt;&lt;span&gt;## [1,]       1         1       0   1   0      0   0
&lt;&#x2F;span&gt;&lt;span&gt;## [2,]       2         2       1   0   0      0   0
&lt;&#x2F;span&gt;&lt;span&gt;## [3,]       3         1       0   1   0      0   0
&lt;&#x2F;span&gt;&lt;span&gt;## [4,]       4         2       1   0   0      0   0
&lt;&#x2F;span&gt;&lt;span&gt;## [5,]       5         1       0   1   1      0   0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can run the centrality measure on this (we only need the &quot;out&quot; scores because there is no true recipiency in this data):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;office_scores &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;narrative_centrality&lt;&#x2F;span&gt;&lt;span&gt;(ep_1_events&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;chars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(ep_1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;mode &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;out&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;start_at &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;cbind.data.frame&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Event&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;seq.int&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dim&lt;&#x2F;span&gt;&lt;span&gt;(office_scores)[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; office_scores) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;% 
&lt;&#x2F;span&gt;&lt;span&gt;  tidyr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;pivot_longer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;cols &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= -&lt;&#x2F;span&gt;&lt;span&gt;Event&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;names_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Character&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;values_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Score&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;mutate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;Label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;ifelse&lt;&#x2F;span&gt;&lt;span&gt;(Character &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%in% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;names&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;which&lt;&#x2F;span&gt;&lt;span&gt;(office_scores[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; office_scores[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;dim&lt;&#x2F;span&gt;&lt;span&gt;(office_scores)[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;]))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                        Character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;NA&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;ggplot&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;aes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Event&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Score&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;group &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Character&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Label)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_line&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;show.legend &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;FALSE&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;scale_x_continuous&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;expand &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;expand_scale&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;))) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_dl&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;aes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Label)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;method &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;last.bumpup&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;fontface &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;bold&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme_light&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;axis.line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_line&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;black&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.grid.major &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.grid.minor &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.border &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;panel.background &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_blank&lt;&#x2F;span&gt;&lt;span&gt;())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-04-30-narrative-centrality&#x2F;figs&#x2F;office_out_001.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And, to illustrate my point about deriving the static representations later, here is the sociogram for the episode after aggregating into an adjacency matrix:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(igraph)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(ggraph)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(graphlayouts)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;office_adj &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;matrix&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;nrow &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(ep_1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;ncol &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(ep_1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character)))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(ep_1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character))) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(j &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(ep_1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character))) {
&lt;&#x2F;span&gt;&lt;span&gt;    office_adj[i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; j] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;which&lt;&#x2F;span&gt;&lt;span&gt;(ep_1_events[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;amp; 
&lt;&#x2F;span&gt;&lt;span&gt;                                      ep_1_events[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; j &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;g &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;graph_from_adjacency_matrix&lt;&#x2F;span&gt;&lt;span&gt;(office_adj&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;weighted &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;TRUE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;diag &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;FALSE&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(ep_1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character))) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;V&lt;&#x2F;span&gt;&lt;span&gt;(g)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;nlines[x] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;which&lt;&#x2F;span&gt;&lt;span&gt;(ep_1_events[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span&gt; x))
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;V&lt;&#x2F;span&gt;&lt;span&gt;(g)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(ep_1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;character)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;V&lt;&#x2F;span&gt;&lt;span&gt;(g)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; scales&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;rescale&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;V&lt;&#x2F;span&gt;&lt;span&gt;(g)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;nlines&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;to&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;14&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;g &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;ggraph&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;layout &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;stress&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_edge_link&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;aes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;alpha &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; weight&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;start_cap &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;circle&lt;&#x2F;span&gt;&lt;span&gt;(node1.size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;unit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;pt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;end_cap &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;circle&lt;&#x2F;span&gt;&lt;span&gt;(node2.size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;unit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;pt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;arrow &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;arrow&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;angle &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;length &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;unit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;inches&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;ends &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;last&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;closed&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;#e86682&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_node_point&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;V&lt;&#x2F;span&gt;&lt;span&gt;(g)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;shape &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;stroke &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;fill &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;#eb4034&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;colour &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;black&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geom_node_text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;V&lt;&#x2F;span&gt;&lt;span&gt;(g)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;repel &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;TRUE&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;scale_edge_alpha_continuous&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;range &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;labs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;title &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;paste0&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Dialogue ties in The Office S01E01&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme_graph&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;legend.position &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;none&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;plot.title &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;element_text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;hjust &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-04-30-narrative-centrality&#x2F;figs&#x2F;office_net.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;&#x2F;h2&gt;
&lt;p&gt;Hopefully this walkthrough helps make the measure less abstract and more accessible&#x2F;user-friendly, but if I can clarify anything further, do get in touch and I&#x27;ll do my best to help.&lt;&#x2F;p&gt;
&lt;p&gt;As a final note, the measure is intended as a simple starting point on which further dynamic measures can be built. Some assumptions can be relaxed if this makes sense in other applications and contexts (for example, network actors don&#x27;t have to start with identical scores if we have prior information). Additional terms can be added where this makes sense (for example, allowing characters&#x27; scores to increase when they are not directly involved in an interaction but are the subject of an interaction, such as when A talks to B &lt;em&gt;about&lt;&#x2F;em&gt; C).&lt;&#x2F;p&gt;
&lt;p&gt;I will be exploring some of these different options myself, and I hope others will too.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Making glitch art in R</title>
        <published>2020-03-09T23:24:18+00:00</published>
        <updated>2020-03-09T23:24:18+00:00</updated>
        
        <author>
          <name>
            
              Pete Jones
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://petejon.es/posts/2020-03-09-glitch-art-in-r/"/>
        <id>https://petejon.es/posts/2020-03-09-glitch-art-in-r/</id>
        
        <content type="html" xml:base="https://petejon.es/posts/2020-03-09-glitch-art-in-r/">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;ilona_crop.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In this post I&#x27;m going to talk about &lt;a href=&quot;http:&#x2F;&#x2F;jameshconnolly.com&#x2F;glitchtalk.html&quot;&gt;glitch art&lt;&#x2F;a&gt; and how to make it entirely in R using databending.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-glitch-art&quot;&gt;What is glitch art?&lt;&#x2F;h2&gt;
&lt;p&gt;This is actually a difficult question to answer, as glitch art can mean many different things to different people (I&#x27;ll provide some &lt;a href=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;#further_reading&quot;&gt;further reading&lt;&#x2F;a&gt; links at the end of this post for those who want to dig deeper). In the sense I&#x27;m using it, glitch art &quot;is visual art that involves or is caused by digital glitches or errors&quot;, to use &lt;a href=&quot;http:&#x2F;&#x2F;blog.animalswithinanimals.com&#x2F;2008&#x2F;08&#x2F;databending-and-glitch-art-primer-part.html&quot;&gt;stAllio&#x27;s terms&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The errors that produce the glitch art can be a genuine malfunction on the part of the machine, such as when a digital camera incorrectly writes a photo file and artefacts are found in the resulting image. &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Databending&quot;&gt;Databending&lt;&#x2F;a&gt;, on the other hand, is the deliberate misuse of digital information for artistic or aesthetic purposes, and it&#x27;s this method of producing glitch art that I&#x27;m talking about in this post. Databending does not only apply to images and can involve the manipulation of any type of file, but in this post I&#x27;m going to stick to databending image files^[More specifically, I&#x27;m going to stick to JPEGs. File type does matter with databending, as &lt;a href=&quot;http:&#x2F;&#x2F;creative.colorado.edu&#x2F;~keho2869&#x2F;glitch&#x2F;Vernacular-of-File-Formats.pdf&quot;&gt;this guide&lt;&#x2F;a&gt; illustrates beautifully. I stuck to JPEG here because this post is long enough as it is, and I particularly like the telltale horizontal effects of databending JPEGs. Experimenting with other formats is on my to-do list of next steps in this project.].&lt;&#x2F;p&gt;
&lt;p&gt;One of the simplest methods of databending an image is to trick a software programme that is not designed for image files into opening an image file. Like all digital files, images are made up of underlying bytes of information, and this raw data can be expressed and represented in different ways. Opening an image file in a text editor, for example, allows us to see and edit a text-based representation of the file&#x27;s binary data. For illustration, here is a screensnip of a photo opened in &lt;a href=&quot;https:&#x2F;&#x2F;notepad-plus-plus.org&#x2F;&quot;&gt;Notepad++&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;notepadpp.PNG&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Making even small changes to this data (adding, deleting, moving, duplicating sections) can produce some really interesting results. One of the ways I used to entertain myself during class when I was a masters student was to databend images using the software installed on the university PCs. That&#x27;s why, if you&#x27;ve ever seen my work desktop, you&#x27;ll notice that my desktop background is the following image:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;koala_glitched.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is actually a glitched version of the following photo, which is one of the photos bundled with Windows 7 in the &quot;Sample Pictures&quot; folder:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;koala_orig.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;databending-in-r&quot;&gt;Databending in R&lt;&#x2F;h2&gt;
&lt;p&gt;So far, so good - as you can see, the process of generating glitch art can be as easy as opening an image in a text editor, making a couple of changes and hitting save (note that if you&#x27;re going to try this, do it on a copy of the image as the data corruption is typically irreverisble).&lt;&#x2F;p&gt;
&lt;p&gt;In fact, making glitch art is now even easier than this, as there are a bunch of tools available (including mobile apps) that allow you to glitch images in all kinds of deliberate and controlled ways.  Personally, I find these more controlled and interactive approaches to glitching less fun than the indeterminacy of applying chance operations to the data and seeing a unique result, like when you&#x27;re making random edits in a text editor.&lt;&#x2F;p&gt;
&lt;p&gt;However, the text editor approach involves a lot of popping in and out of different image and text manipulation softwares and browsers, so I decided to set myself the challenge of streamlining this process so that it can be done entirely within R. As far as I can tell from searching on Google and CRAN, nobody has done this in R before, so I decided to just make it up as I go along.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;defining-a-glitch-method&quot;&gt;Defining a glitch method&lt;&#x2F;h2&gt;
 &lt;!----&gt;


&lt;div
  class=&quot;my-4 flex flex-col rounded-lg bg-[var(--admonition-bg)]&quot;
  style=&quot;--admonition-bg: rgba(83, 211, 230, 0.1)&quot;
&gt;
  &lt;div class=&quot;flex items-center rounded-t-lg bg-[var(--admonition-bg)] p-1&quot;&gt;
    &lt;div
      class=&quot;mx-2 h-4 w-4 text-[0] [background:var(--url)_center_center_no-repeat] dark:invert&quot;
      style=&quot;--url: url(.&#x2F;icons&#x2F;info.svg)&quot;
    &gt;
      info
    &lt;&#x2F;div&gt;
    &lt;span&gt;&lt;strong&gt;Note from the future&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;pl-4&quot;&gt;&lt;p&gt;Some time after making this post, I put together a toy package called &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;glitchr&quot;&gt;{glitchr}&lt;&#x2F;a&gt;, which provides a simple R interface to the various functions discussed in this post.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h4 id=&quot;step-1-find-a-guinea-pig&quot;&gt;Step 1: find a guinea pig&lt;&#x2F;h4&gt;
&lt;p&gt;Or, more specifically, a bear. I needed an image to experiment on, so I went to &lt;a href=&quot;https:&#x2F;&#x2F;unsplash.com&quot;&gt;Unsplash&lt;&#x2F;a&gt; and found &lt;a href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;y421kXlUOQk&quot;&gt;this magnificient bear&lt;&#x2F;a&gt; to participate in my trials:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;bear.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-2-represent-the-file-as-raw-data&quot;&gt;Step 2: represent the file as raw data&lt;&#x2F;h4&gt;
&lt;p&gt;The next step was to find a way of bringing this bear into R as raw data that I can mess with. The &lt;a href=&quot;https:&#x2F;&#x2F;readr.tidyverse.org&#x2F;&quot;&gt;readr&lt;&#x2F;a&gt; package provides a handy function &lt;code&gt;readr::read_file_raw()&lt;&#x2F;code&gt; to do this, but first I wanted to reduce the file size. As I was aiming to do this whole thing in R, I needed a way of handling images in R. There are plenty of tools for doing this, but I decided to take this opportunity to try out &lt;a href=&quot;https:&#x2F;&#x2F;cran.r-project.org&#x2F;web&#x2F;packages&#x2F;magick&#x2F;index.html&quot;&gt;magick&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Using magick, I reduced the file size to 40% of the original:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;R&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-R &quot;&gt;&lt;code class=&quot;language-R&quot; data-lang=&quot;R&quot;&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(magick)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(magrittr)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;magick&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;image_read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;data&#x2F;raw&#x2F;bear.jpg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  magick&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;image_scale&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;geometry &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= 
&lt;&#x2F;span&gt;&lt;span&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geometry_size_percent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;width &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;height &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;  magick&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;image_write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;data&#x2F;bear_sml.jpg&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;jpg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and then read in this smaller image file:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(readr)
&lt;&#x2F;span&gt;&lt;span&gt;raw_image &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; readr&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;read_file_raw&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;data&#x2F;bear_sml.jpg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This produces an object of class &lt;code&gt;raw&lt;&#x2F;code&gt; and length 291520.&lt;&#x2F;p&gt;
&lt;p&gt;The data looks like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;raw_image[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#0f1419;color:#bfbab0;&quot;&gt;&lt;code&gt;&lt;span&gt;##   [1] ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48 00 48 00 00 ff e2 02 1c 49
&lt;&#x2F;span&gt;&lt;span&gt;##  [26] 43 43 5f 50 52 4f 46 49 4c 45 00 01 01 00 00 02 0c 6c 63 6d 73 02 10 00 00
&lt;&#x2F;span&gt;&lt;span&gt;##  [51] 6d 6e 74 72 52 47 42 20 58 59 5a 20 07 dc 00 01 00 19 00 03 00 29 00 39 61
&lt;&#x2F;span&gt;&lt;span&gt;##  [76] 63 73 70 41 50 50 4c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This we can wreck!&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-3-write-a-glitch-function&quot;&gt;Step 3: write a glitch function&lt;&#x2F;h4&gt;
&lt;p&gt;There are obviously lots of ways in which we could mess with this data, but I wanted to harness the power of &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;An_Anthology_of_Chance_Operations&quot;&gt;chance operations&lt;&#x2F;a&gt;. Here&#x27;s how I decided to go about it:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Randomly select &lt;em&gt;N&lt;&#x2F;em&gt; change points in the raw vector.&lt;&#x2F;li&gt;
&lt;li&gt;For each of these change points, randomly make a change &lt;em&gt;M&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Where &lt;em&gt;M&lt;&#x2F;em&gt; can be one of the following operations, with equal probability:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;add&lt;&#x2F;code&gt;: take all unique values of the raw vector, randomly sample a number of them, and then insert these in at the change point.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;move&lt;&#x2F;code&gt;: take a chunk of elements starting at the change point, delete them, and then reinsert them at a random point in the raw vector.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;clone&lt;&#x2F;code&gt;: as with &lt;code&gt;move&lt;&#x2F;code&gt;, but don&#x27;t delete the chunk, simply copy it to another location.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;delete&lt;&#x2F;code&gt;: take a chunk of elements starting at the change point and delete them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;One thing to note about databending images is that it is important not to make changes to the data near the start of the file, as this is the file header and corrupting it can destroy the image altogether. So I limit the possible change points that can be chosen to anything after the first 0.5% of the elements and before the final 5% of the elements (to avoid subscript-out-of-bounds type errors).&lt;&#x2F;p&gt;
&lt;p&gt;This all looks like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_it &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;input_data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_changes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;noise &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Generate a safe copy of the raw file
&lt;&#x2F;span&gt;&lt;span&gt;  glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; input_data
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Sample to find the change points (indices for the raw vector)
&lt;&#x2F;span&gt;&lt;span&gt;  change_points &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;runif&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; n_changes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;min &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;as.integer&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(input_data) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;max &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(input_data) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;- 
&lt;&#x2F;span&gt;&lt;span&gt;                           ((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(input_data) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Now iterate over these change points
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; change_points) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Then, decide what to do at each change point
&lt;&#x2F;span&gt;&lt;span&gt;    how_to_mess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;add&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;move&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;clone&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;delete&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# And mess with it in that way
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(how_to_mess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;add&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(glitched&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(input_data)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                                          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;noise&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;TRUE&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i)
&lt;&#x2F;span&gt;&lt;span&gt;    } 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(how_to_mess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;move&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      move_seed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;noise&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;      move_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; glitched[i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; move_seed)]
&lt;&#x2F;span&gt;&lt;span&gt;      glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; glitched[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;(i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; move_seed))]
&lt;&#x2F;span&gt;&lt;span&gt;      safe_range &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(glitched) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(glitched) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(glitched) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;      glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(glitched&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; move_data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;after &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(safe_range&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;    }  
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(how_to_mess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;clone&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      move_seed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;noise&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;      move_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; glitched[i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; move_seed)]
&lt;&#x2F;span&gt;&lt;span&gt;      safe_range &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(glitched) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(glitched) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(glitched) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;      glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(glitched&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; move_data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;after &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(safe_range&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(how_to_mess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;delete&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      move_seed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;noise&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;      move_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; glitched[i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; move_seed)]
&lt;&#x2F;span&gt;&lt;span&gt;      glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; glitched[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;(i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; move_seed))]
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Output the glitched data
&lt;&#x2F;span&gt;&lt;span&gt;  glitched
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The number of change points to identify can be passed in as an argument, and the &lt;code&gt;noise&lt;&#x2F;code&gt; argument sets the ceiling of how big the chunks that are selected when making changes can be.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-4-glitch-it&quot;&gt;Step 4: glitch it&lt;&#x2F;h4&gt;
&lt;p&gt;Now we&#x27;re ready to glitch our guinea pig. Let&#x27;s make 10 changes, and set the noise to 20:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;my_glitch &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_it&lt;&#x2F;span&gt;&lt;span&gt;(raw_image&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_changes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;noise &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;step-5-look-at-the-results&quot;&gt;Step 5: look at the results&lt;&#x2F;h4&gt;
&lt;p&gt;Now we want to take a look at what we&#x27;ve just created without leaving R.&lt;&#x2F;p&gt;
&lt;p&gt;We can use magick to do this, as magick can read raw data, and will print this image to the RStudio Viewer pane:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;plot_glitch &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;glitch&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  magick&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;image_read&lt;&#x2F;span&gt;&lt;span&gt;(glitch) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;% 
&lt;&#x2F;span&gt;&lt;span&gt;    magick&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;image_scale&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geometry_size_pixels&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;width &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;550&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;% 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;plot_glitch&lt;&#x2F;span&gt;&lt;span&gt;(my_glitch)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;bear_glitched_10_20.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Great - it works! How about if we tweak the parameters a little:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;my_glitch &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_it&lt;&#x2F;span&gt;&lt;span&gt;(raw_image&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_change &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;noise &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;plot_glitch&lt;&#x2F;span&gt;&lt;span&gt;(my_glitch)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;bear_glitched_50_50_3.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Again, this looks pretty good.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-6-celebrate-or-not&quot;&gt;Step 6: celebrate (or not...)&lt;&#x2F;h4&gt;
&lt;p&gt;Actually, running the &lt;code&gt;glitch_it()&lt;&#x2F;code&gt; function a few times reveals a problem with this method: the resulting images often corrupt in a way which destroys whole sections of the image with grey blocks:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;bear_10_20_greyblock_1.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-7-try-a-hacky-fix&quot;&gt;Step 7: try a hacky fix&lt;&#x2F;h4&gt;
&lt;p&gt;Presumably, this corruption is something to do with the glitched vector being a different length to the original vector - something critical ends up not being where it&#x27;s supposed to be. Since I already protected the header area from corruption, I tried to solve the problem by adding some code to the function just before outputting the vector which makes sure that the glitched vector is the same length as the original vector (by either randomly cutting or inserting data into the middle to correct the length).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Make sure the glitched data ends up the same length as the input data
&lt;&#x2F;span&gt;&lt;span&gt;  size_diff &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(glitched) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(input_data)
&lt;&#x2F;span&gt;&lt;span&gt;  corr_min &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;as.integer&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(raw_image) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  corr_max &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(glitched) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(input_data) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(size_diff &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) { &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Delete stuff if output longer than input
&lt;&#x2F;span&gt;&lt;span&gt;    glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; glitched[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(corr_min&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;corr_max&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; size_diff)]
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(size_diff &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) { &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Add stuff if output shorter than input
&lt;&#x2F;span&gt;&lt;span&gt;    glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(glitched&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(input_data)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;abs&lt;&#x2F;span&gt;&lt;span&gt;(size_diff)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;TRUE&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;after &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(glitched)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This successfully made sure that the vector lengths matched, but it solved nothing and I still got occasional grey blocks in my glitches.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-8-try-a-completely-different-approach&quot;&gt;Step 8: try a completely different approach&lt;&#x2F;h4&gt;
&lt;p&gt;Unsatisfied, I decided to take a different approach altogether and define a new glitch method. Instead of harnessing the power of chance operations, I decided to harness the meh of find and replace. This is far less exciting than the randomness-within-randomness chaos of the previous method, but seemed like it was worth a shot.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;meh.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The idea behind this method is simple:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Gather all the unique values in the raw vector and pick one (&lt;em&gt;F&lt;&#x2F;em&gt;) at random.&lt;&#x2F;li&gt;
&lt;li&gt;Determine the vector indices for each occurrence of &lt;em&gt;F&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Choose a replacement value &lt;em&gt;R&lt;&#x2F;em&gt; by repeating (1).&lt;&#x2F;li&gt;
&lt;li&gt;Replace all occurrences of &lt;em&gt;F&lt;&#x2F;em&gt; with &lt;em&gt;R&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Again, we&#x27;ll only make these changes after the first 0.5% of the vector in order to protect the header from corruption.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_far &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;input_data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_changes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; input_data
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;n_changes) {
&lt;&#x2F;span&gt;&lt;span&gt;    change_rows &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;grep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;pattern &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(input_data)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; input_data)
&lt;&#x2F;span&gt;&lt;span&gt;    change_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(input_data)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(safe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; change_rows) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(safe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(input_data) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        glitched[safe] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; change_to
&lt;&#x2F;span&gt;&lt;span&gt;      }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  glitched
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And give it a whirl:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;my_glitch &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_far&lt;&#x2F;span&gt;&lt;span&gt;(raw_image&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_change &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;plot_glitch&lt;&#x2F;span&gt;&lt;span&gt;(my_glitch)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;bear_far_1.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Well, there&#x27;s no grey blocks, and this is a pretty interesting result, but our bear friend seems to have got a little lost in the sauce here.&lt;&#x2F;p&gt;
&lt;p&gt;Even when making fewer changes, we still get images like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;my_glitch &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_far&lt;&#x2F;span&gt;&lt;span&gt;(raw_image&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_change &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;plot_glitch&lt;&#x2F;span&gt;&lt;span&gt;(my_glitch) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# x 10:
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;method2_buffer.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;These generate some pretty cool colour palettes, but that&#x27;s not really what I&#x27;m going for here.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-9-actually-solve-the-problem&quot;&gt;Step 9: actually solve the problem&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;code&gt;glitch_far()&lt;&#x2F;code&gt; isn&#x27;t breaking the file in the way that &lt;code&gt;glitch_it()&lt;&#x2F;code&gt; did, but it&#x27;s clearly making too many changes and our original image is getting lost. So we need to reign in the find-and-replace approach a little bit.&lt;&#x2F;p&gt;
&lt;p&gt;Modifying the approach in Step 8, I defined a more flexible version like so:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Gather all the unique values in the raw vector and pick one &lt;em&gt;F&lt;&#x2F;em&gt; at random.&lt;&#x2F;li&gt;
&lt;li&gt;Determine the vector indices for each occurrence of &lt;em&gt;F&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Choose a replacement &lt;em&gt;R&lt;&#x2F;em&gt; value by repeating (1).&lt;&#x2F;li&gt;
&lt;li&gt;Replace &lt;strong&gt;some of the&lt;&#x2F;strong&gt; occurrences of &lt;em&gt;F&lt;&#x2F;em&gt; with &lt;em&gt;R&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We can determine how many of the sampled values to actually replace with a tuning parameter, allowing us to specify a percentage of the occurences to replace:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_far2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;input_data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_changes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;tune &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  glitched &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; input_data
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;n_changes) {
&lt;&#x2F;span&gt;&lt;span&gt;    change_rows &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;grep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;pattern &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(input_data)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; input_data)
&lt;&#x2F;span&gt;&lt;span&gt;    change_samp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(change_rows&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                          (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(change_rows) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;min&lt;&#x2F;span&gt;&lt;span&gt;(tune&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;    change_to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sample&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;unique&lt;&#x2F;span&gt;&lt;span&gt;(input_data)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(safe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; change_samp) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(safe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;(input_data) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;        glitched[safe] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; change_to
&lt;&#x2F;span&gt;&lt;span&gt;      }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  glitched
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This produces nice clean results which don&#x27;t break the image and allow the original image to come through:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;my_glitch &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_far2&lt;&#x2F;span&gt;&lt;span&gt;(raw_image&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_changes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;tune &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;plot_glitch&lt;&#x2F;span&gt;&lt;span&gt;(my_glitch) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# x 10:
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;bear_far_1x8_1.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span&gt;my_glitch &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_far2&lt;&#x2F;span&gt;&lt;span&gt;(raw_image&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_changes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;tune &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;plot_glitch&lt;&#x2F;span&gt;&lt;span&gt;(my_glitch) &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# x 10:
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;petejon.es&#x2F;posts&#x2F;2020-03-09-glitch-art-in-r&#x2F;figs&#x2F;bear_far_2x5_1.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-note-on-the-gifs&quot;&gt;A note on the GIFs&lt;&#x2F;h3&gt;
&lt;p&gt;The goal of this project was to do everything without leaving R. This also applies to the GIFs I&#x27;m embedding in this post - they were created by iteratively performing 10 glitches and writing to file:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;r&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-r &quot;&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  my_glitch &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;glitch_far2&lt;&#x2F;span&gt;&lt;span&gt;(raw_image&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;n_changes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;tune &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  my_path &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;paste0&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;temp&#x2F;glitch_&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;.png&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;  my_glitch &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;image_read&lt;&#x2F;span&gt;&lt;span&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;image_scale&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;geometry_size_pixels&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;width &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;550&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;%&amp;gt;%
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;image_write&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;path &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; my_path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;png&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and then using &lt;a href=&quot;https:&#x2F;&#x2F;imagemagick.org&#x2F;&quot;&gt;ImageMagick&lt;&#x2F;a&gt;&#x27;s command line tools to create a GIF from these images by running &lt;code&gt;magick convert -delay 50 temp&#x2F;*.png img&#x2F;gif&#x2F;my_gif.gif&lt;&#x2F;code&gt; in the terminal.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;putting-the-glitcher-into-action&quot;&gt;Putting the glitcher into action&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have a working glitch function, I want to test it out with some images that are more suited to databending. The ideal images for databending are generally those that don&#x27;t have too many colours and feature a subject against a plain background. I went back to &lt;a href=&quot;https:&#x2F;&#x2F;unsplash.com&quot;&gt;Unsplash&lt;&#x2F;a&gt;, browsed, and picked the first three that caught my eye:&lt;&#x2F;p&gt;
&lt;div class=&quot;icon-container&quot;&gt;
  &lt;a href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;yQILyG_fGuE&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;figs&#x2F;building.jpg&quot; style=&quot;max-height:360px; width:auto;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;
  &lt;a href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;LWuHsMPzoss&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;figs&#x2F;ilona.jpg&quot; style=&quot;max-height:360px; width:auto;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;
  &lt;a href=&quot;https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;i0yjni9irCA&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;figs&#x2F;mike_von.jpg&quot; style=&quot;max-height:360px; width:auto;&quot; &#x2F;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Here are some of my favourite results and how I got them:&lt;&#x2F;p&gt;
&lt;img src=&quot;figs&#x2F;building_far_1x5_1.gif&quot; style=&quot;max-height:600px;max-width:100%;width:auto;&quot; &#x2F;&gt;
&lt;center&gt;`glitch_far2(raw_image, n_changes = 1, tune = 5)`&lt;&#x2F;center&gt;
&lt;img src=&quot;figs&#x2F;ilona_far_1x8_1.gif&quot; style=&quot;max-height:600px;max-width:100%;width:auto;&quot; &#x2F;&gt;
&lt;center&gt;`glitch_far2(raw_image, n_changes = 1, tune = 8)`&lt;&#x2F;center&gt;
&lt;img src=&quot;figs&#x2F;mike_far_1x6_1.gif&quot; style=&quot;max-height:600px;max-width:100%;width:auto;&quot; &#x2F;&gt;
&lt;center&gt;`glitch_far2(raw_image, n_changes = 1, tune = 6)`&lt;&#x2F;center&gt;
&lt;p&gt;Go forth and databend!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further_reading&quot;&gt;Further reading&lt;&#x2F;h2&gt;
&lt;p&gt;For an overview of glitch art, I recommend reading James H. Connelly&#x27;s fantastic &lt;a href=&quot;http:&#x2F;&#x2F;jameshconnolly.com&#x2F;glitchtalk.html&quot;&gt;talk on the subject&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For a more how-to and databending-oriented walkthrough, &lt;a href=&quot;http:&#x2F;&#x2F;blog.animalswithinanimals.com&#x2F;search&#x2F;label&#x2F;primers&quot;&gt;stAllio&#x27;s primers&lt;&#x2F;a&gt; are brilliant.&lt;&#x2F;p&gt;
&lt;p&gt;Additional resources on glitch art and databending from:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.glitchet.com&#x2F;resources&quot;&gt;Glitchet&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;danieltemkin.com&#x2F;Tutorials&#x2F;&quot;&gt;Daniel Temkin&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docpop.org&#x2F;2014&#x2F;01&#x2F;a-glitch-primer-editing-image-files-with-text-editors&#x2F;&quot;&gt;Doc Pop&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tobloef.com&#x2F;fun&#x2F;glitch-art&quot;&gt;Tobias Løfgren&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;datamoshing.com&#x2F;2016&#x2F;06&#x2F;15&#x2F;how-to-glitch-jpg-images-with-data-corruption&#x2F;&quot;&gt;Datamoshing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;critiquecollective.com&#x2F;2014&#x2F;03&#x2F;13&#x2F;tutorial-on-databending-and-glitch-art&#x2F;&quot;&gt;Paul Weiner&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;creative.colorado.edu&#x2F;~keho2869&#x2F;glitch&#x2F;Vernacular-of-File-Formats.pdf&quot;&gt;Rosa Menkman&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;static1.squarespace.com&#x2F;static&#x2F;525bec67e4b0ef380880a5bc&#x2F;t&#x2F;597ac1e9e6f2e1264339d89f&#x2F;1501217258536&#x2F;Glitching.pdf&quot;&gt;Unknown&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Finally, this was a really fun way for me to use R for something creative, and in the process I got some hands on experience using the magick package and ImageMagick to handle images within R in all kinds of ways. I was mostly interested in reading, writing, scaling and viewing the images, but there are many more cool and interesting things that magick can do, and the &lt;a href=&quot;https:&#x2F;&#x2F;cran.r-project.org&#x2F;web&#x2F;packages&#x2F;magick&#x2F;vignettes&#x2F;intro.html&quot;&gt;package vignette&lt;&#x2F;a&gt; illustrates these very nicely.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>movienetdata: A data package for character interactions in popular films</title>
        <published>2020-03-03T15:28:00+00:00</published>
        <updated>2020-03-03T15:28:00+00:00</updated>
        
        <author>
          <name>
            
              Pete Jones
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://petejon.es/posts/2020-03-03-movienetdata/"/>
        <id>https://petejon.es/posts/2020-03-03-movienetdata/</id>
        
        <content type="html" xml:base="https://petejon.es/posts/2020-03-03-movienetdata/">&lt;img src=&quot;hex-logo.png&quot; align=&quot;right&quot; width=&quot;160&quot; &#x2F;&gt;
&lt;p&gt;I recently released the data I collected during my PhD research as a &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;movienetdata&quot;&gt;data package&lt;&#x2F;a&gt; for R. The main reasons I did this are:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Sharing&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;One of the most common questions I get when chatting to people at conferences etc. is whether my data is publicly available. I assume this means that people would be interested in taking a look at the data, analysing it, playing around with it and such.&lt;&#x2F;p&gt;
&lt;p&gt;The dataset was generated &lt;a href=&quot;https:&#x2F;&#x2F;doi.org&#x2F;10.1080&#x2F;14680777.2018.1510846&quot;&gt;to answer questions&lt;&#x2F;a&gt; about the narrative marginalisation of women in popular cinema. However, there are a number of reasons why somebody might want to use it beyond this purpose:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It is an ideal dataset for exploring &lt;em&gt;character networks&lt;&#x2F;em&gt; in all their complexity - each film in the dataset comes with both an event list, which can be used for constructing dynamic network representations of the narratives, and an adjacency matrix derived from this event list, which can be used for static network representations. The event list also indexes each interaction by scene, allowing for the interaction data to be grouped into story chunks.&lt;&#x2F;li&gt;
&lt;li&gt;The dataset offers useful teaching data for illustrating basic network analysis ideas using familiar, easy to grasp examples of networks.&lt;&#x2F;li&gt;
&lt;li&gt;I&#x27;m sure there are all kinds of interesting questions about the films that the data can help to answer that I didn&#x27;t think to ask.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Making my life easier&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I plan on sharing other aspects of my character network analysis work, and releasing the data this way allows me to separate out the data from the core functionality of the various tools and functions that I work with. This is useful as it helps me to ensure that they make sense independently of the particular data with which I have been using them to work.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, I wanted some hands-on experience with R package development, and data packages offer a great way to learn the basics of package structure and documentation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-use-the-data&quot;&gt;How to use the data&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;In R&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you use R, you can install the package using any package manager that can install from git repositories:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;R&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-R &quot;&gt;&lt;code class=&quot;language-R&quot; data-lang=&quot;R&quot;&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# e.g. using {remotes}:
&lt;&#x2F;span&gt;&lt;span&gt;remotes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;install_git&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;movienetdata.git&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# or using {pak}:
&lt;&#x2F;span&gt;&lt;span&gt;pak&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;pkg_install&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;git::https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;movienetdata.git&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, load the package:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;R&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-R &quot;&gt;&lt;code class=&quot;language-R&quot; data-lang=&quot;R&quot;&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(movienetdata)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can browse the complete list of different films in the dataset using &lt;code&gt;data(package = &quot;movienetdata&quot;)&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;img src=&quot;all-films.png&quot; width=&quot;600&quot; &#x2F;&gt;
&lt;p&gt;And load a specific film into the workspace using e.g. &lt;code&gt;data(&quot;mcu01_ironman&quot;, &quot;movienetdata&quot;)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Each film is stored as a list containing three elements:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The event list. Each row contains information on a line of dialogue,
with columns corresponding to &lt;code&gt;eventID&lt;&#x2F;code&gt;, &lt;code&gt;sceneID&lt;&#x2F;code&gt;, &lt;code&gt;speakerID&lt;&#x2F;code&gt;, and
dummy variables for each recipient.&lt;&#x2F;li&gt;
&lt;li&gt;The node list. Rows correspond to named speaking characters, with
columns corresponding to variables for ID, name, total lines spoken
(&lt;code&gt;nlines&lt;&#x2F;code&gt;), total times spoken to (&lt;code&gt;linesin&lt;&#x2F;code&gt;), and gender. Note that
some films in the dataset might have additional or different variables
included.&lt;&#x2F;li&gt;
&lt;li&gt;The adjacency matrix. This is derived from the event list through
aggregation and can be useful for static purposes such as
visualising the network as a sociogram.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Access specific elements by name or by indexing the list:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;R&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-R &quot;&gt;&lt;code class=&quot;language-R&quot; data-lang=&quot;R&quot;&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Get the nodes by name
&lt;&#x2F;span&gt;&lt;span&gt;mcu01_ironman&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;node_list
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;R&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-R &quot;&gt;&lt;code class=&quot;language-R&quot; data-lang=&quot;R&quot;&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Get the nodes by indexing
&lt;&#x2F;span&gt;&lt;span&gt;mcu01_ironman[[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Example:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you just want to create a quick network diagram for the film &lt;em&gt;Black Panther&lt;&#x2F;em&gt;, you can do something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;R&quot; style=&quot;background-color:#0f1419;color:#bfbab0;&quot; class=&quot;language-R &quot;&gt;&lt;code class=&quot;language-R&quot; data-lang=&quot;R&quot;&gt;&lt;span&gt;black_panther &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; movienetdata&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;mcu18_blackpanther
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# install.packages(&amp;quot;network&amp;quot;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;library&lt;&#x2F;span&gt;&lt;span&gt;(network)
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Create network object from adjacency matrix
&lt;&#x2F;span&gt;&lt;span&gt;bp_net &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&amp;lt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffb454;&quot;&gt;network&lt;&#x2F;span&gt;&lt;span&gt;(black_panther&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;adjacency)
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#5c6773;&quot;&gt;# Plot the network
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;plot&lt;&#x2F;span&gt;&lt;span&gt;(bp_net&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;label &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; black_panther[[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;char_name&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;edge.col &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;lightpink1&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;vertex.cex &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;sqrt&lt;&#x2F;span&gt;&lt;span&gt;(black_panther[[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;nlines)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;label.pos &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;arrowhead.cex &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;vertex.col &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f07178;&quot;&gt;ifelse&lt;&#x2F;span&gt;&lt;span&gt;(black_panther[[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff7733;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt;char_female &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;#ded649&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;#55467a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#bfbab0cc;&quot;&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29718;&quot;&gt;main &lt;&#x2F;span&gt;&lt;span style=&quot;color:#f29668;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c2d94c;&quot;&gt;&amp;quot;Character interactions in Black Panther (2018)&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;img src=&quot;panther-net.png&quot; &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;Not in R&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you&#x27;re not an R user, you can still access the raw data from the &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;pjphd&#x2F;movienetdata&quot;&gt;package source repository&lt;&#x2F;a&gt;. In the &lt;code&gt;data-raw&lt;&#x2F;code&gt; folder you will find the CSV files for each film&#x27;s event list and node list.&lt;&#x2F;p&gt;
 &lt;!----&gt;


&lt;div
  class=&quot;my-4 flex flex-col rounded-lg bg-[var(--admonition-bg)]&quot;
  style=&quot;--admonition-bg: rgba(83, 211, 230, 0.1)&quot;
&gt;
  &lt;div class=&quot;flex items-center rounded-t-lg bg-[var(--admonition-bg)] p-1&quot;&gt;
    &lt;div
      class=&quot;mx-2 h-4 w-4 text-[0] [background:var(--url)_center_center_no-repeat] dark:invert&quot;
      style=&quot;--url: url(.&#x2F;icons&#x2F;info.svg)&quot;
    &gt;
      info
    &lt;&#x2F;div&gt;
    &lt;span&gt;&lt;strong&gt;Note&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;pl-4&quot;&gt;&lt;p&gt;This post was edited to update the various references to the package source repository, which is now hosted on &lt;a href=&quot;https:&#x2F;&#x2F;codeberg.org&quot;&gt;Codeberg&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
</feed>
