<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:webfeeds="http://webfeeds.org/rss/1.0">
  <channel>
    <title>Posts on staticnotes.org</title>
    <link>https://staticnotes.org/posts/</link>
    <webfeeds:icon>https://staticnotes.org/logo.png</webfeeds:icon>
    <webfeeds:logo>https://staticnotes.org/logo.png</webfeeds:logo>
    <description>Recent content in Posts on staticnotes.org</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-US</language>
    <copyright>staticnotes.org (CC BY-NC-SA 4.0)</copyright><atom:link href="https://staticnotes.org/posts/index.xml" rel="self" type="application/rss+xml" /><image>
      <url>https://staticnotes.org/logo.png</url>
      <title>staticnotes.org</title>
      <link>https://staticnotes.org/posts/</link>
    </image>
    
    <item>
      <title>Encrypted cloud backups with restic</title>
      <link>https://staticnotes.org/posts/cloud-backups-with-restic/</link>
      <pubDate>Mon, 31 Aug 2026 00:00:00 +0100</pubDate>
      
      <guid>https://staticnotes.org/posts/cloud-backups-with-restic/</guid>
      <description>&lt;p&gt;My current backup strategy is pretty inconsistent. I run a weekly system backup of my MacBook onto an external hardrive &lt;code&gt;sysbackup&lt;/code&gt; using &lt;a href=&#34;https://bombich.com/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;CarbonCopyCloner&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. I also have another external hardrive &lt;code&gt;photos1&lt;/code&gt; to store files that don&amp;rsquo;t fit onto my MacBook and which isn&amp;rsquo;t backed up at all. Unfortunately, this includes most of my photos and videos. Storing those photos in the cloud would be a convenient option. However, I am not comfortable uploading &lt;em&gt;important&lt;/em&gt; personal documents and photos to the cloud.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; Even if Google Photos reminds me daily that I should.&lt;/small&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;p&gt;This status quo is eventually going to fail, e.g. if the &lt;code&gt;photos1&lt;/code&gt; drive breaks or both my MacBook and the &lt;code&gt;sysbackup&lt;/code&gt; drive get destroyed at the same time (burglary, fire, flooding, ransomware attack). Recently, my photo hardrive made unusually loud noises when plugged in, which prompted me to finally adopt a more solid backup approach.&lt;/p&gt;&#xA;&lt;p&gt;Generally for backups the 3-2-1 rule is recommended (3 copies, 2 different storage media, 1 off-site backup). To accomplish this I will periodically clone the external hardrive &lt;code&gt;photos1&lt;/code&gt; to a new external hardrive &lt;code&gt;photos2&lt;/code&gt; and also set up the off-site backup. This post is mostly about how I set up the cloud backup, but I will summarize the overall approach at the end as well.&lt;/p&gt;&#xA;&lt;h2 id=&#34;requirements-for-my-cloud-backup&#34; class=&#34;content-heading&#34;&gt;Requirements for my cloud backup&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;To find the right approach I wrote down my requirements:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;reliable and cheap cloud storage&lt;/li&gt;&#xA;&lt;li&gt;backups encrypted locally before upload&lt;/li&gt;&#xA;&lt;li&gt;open-source software to prevent vendor lock-in or software disappearing in 5 years.&lt;/li&gt;&#xA;&lt;li&gt;simple to use for someone comfortable with the command line&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In the end I settled on &lt;a href=&#34;https://restic.net/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;&lt;code&gt;restic&lt;/code&gt;&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; which works on Linux, macOS, Windows, encrypts data locally by default, and doesn&amp;rsquo;t need to run on a server.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; I also looked into &lt;a href=&#34;https://www.borgbackup.org/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;BorgBackup&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; which probably would have worked as well. However, that requires running borg on the server.&lt;/small&gt;&lt;/span&gt; Moreover, the commands and basic configuration are straightforward.&lt;/p&gt;&#xA;&lt;h2 id=&#34;getting-cheap-space-in-the-cloud&#34; class=&#34;content-heading&#34;&gt;Getting cheap space in the cloud&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I already have a Hetzner account to host my Nextcloud instance. Luckily, they offer very cheap storage. I got the &lt;em&gt;Hetzner 1TB Storage Box&lt;/em&gt; for 3.83€/month. This means my data is stored in their datacenter in Falkenstein, Germany. By activating automatic snapshots of the storage box in the Hetzner console, I get another backup layer.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; &lt;a href=&#34;https://www.youtube.com/watch?v=MQeJYEN_lrg&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Here&#xA;    &#xA;&#xA;        &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.9em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 448 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M549.7 124.1c-6.3-23.7-24.8-42.3-48.3-48.6C458.8 64 288 64 288 64S117.2 64 74.6 75.5c-23.5 6.3-42 24.9-48.3 48.6-11.4 42.9-11.4 132.3-11.4 132.3s0 89.4 11.4 132.3c6.3 23.7 24.8 41.5 48.3 47.8C117.2 448 288 448 288 448s170.8 0 213.4-11.5c23.5-6.3 42-24.2 48.3-47.8 11.4-42.9 11.4-132.3 11.4-132.3s0-89.4-11.4-132.3zm-317.5 213.5V175.2l142.7 81.2-142.7 81.2z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;&#xA;    &#xA;    &#xA;&lt;/a&gt; you can see the inside of their datacenter. &lt;/small&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;p&gt;To set up the Hetzner Storage Box to work with restic, I had to enable &lt;code&gt;External Reachability&lt;/code&gt;, enable &lt;code&gt;SSH&lt;/code&gt;, and set a password in the Hetzner console. The communication between my local machine and the storage box will be via SSH and the file upload happens over &lt;a href=&#34;https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;SFTP&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; which is based on SSH.&lt;/p&gt;&#xA;&lt;p&gt;First I create a new pair of SSH keys&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; I have more detailed notes on setting up SSH keys &lt;a href=&#34;https://staticnotes.org/til/2025/11/how-to-set-up-multiple-ssh-keys/&#34; &#xA;&gt;here&#xA;&lt;/a&gt;.&lt;/small&gt;&lt;/span&gt; and then upload the public key to the storage box. In short:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Create new SSH keys:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ ssh-keygen -t ed25519 -f ~/.ssh/storagebox&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Add a host entry for the storagebox to your &lt;code&gt;~/.ssh/config&lt;/code&gt; file:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;Host storagebox&#xA;    HostName uXXXXXX.your-storagebox.de&#xA;    User uXXXXXX&#xA;    Port 23&#xA;    IdentityFile ~/.ssh/storagebox&#xA;    WarnWeakCrypto no-pq-kex&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Copy the public SSH key to the storagebox:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ ssh-copy-id -p 23 -s -i ~/.ssh/storagebox.pub uXXXXXX@uXXXXXX.your-storagebox.de&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I should now be able to interact via sftp without providing a separate password. I can test that it works with:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ sftp storagebox&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;h2 id=&#34;installing-and-configuring-restic&#34; class=&#34;content-heading&#34;&gt;Installing and configuring &lt;code&gt;restic&lt;/code&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I installed restic via homebrew with &lt;code&gt;brew install restic&lt;/code&gt;. Next, I create a restic password that restic uses to encrypt my data locally before it is uploaded. To not forget it, I stored it in my password manager and also wrote it down in my notes. I also store this password in my Apple Keychain with:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ security add-generic-password -a &amp;#34;$USER&amp;#34; -s restic-password -w&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;I then configured two important environment variables in a new restic config file &lt;code&gt;~/.config/restic/env&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;export RESTIC_REPOSITORY=&amp;#34;sftp:storagebox:/home/restic-backup&amp;#34;&#xA;export RESTIC_PASSWORD_COMMAND=&amp;#34;security find-generic-password -a yourusername -s restic-password -w&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;&lt;code&gt;RESTIC_REPOSITORY&lt;/code&gt; is the director on the storage box where the backups are stored. This is called the &lt;em&gt;restic repository&lt;/em&gt;. &lt;code&gt;RESTIC_PASSWORD_COMMAND&lt;/code&gt; tells &lt;code&gt;restic&lt;/code&gt; which command to run to get the restic password from the Apple Keychain (all of this avoids storing it in plain text in an environment variable).&lt;/p&gt;&#xA;&lt;p&gt;Next I created the restic repository on the storage box with:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic -r sftp:storagebox:/home/restic-backup init&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;This is all that is needed for the initial configuration. I can now start making backups.&lt;/p&gt;&#xA;&lt;h2 id=&#34;basic-restic-backup-commands&#34; class=&#34;content-heading&#34;&gt;Basic restic backup commands&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;To backup the folder &lt;code&gt;~/important_docs/&lt;/code&gt; to the restic repository on the storage box I run:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic backup ~/important_docs --verbose&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;Restic calls the content of a directory at a specific point in time a &lt;em&gt;snapshot&lt;/em&gt;. This snapshot is now available in the repository and I can restore the whole snapshot or selected files of the directory back to my local machine.&lt;/p&gt;&#xA;&lt;p&gt;If I run the above backup command again, restic will create a second snapshot, but not upload any files as none have changed. This deduplication makes sure that the data is stored efficiently.&lt;/p&gt;&#xA;&lt;h2 id=&#34;inspecting-the-storage-box&#34; class=&#34;content-heading&#34;&gt;Inspecting the storage box&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;To inspect the files in my storage box I use &lt;a href=&#34;https://cyberduck.io/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Cyberduck&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. Create a new SFTP connection with the storage box details:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;Server: uXXXXXX.your-storagebox.de&#xA;Port: 22&#xA;Username: uXXXXXX&#xA;SSH Private Key: ~/.ssh/storagebox&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;This opens the file viewer:&#xA;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/cloud-backups-with-restic/cyberduck_files.png&#34; alt=&#34;Cyberduck&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 1. Restic repository files visible in my storage box.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;I can see that (encrypted) restic files have been uploaded to the subfolder &lt;code&gt;restic-backup&lt;/code&gt;.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; Of course I can also store other things in the storage box, e.g. I have a separate &lt;code&gt;sync&lt;/code&gt; folder that I use with &lt;code&gt;rsync&lt;/code&gt;.&lt;/small&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;working-with-snapshots&#34; class=&#34;content-heading&#34;&gt;Working with snapshots&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Here are useful commands to inspect and manage snapshots taken in the past:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;To list all available snapshots in the repository: &lt;code&gt;restic snapshots&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;To list all files in a specific snapshot with id &lt;code&gt;073a90db&lt;/code&gt;: &lt;code&gt;restic ls 073a90db&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;To view the size of the restic repository, run  &lt;code&gt;restic stats --mode raw-data&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;restoring-backups&#34; class=&#34;content-heading&#34;&gt;Restoring backups&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;It is worth understanding how to restore a backed-up directory. Let&amp;rsquo;s say I want to restore snapshot &lt;code&gt;a798b76e&lt;/code&gt;. If I run&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic restore a798b76e --target ~/restore-test&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;restic will reproduce all directories and files that are part of that snapshot in the provided target folder &lt;code&gt;restore-test&lt;/code&gt;. If I just want to restore a single file from a snapshot I can use the &lt;code&gt;--include&lt;/code&gt; flag, e.g.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic restore a798b76e --include photo_of_grandma.jpg --target ~/restore-test&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;This will restore &lt;code&gt;photo_of_grandma.jpg&lt;/code&gt; from snapshot &lt;code&gt;a798b76e&lt;/code&gt; and make it available in the folder &lt;code&gt;~/restore-test&lt;/code&gt;. Important: To restore you will implicitely or explicitely need my restic password. Make sure you have it available.&lt;/p&gt;&#xA;&lt;h2 id=&#34;managing-the-repositorys-size-and-integrity&#34; class=&#34;content-heading&#34;&gt;Managing the repository&amp;rsquo;s size and integrity&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Two additional commands help me manage the repository and its size. To make sure that the data on the storage box hasn&amp;rsquo;t been corrupted I periodically run:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic check&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;This performs a structural integrity check of the data in the repository. Do the available files and the index match? Are there files not in the index? Check that it can decrypt snapshot metadata. This check is fast because it doesn&amp;rsquo;t actually read any data. If I want to also check that files are correct I need to append &lt;code&gt;--read-data&lt;/code&gt; for a full repository read. This will likely take some time. Alternatively I can only check a subset of data with &lt;code&gt;--read-data-subset=5%&lt;/code&gt; or &lt;code&gt;--read-data-subset=500M&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The other important command is &lt;code&gt;forget&lt;/code&gt;. My storage box only has a size of 1TB, so if I keep accumulating snapshots, I will eventually run out of space. &lt;code&gt;forget&lt;/code&gt; and &lt;code&gt;prune&lt;/code&gt; can be used to delete snapshots.&lt;/p&gt;&#xA;&lt;p&gt;To manually delete a snapshot with id &lt;code&gt;a798b76e&lt;/code&gt; I run:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic forget a798b76e&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;This only deletes the snapshot. It doesn&amp;rsquo;t actually delete the data that was exclusive to that snapshot (not part of another snapshot). To delete this data I need to follow up with &lt;code&gt;prune&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic prune&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;or do it as part of the forget command:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic forget a798b76e --prune&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;The restic docs recommend running a &lt;code&gt;restic check&lt;/code&gt; after pruning operations to flag any issues.&lt;/p&gt;&#xA;&lt;p&gt;Instead of deleting a specific snapshot, I want to specify a deletion policy, e.g. &amp;ldquo;keep one backup for the last 6 month, one for the last 4 weeks, and daily for the current week.&amp;rdquo; Restic uses the &lt;code&gt;--keep-*&lt;/code&gt; flag to specify such a policy.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; Use the &lt;code&gt;--dry-run&lt;/code&gt; flag when trying this out the first time.&lt;/small&gt;&lt;/span&gt; Some example policies:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;--keep-last n&lt;/code&gt; keep the &lt;code&gt;n&lt;/code&gt; last (most recent) snapshots.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;--keep-daily n&lt;/code&gt; for the last &lt;code&gt;n&lt;/code&gt; days which have one or more snapshots, keep only the most recent one for each day.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;--keep-weekly n&lt;/code&gt; for the last &lt;code&gt;n&lt;/code&gt; weeks which have one or more snapshots, keep only the most recent one for each week.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;These can be combined (union of snapshots). So for my desired policy I could use:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune --verbose&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;Note that one snapshot could fulfil multiple conditions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;scheduling-and-profiles-with-resticprofile&#34; class=&#34;content-heading&#34;&gt;Scheduling and profiles with &lt;code&gt;resticprofile&lt;/code&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;So far I only have a set of CLI commands that I would have to remember to run periodically.&#xA;To actually make &lt;code&gt;restic&lt;/code&gt; work, I want &lt;em&gt;scheduling&lt;/em&gt; and &lt;em&gt;profiles&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Scheduling to reliably run the backup daily and profiles to have different command configurations for different backup sources, e.g. I want daily backups of core folders on my MacBook and only weekly backups for my external hard drive &lt;code&gt;photos1&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I am using &lt;a href=&#34;https://creativeprojects.github.io/resticprofile/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;resticprofile&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; for both which I install via homebrew&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ brew tap creativeprojects/tap&#xA;$ brew install resticprofile&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;With &lt;code&gt;resticprofile&lt;/code&gt; I can use a &lt;code&gt;yml&lt;/code&gt; or &lt;code&gt;toml&lt;/code&gt; configuration file to specify commands and configurations for specific paths. I created two profiles here &lt;code&gt;~/.config/resticprofile/profiles.yml&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;yml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# default profile set up for files on my MacBook&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;repository&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sftp:storagebox:/home/restic-backup&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;password-command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;security find-generic-password -a yourusername -s restic-password -w&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;initialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;force-inactive-lock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;retry-lock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;10m&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;backup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;~/core_data_from_my_macbook&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;exclude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;~/stuff_I_want_to_exclude/&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;exclude-file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;~/.config/restic/excludes.txt&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;verbose&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;schedule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;11:00&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;forget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# path: true reuses the source list from backup command&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;keep-daily&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;keep-weekly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;keep-monthly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;prune&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;schedule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;12:00&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;check&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;read-data-subset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;5%&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;schedule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Mon 12:30&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# for `photos1` external hard drive&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;photos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;repository&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sftp:storagebox:/home/restic-backup&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;password-command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;security find-generic-password -a yourusername -s restic-password -w&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;initialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;backup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;/Volumes/photos1/Photos&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;forget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;prune&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;keep-last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;The first profile &lt;code&gt;default&lt;/code&gt; configures my MacBook backups. It specifies which folders to backup and is configured to run daily at 11am. At 12pm &lt;code&gt;restic&lt;/code&gt; executes my forget policy on the specified paths and at 12:30 &lt;code&gt;restic&lt;/code&gt; runs an integrity check.&lt;/p&gt;&#xA;&lt;p&gt;I have set up a second profile &lt;code&gt;photos&lt;/code&gt; to configure backups from my external hard drive to the same remote restic repository. The backup command is not scheduled. I only run it after I have copied new photos onto the harddrive, which only really happens every few weeks. The forget policy ensures the last 5 snapshots are kept.&lt;/p&gt;&#xA;&lt;p&gt;To schedule this configuration, I run &lt;code&gt;resticprofile schedule&lt;/code&gt;. On macOS this schedules the jobs in the &lt;code&gt;launchd&lt;/code&gt; service manager.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; The first time this runs, macOS will ask you to confirm permissions.&lt;/small&gt;&lt;/span&gt; I verified the schedule is set with &lt;code&gt;launchctl list | grep -i restic&lt;/code&gt;. Moreover, I can show all configured profiles with&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ resticprofile profiles&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;I run the backup command for the &lt;em&gt;photos profile&lt;/em&gt; manually with&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ resticprofile photos.backup&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;h2 id=&#34;conclusion&#34; class=&#34;content-heading&#34;&gt;Conclusion&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;My final backup approach is show in Figure 2. My MacBook is backed up daily to the remote restic repository on the Hetzner Storage Box and weekly to an external hard drive. My photos hard drive is backed up weekly to the restic repository and monthly to a second external hard drive.&#xA;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/cloud-backups-with-restic/backup_devices.jpg&#34; alt=&#34;Backup approach&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 2. Final backup approach to restic cloud repository and external hard drives.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;I have been running this setup for a couple of weeks and so far I am happy with it. The important files on my MacBook are about 15GB which took 20&amp;ndash;30min for the first uploaded snapshot and only a few seconds since. The &lt;code&gt;photos1&lt;/code&gt; hard drive has about 250GB of data which took 4&amp;ndash;5h for the initial upload.&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s also nice that I can change storage vendor seamlessly, e.g. I can switch to AWS S3 or Backblaze B2 by modifying the config file and setting up new SSH keys.&lt;/p&gt;&#xA;&lt;h2 id=&#34;appendix&#34; class=&#34;content-heading&#34;&gt;Appendix&#xA;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;launchd-schedules-with-sleeping-macbook-closed-lid&#34; class=&#34;content-heading&#34;&gt;Launchd schedules with sleeping MacBook (closed lid)&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I noticed that some scheduled backups failed when my MacBook was asleep (lid closed). I think that it&amp;rsquo;s because launchd resumes scheduled jobs once the MacBook awakes but a network connection isn&amp;rsquo;t always immediately available. I fixed this by checking for a network connection befor running the backup command using the &lt;code&gt;run-before&lt;/code&gt; setting. I added the following line for &lt;code&gt;backup&lt;/code&gt; &lt;code&gt;forget&lt;/code&gt; and &lt;code&gt;check&lt;/code&gt; in my &lt;code&gt;profiles.yml&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;yml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# [...]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;backup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# before running backup try 30x to reach the storage box, this should give time for network access to be available after sleep&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run-before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;for i in $(seq 1 30); do nc -z -G 5 uXXXXXX.your-storagebox.de 23 &amp;amp;&amp;amp; exit 0; sleep 10; done; exit 1&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# [...]      &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;locks&#34; class=&#34;content-heading&#34;&gt;Locks&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Certain restic commands put a lock onto the repository to prevent multiple clients from working on the same files. I can list all locks with&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic list locks&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;Sometimes failed commands leave the repository locked. If you are sure it&amp;rsquo;s safe to unlock it, run:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;$ restic unlock&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;A common failure mode is for example for the &lt;code&gt;check&lt;/code&gt; command to run and fail and leave an exclusive lock behind on the repository, which then makes subsequent backups fail. To avoid this issue I added the following settings:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;yml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# [...]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;repository&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sftp:storagebox:/home/restic-backup&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# remove stale restic locks older than 1h&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;force-inactive-lock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# when restic finds a blocking lock, try locking again in 10min&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;retry-lock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;10m&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# [...]      &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;exclusion-file&#34; class=&#34;content-heading&#34;&gt;Exclusion file&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;My profile uses an exclusion file &lt;code&gt;~/.config/restic/excludes.txt&lt;/code&gt; to ignore certain types of files I don&amp;rsquo;t want to back up, e.g. build artefacts or temporary files:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;txt&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Python&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.venv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;venv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;__pycache__&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;*.pyc&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.pytest_cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.mypy_cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.ruff_cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.tox&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;*.egg-info&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Node / JS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;node_modules&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.next&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.nuxt&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.parcel-cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Editors &amp;amp; tooling&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.idea&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.vscode&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;*.swp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;*~&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Caches &amp;amp; logs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.cache&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;*.log&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;*.tmp&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.terraform&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# OS junk&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.DS_Store&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;._*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.Spotlight-V100&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.fseventsd&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.Trashes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.TemporaryItems&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.DocumentRevisions-V100&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Additionally I use the flag &lt;code&gt;exclude-caches: true&lt;/code&gt;, which ignores all folders that have a &lt;code&gt;CACHEDIR.TAG&lt;/code&gt; file, e.g. Rust cache directories.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Visualising London rental bike location data</title>
      <link>https://staticnotes.org/posts/london-bike-data/</link>
      <pubDate>Wed, 15 Jul 2026 12:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/london-bike-data/</guid>
      <description>&lt;p&gt;London has a great rental bike scheme that makes it easy to get around the city. Rather than free-floating you can rent bikes from fixed bike stations like the one shown below. If you get the yearly membership you even get a key that you can use to rent the bike without an app.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;map_images/station_photo.jpg&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;400px&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/london-bike-data/output_1_0.jpg&#34; alt=&#34;jpeg&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Moreover, Transport for London makes the live rental station data available on &lt;a href=&#34;https://tfl.gov.uk/tfl/syndication/feeds/cycle-hire/livecyclehireupdates.xml&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;this endpoint&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. I collected hourly snapshots of bike availability data over a month so I can play around with it with DuckDB&amp;rsquo;s new spatial features and QGIS.&lt;/p&gt;&#xA;&lt;h2 id=&#34;collecting-the-data&#34; class=&#34;content-heading&#34;&gt;Collecting the data&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I created a simple script &lt;code&gt;fetch_bike_data.sh&lt;/code&gt; and a cronjob on a Hetzner VPS to request and store the data every hour. Here is the script:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;DATE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;((&lt;/span&gt;date +&lt;span class=&#34;s2&#34;&gt;&amp;#34;%Y.%m.%d.%H.%M.%S&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;DIR&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/home/projects/bike&lt;span class=&#34;se&#34;&gt;\_&lt;/span&gt;data&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir -p &lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;DIR&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -o santander.&lt;span class=&#34;nv&#34;&gt;$DATE&lt;/span&gt;.xml https://tfl.gov.uk/tfl/syndication/feeds/cycle-hire/livecyclehireupdates.xml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;After adding permissions to the script with &lt;code&gt;chmod +x fetch_bike_data.sh&lt;/code&gt; I modify crontab:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;crontab -e&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;and add the following line to run this script:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; * * * * /home/projects/bike_data/fetch_bike_data.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Each request is stored to an XML-file on disk which has the following format:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;xml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;stations&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;lastUpdate=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1784031061002&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;version=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;2.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;station&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;id&amp;gt;&lt;/span&gt;1&lt;span class=&#34;nt&#34;&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;River Street , Clerkenwell&lt;span class=&#34;nt&#34;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;terminalName&amp;gt;&lt;/span&gt;001023&lt;span class=&#34;nt&#34;&gt;&amp;lt;/terminalName&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;lat&amp;gt;&lt;/span&gt;51.52916347&lt;span class=&#34;nt&#34;&gt;&amp;lt;/lat&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;long&amp;gt;&lt;/span&gt;-0.109970527&lt;span class=&#34;nt&#34;&gt;&amp;lt;/long&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;installed&amp;gt;&lt;/span&gt;true&lt;span class=&#34;nt&#34;&gt;&amp;lt;/installed&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;locked&amp;gt;&lt;/span&gt;false&lt;span class=&#34;nt&#34;&gt;&amp;lt;/locked&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;installDate&amp;gt;&lt;/span&gt;1278947280000&lt;span class=&#34;nt&#34;&gt;&amp;lt;/installDate&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;removalDate/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;temporary&amp;gt;&lt;/span&gt;false&lt;span class=&#34;nt&#34;&gt;&amp;lt;/temporary&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbBikes&amp;gt;&lt;/span&gt;0&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbBikes&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbStandardBikes&amp;gt;&lt;/span&gt;0&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbStandardBikes&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbEBikes&amp;gt;&lt;/span&gt;0&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbEBikes&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbEmptyDocks&amp;gt;&lt;/span&gt;19&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbEmptyDocks&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbDocks&amp;gt;&lt;/span&gt;19&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbDocks&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/station&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;station&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;id&amp;gt;&lt;/span&gt;2&lt;span class=&#34;nt&#34;&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Phillimore Gardens, Kensington&lt;span class=&#34;nt&#34;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;terminalName&amp;gt;&lt;/span&gt;001018&lt;span class=&#34;nt&#34;&gt;&amp;lt;/terminalName&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;lat&amp;gt;&lt;/span&gt;51.49960695&lt;span class=&#34;nt&#34;&gt;&amp;lt;/lat&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;long&amp;gt;&lt;/span&gt;-0.197574246&lt;span class=&#34;nt&#34;&gt;&amp;lt;/long&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;installed&amp;gt;&lt;/span&gt;true&lt;span class=&#34;nt&#34;&gt;&amp;lt;/installed&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;locked&amp;gt;&lt;/span&gt;false&lt;span class=&#34;nt&#34;&gt;&amp;lt;/locked&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;installDate&amp;gt;&lt;/span&gt;1278585780000&lt;span class=&#34;nt&#34;&gt;&amp;lt;/installDate&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;removalDate/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;temporary&amp;gt;&lt;/span&gt;false&lt;span class=&#34;nt&#34;&gt;&amp;lt;/temporary&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbBikes&amp;gt;&lt;/span&gt;6&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbBikes&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbStandardBikes&amp;gt;&lt;/span&gt;6&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbStandardBikes&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbEBikes&amp;gt;&lt;/span&gt;0&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbEBikes&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbEmptyDocks&amp;gt;&lt;/span&gt;28&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbEmptyDocks&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;lt;nbDocks&amp;gt;&lt;/span&gt;37&lt;span class=&#34;nt&#34;&gt;&amp;lt;/nbDocks&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/station&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;As you can see the raw data contains per-station information about its name, location, and bike availability.&lt;/p&gt;&#xA;&lt;h2 id=&#34;convert-to-duckdb-table&#34; class=&#34;content-heading&#34;&gt;Convert to DuckDB table&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I load and combine all the XML-files into a DuckDB database &lt;code&gt;london_bike_data&lt;/code&gt; so that I can use SQL to analyse it. Before I do that I install the extensions &lt;code&gt;spatial&lt;/code&gt; and &lt;code&gt;h3&lt;/code&gt; for the geospatial features and &lt;code&gt;webbed&lt;/code&gt; to read xml files.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;duckdb&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;IPython.display&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Connect to DuckDB&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;duckdb&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;london_bike_data.duckdb&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;INSTALL spatial;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;INSTALL h3 FROM community;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;INSTALL webbed FROM community;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;LOAD spatial;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;LOAD h3;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;LOAD webbed;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;The next query loads all collected xml-files into one DuckDB table and enforces the schema, adds metadata, and handles missing data issues. Note the Hetzner instance was based in Helsinki which I account for when converting the filename into a timestamp with the correct time zone.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    CREATE OR REPLACE TABLE londonbikestations AS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;     SELECT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            strptime(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            regexp_extract(filename, &amp;#39;santander&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.(&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{4}&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.xml&amp;#39;, 1),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            &amp;#39;%Y.%m.&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.%H.%M.%S&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        ) AT TIME ZONE &amp;#39;Europe/Helsinki&amp;#39; AT TIME ZONE &amp;#39;Europe/London&amp;#39; AS downloaded_at,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 id::INTEGER AS id,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 terminalName AS terminal_name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 lat::DOUBLE AS lat,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 long::DOUBLE AS lng,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 installed::BOOLEAN AS installed,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 locked::BOOLEAN AS locked,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 temporary::BOOLEAN AS temporary,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 nbBikes::INTEGER AS nb_bikes,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 nbStandardBikes::INTEGER AS nb_standard_bikes,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 nbEBikes::INTEGER AS nb_ebikes,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 nbEmptyDocks::INTEGER AS nb_empty_docks,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                 nbDocks::INTEGER AS nb_docks,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                epoch_ms(installDate::BIGINT) AS install_date,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                CASE WHEN removalDate = &amp;#39;&amp;#39; THEN NULL ELSE epoch_ms(removalDate::BIGINT) END AS removal_date&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;             FROM read_xml(&amp;#39;data/santander.*.xml&amp;#39;, all_varchar=true, filename=true)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sql&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;select count(*) from londonbikestations&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;┌──────────────┐&#xA;│ count_star() │&#xA;│    int64     │&#xA;├──────────────┤&#xA;│       707197 │&#xA;└──────────────┘&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The query below shows the station data that is available. The table contains the station &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt; and coordinates (&lt;code&gt;lat&lt;/code&gt;, &lt;code&gt;lng&lt;/code&gt;) and when it was installed and/or removed. For every station I have the capacity &lt;code&gt;nb_docks&lt;/code&gt; and the current number of rentable bikes &lt;code&gt;nb_bikes&lt;/code&gt; (split into standard and ebikes).&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sql&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;describe table londonbikestations&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;┌───────────────────┬─────────────┬─────────┬─────────┬─────────┬─────────┐&#xA;│    column_name    │ column_type │  null   │   key   │ default │  extra  │&#xA;│      varchar      │   varchar   │ varchar │ varchar │ varchar │ varchar │&#xA;├───────────────────┼─────────────┼─────────┼─────────┼─────────┼─────────┤&#xA;│ downloaded_at     │ TIMESTAMP   │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ id                │ INTEGER     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ name              │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ terminal_name     │ VARCHAR     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ lat               │ DOUBLE      │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ lng               │ DOUBLE      │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ installed         │ BOOLEAN     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ locked            │ BOOLEAN     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ temporary         │ BOOLEAN     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ nb_bikes          │ INTEGER     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ nb_standard_bikes │ INTEGER     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ nb_ebikes         │ INTEGER     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ nb_empty_docks    │ INTEGER     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ nb_docks          │ INTEGER     │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ install_date      │ TIMESTAMP   │ YES     │ NULL    │ NULL    │ NULL    │&#xA;│ removal_date      │ TIMESTAMP   │ YES     │ NULL    │ NULL    │ NULL    │&#xA;└───────────────────┴─────────────┴─────────┴─────────┴─────────┴─────────┘&#xA;  16 rows                                                       6 columns&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The &lt;code&gt;removal_date&lt;/code&gt; column seems not trustworthy since there is definitely activity (changes in &lt;code&gt;nb_bikes&lt;/code&gt;) happening at stations that have a removal date, e.g.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sql&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;select downloaded_at, name, terminal_name, nb_bikes, removal_date from londonbikestations where terminal_name = &amp;#39;000968&amp;#39; order by downloaded_at&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;┌─────────────────────┬──────────────────────────┬───────────────┬──────────┬─────────────────────┐&#xA;│    downloaded_at    │           name           │ terminal_name │ nb_bikes │    removal_date     │&#xA;│      timestamp      │         varchar          │    varchar    │  int32   │      timestamp      │&#xA;├─────────────────────┼──────────────────────────┼───────────────┼──────────┼─────────────────────┤&#xA;│ 2026-05-08 22:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│ 2026-05-08 23:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│ 2026-05-09 00:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│ 2026-05-09 01:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│ 2026-05-09 02:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│ 2026-05-09 03:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│ 2026-05-09 04:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│ 2026-05-09 05:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│ 2026-05-09 06:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│ 2026-05-09 07:00:01 │ Warwick Row, Westminster │ 000968        │        6 │ 2018-10-18 06:56:00 │&#xA;│          ·          │            ·             │   ·           │        · │          ·          │&#xA;│          ·          │            ·             │   ·           │        · │          ·          │&#xA;│          ·          │            ·             │   ·           │        · │          ·          │&#xA;│ 2026-06-14 12:00:01 │ Warwick Row, Westminster │ 000968        │        3 │ 2018-10-18 06:56:00 │&#xA;│ 2026-06-14 13:00:01 │ Warwick Row, Westminster │ 000968        │        5 │ 2018-10-18 06:56:00 │&#xA;│ 2026-06-14 14:00:01 │ Warwick Row, Westminster │ 000968        │        9 │ 2018-10-18 06:56:00 │&#xA;│ 2026-06-14 15:00:01 │ Warwick Row, Westminster │ 000968        │        4 │ 2018-10-18 06:56:00 │&#xA;│ 2026-06-14 16:00:01 │ Warwick Row, Westminster │ 000968        │        2 │ 2018-10-18 06:56:00 │&#xA;│ 2026-06-14 17:00:01 │ Warwick Row, Westminster │ 000968        │        7 │ 2018-10-18 06:56:00 │&#xA;│ 2026-06-14 18:00:01 │ Warwick Row, Westminster │ 000968        │        9 │ 2018-10-18 06:56:00 │&#xA;│ 2026-06-14 19:00:01 │ Warwick Row, Westminster │ 000968        │       10 │ 2018-10-18 06:56:00 │&#xA;│ 2026-06-14 20:00:01 │ Warwick Row, Westminster │ 000968        │       11 │ 2018-10-18 06:56:00 │&#xA;│ 2026-06-14 21:00:01 │ Warwick Row, Westminster │ 000968        │        8 │ 2018-10-18 06:56:00 │&#xA;└─────────────────────┴──────────────────────────┴───────────────┴──────────┴─────────────────────┘&#xA;  887 rows (20 shown)                                                                   5 columns&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I have confirmed that this station still exists (&lt;a href=&#34;https://santandercycles.tfl.gov.uk/map&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;) so I will just ignore this column.&lt;/p&gt;&#xA;&lt;p&gt;I want to get an overview of the total capacity across all stations. The exact number fluctuates slightly between snapshots but the capacity seems to be around 20.9k. The maximum number of &lt;em&gt;docked&lt;/em&gt; bikes was 7708 standard bikes and 1131 eBikes. The &lt;a href=&#34;https://www.santander.co.uk/about-santander/media-centre/press-releases/santander-renews-sponsorship-of-londons-cycle-hire&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;official numbers&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; given by TfL are 10,000 standard bikes and 2,000 eBikes.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sql&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;select downloaded_at, sum(nb_standard_bikes) as sum_docked_standard_bikes, sum(nb_ebikes) as sum_docked_ebikes, sum(nb_docks) as sum_station_capacity from londonbikestations group by downloaded_at order by sum_docked_standard_bikes&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;┌─────────────────────┬───────────────────────────┬───────────────────┬──────────────────────┐&#xA;│    downloaded_at    │ sum_docked_standard_bikes │ sum_docked_ebikes │ sum_station_capacity │&#xA;│      timestamp      │          int128           │      int128       │        int128        │&#xA;├─────────────────────┼───────────────────────────┼───────────────────┼──────────────────────┤&#xA;│ 2026-06-04 08:00:01 │                      6008 │               795 │                20963 │&#xA;│ 2026-06-01 08:00:01 │                      6047 │               585 │                20934 │&#xA;│ 2026-06-03 08:00:01 │                      6056 │               948 │                20951 │&#xA;│ 2026-06-02 08:00:01 │                      6082 │               927 │                20921 │&#xA;│ 2026-06-04 17:00:01 │                      6122 │              1185 │                20963 │&#xA;│ 2026-06-09 08:00:02 │                      6127 │               830 │                20962 │&#xA;│ 2026-05-28 08:00:01 │                      6191 │               692 │                20950 │&#xA;│ 2026-06-01 17:00:01 │                      6201 │              1086 │                20892 │&#xA;│ 2026-05-27 17:00:01 │                      6203 │               829 │                20950 │&#xA;│ 2026-06-04 10:00:01 │                      6210 │               983 │                20963 │&#xA;│          ·          │                        ·  │                ·  │                  ·   │&#xA;│          ·          │                        ·  │                ·  │                  ·   │&#xA;│          ·          │                        ·  │                ·  │                  ·   │&#xA;│ 2026-05-16 06:00:01 │                      7668 │              1081 │                20969 │&#xA;│ 2026-05-15 01:00:01 │                      7671 │              1182 │                20949 │&#xA;│ 2026-05-15 03:00:01 │                      7674 │              1169 │                20949 │&#xA;│ 2026-05-16 01:00:01 │                      7678 │              1172 │                20942 │&#xA;│ 2026-05-15 02:00:01 │                      7678 │              1178 │                20949 │&#xA;│ 2026-05-16 00:00:01 │                      7679 │              1186 │                20942 │&#xA;│ 2026-05-16 02:00:01 │                      7699 │              1157 │                20942 │&#xA;│ 2026-05-16 05:00:01 │                      7703 │              1106 │                20969 │&#xA;│ 2026-05-16 03:00:01 │                      7705 │              1143 │                20942 │&#xA;│ 2026-05-16 04:00:01 │                      7708 │              1131 │                20942 │&#xA;└─────────────────────┴───────────────────────────┴───────────────────┴──────────────────────┘&#xA;  887 rows (20 shown)                                                              4 columns&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The largest station is Jubilee Plaza in Canary Wharf.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sql&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;select name, nb_bikes, nb_docks from londonbikestations order by nb_docks desc limit 1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;┌─────────────────────────────┬──────────┬──────────┐&#xA;│            name             │ nb_bikes │ nb_docks │&#xA;│           varchar           │  int32   │  int32   │&#xA;├─────────────────────────────┼──────────┼──────────┤&#xA;│ Jubilee Plaza, Canary Wharf │       42 │       63 │&#xA;└─────────────────────────────┴──────────┴──────────┘&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;busiest-stations&#34; class=&#34;content-heading&#34;&gt;Busiest stations&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;To approximate the busiest stations I sum the absolute hour-to-hour change in &lt;code&gt;nb_bikes&lt;/code&gt; per station. This approximates total churn (bikes leaving and arriving) since simultaneous arrivals and departures within the same hour cancel out.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    CREATE OR REPLACE TABLE busy_stations AS   &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    WITH hourly_changes AS (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        SELECT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            terminal_name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            ST_POINT(lng, lat) AS geometry,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            downloaded_at,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            nb_bikes,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            abs(nb_bikes - lag(nb_bikes) OVER w) AS abs_change&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        FROM londonbikestations&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        WINDOW w AS (PARTITION BY terminal_name ORDER BY downloaded_at)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    SELECT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        terminal_name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        geometry,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        any_value(name) AS name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        sum(abs_change) AS total_churn,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        count(*) AS nb_snapshots&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    FROM hourly_changes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    GROUP BY terminal_name, geometry&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    ORDER BY total_churn DESC&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sql&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;select name, total_churn from busy_stations limit 20&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;┌──────────────────────────────────────────┬─────────────┐&#xA;│                   name                   │ total_churn │&#xA;│                 varchar                  │   int128    │&#xA;├──────────────────────────────────────────┼─────────────┤&#xA;│ Hop Exchange, The Borough                │        3218 │&#xA;│ Soho Square , Soho                       │        3160 │&#xA;│ Argyle Street, Kings Cross               │        2930 │&#xA;│ Waterloo Station 2, Waterloo             │        2753 │&#xA;│ Hyde Park Corner, Hyde Park              │        2605 │&#xA;│ Waterloo Station 1, Waterloo             │        2554 │&#xA;│ Moorfields, Moorgate                     │        2527 │&#xA;│ Brushfield Street, Liverpool Street      │        2514 │&#xA;│ Waterloo Station 3, Waterloo             │        2389 │&#xA;│ St. James&#39;s Square, St. James&#39;s          │        2360 │&#xA;│ Jubilee Plaza, Canary Wharf              │        2289 │&#xA;│ Eagle Wharf Road, Hoxton                 │        2263 │&#xA;│ Cheapside, Bank                          │        2202 │&#xA;│ Imperial College, Knightsbridge          │        2181 │&#xA;│ Worship Street, Shoreditch               │        2167 │&#xA;│ Natural History Museum, South Kensington │        2142 │&#xA;│ Whitehall Place, Strand                  │        2042 │&#xA;│ Queen&#39;s Gate (North), Kensington         │        2019 │&#xA;│ Malet Street, Bloomsbury                 │        2013 │&#xA;│ Exhibition Road, Knightsbridge           │        1987 │&#xA;└──────────────────────────────────────────┴─────────────┘&#xA;  20 rows                                      2 columns&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;None of these stations are surprising. As we can see later on the map all of these stations are in the city centre or close to commuter train stations.&lt;/p&gt;&#xA;&lt;h2 id=&#34;busiest-hours-of-the-day&#34; class=&#34;content-heading&#34;&gt;Busiest hours of the day&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Using the same total-churn metric I group the data by hour of day to see when bike activity peaks.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sql&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    WITH hourly_changes AS (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        SELECT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            terminal_name,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            downloaded_at,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            nb_bikes,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            abs(nb_bikes - lag(nb_bikes) OVER w) AS abs_change&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        FROM londonbikestations&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        WINDOW w AS (PARTITION BY terminal_name ORDER BY downloaded_at)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    SELECT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        hour(downloaded_at) AS hour_of_day,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        sum(abs_change) AS total_churn,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        count(*) AS nb_snapshots&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    FROM hourly_changes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    GROUP BY hour_of_day&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    ORDER BY total_churn&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;┌─────────────┬─────────────┬──────────────┐&#xA;│ hour_of_day │ total_churn │ nb_snapshots │&#xA;│    int64    │   int128    │    int64     │&#xA;├─────────────┼─────────────┼──────────────┤&#xA;│           3 │        3911 │        29501 │&#xA;│           4 │        4111 │        29501 │&#xA;│           2 │        5398 │        29501 │&#xA;│           5 │        7441 │        29502 │&#xA;│           1 │        8518 │        29501 │&#xA;│           0 │       13462 │        29501 │&#xA;│           6 │       20333 │        29502 │&#xA;│          23 │       21172 │        29500 │&#xA;│          22 │       29554 │        29500 │&#xA;│          21 │       33808 │        28702 │&#xA;│           · │         ·   │          ·   │&#xA;│           · │         ·   │          ·   │&#xA;│           · │         ·   │          ·   │&#xA;│          13 │       40336 │        29497 │&#xA;│          20 │       40433 │        29499 │&#xA;│          10 │       41575 │        29495 │&#xA;│           7 │       45237 │        29503 │&#xA;│          19 │       47598 │        28707 │&#xA;│          16 │       54813 │        29498 │&#xA;│           9 │       57626 │        29498 │&#xA;│          17 │       64213 │        29498 │&#xA;│          18 │       64873 │        30300 │&#xA;│           8 │       78166 │        29503 │&#xA;└─────────────┴─────────────┴──────────────┘&#xA;  24 rows (20 shown)             3 columns&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;We see the highest activity from 7:00-8:00, 8:00-9:00, 16:00-17:00, 17:00-18:00 which are peak commuter hours and the lowest activity in the early morning.&lt;/p&gt;&#xA;&lt;h2 id=&#34;storing-geometric-data-as-parquet-files&#34; class=&#34;content-heading&#34;&gt;Storing geometric data as parquet files&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Before I can use QGIS for map-based visualisations I need to store the relevant data in a compatible format.&lt;/p&gt;&#xA;&lt;p&gt;I want to show the number of bikes available across the city at different times of the day (I picked Wednesday 27.5.2026). To aggregate the number of available bikes spatially, I group by &lt;a href=&#34;https://www.uber.com/gb/en/blog/h3/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;H3 cells&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. If the coordinates of the bike station fall into the cell I sum all available bikes.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    CREATE OR REPLACE TABLE bike_station_geo AS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        SELECT *, ST_POINT(lng, lat) AS geometry FROM londonbikestations where downloaded_at::date = &amp;#39;2026-05-27&amp;#39;   &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;    CREATE OR REPLACE TABLE h3_cell_covering AS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        SELECT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            downloaded_at,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            H3_LATLNG_TO_CELL(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                ST_Y(geometry),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                ST_X(geometry),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;                7&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            ) AS hexagon,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;            sum(nb_bikes) AS nb_bikes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        FROM bike_station_geo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;        GROUP BY 1, 2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;I then store the h3 bike counts table as a parquet file. This involves conversion of the hexagon data into WKB(well-known-binary) that GeoParquet uses to store geometries. Note: By default the geometry in DuckDB is assumed to be &lt;code&gt;EPSG:4326&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;COPY (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;      SELECT geometry: ST_ASWKB(H3_CELL_TO_BOUNDARY_WKT(hexagon)::geometry),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;              date_trunc(&amp;#39;hour&amp;#39;, downloaded_at) AS downloaded_at,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;             nb_bikes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;      FROM   h3_cell_covering&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;  ) TO &amp;#39;available_bikes_per_h3_7_cell.parquet&amp;#39;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;  &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;I also want to visualise the location of the busy stations on the map, so I store the busy stations as a separate file.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;COPY (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;      SELECT *  FROM busy_stations&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;  ) TO &amp;#39;busy_stations.parquet&amp;#39;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;  &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h2 id=&#34;visualising-availability-using-qgis&#34; class=&#34;content-heading&#34;&gt;Visualising availability using QGIS&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/QGIS&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;QGIS&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; (3.44.10) is an open-source geographic information system. It allows combining, viewing, and analysing tabular data with geographic and mapping data.&lt;/p&gt;&#xA;&lt;p&gt;I want to display our parquet data over an actual map of London. To get this map, I install the plugin &lt;code&gt;NextGIS MapServices&lt;/code&gt; and then restart QGIS to make it available. I use OpenStreetMap as the base map. In the toolbar click on &lt;code&gt;QuickMapService&lt;/code&gt;(Globe icon) and add the OpenstreetMap OSM Standard. Next, in &lt;code&gt;Project Properties&lt;/code&gt; (Cmd+Shift+P)-&amp;gt; &lt;code&gt;CRS&lt;/code&gt; change the Projection or Coordinate Reference System to &lt;code&gt;EPSG:3857 (Pseudo-Mercator)&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;visualising-busy-stations&#34; class=&#34;content-heading&#34;&gt;Visualising busy stations&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Drag and drop the &lt;code&gt;busy_stations.parquet&lt;/code&gt; file into the Layers field (bottom left). Ensure under &lt;code&gt;Layer Properties&lt;/code&gt; &amp;ndash;&amp;gt; &lt;code&gt;Assigned Coordinate Reference System&lt;/code&gt; that &lt;code&gt;EPSG:4326 - WGS 84&lt;/code&gt; is selected. This allows QGIS to correctly reproject the geography data from the file onto the map.&lt;/p&gt;&#xA;&lt;p&gt;Under &lt;code&gt;Layer Properties&lt;/code&gt; &amp;ndash;&amp;gt; &lt;code&gt;Symbology&lt;/code&gt; I can change the style of the location marker to show all the stations. You can see all the coordinates of stations in the dataset below.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;map_images/station_locations.jpg&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/london-bike-data/output_29_0.jpg&#34; alt=&#34;jpeg&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;To only show the top 20 busiest stations as calculated in the previous section I add a filter on the busy stations layer. (Right click on layer &amp;ndash;&amp;gt; &lt;code&gt;Filter&lt;/code&gt;, then add &lt;code&gt;total_churn &amp;gt; 1900&lt;/code&gt;). I also want to show the station names, so I go to &lt;code&gt;Layer Properties&lt;/code&gt; &amp;ndash;&amp;gt; &lt;code&gt;Label&lt;/code&gt; &amp;ndash;&amp;gt; &lt;code&gt;Single labels&lt;/code&gt; and select for &lt;code&gt;value&lt;/code&gt; the Expression Builder and then use the expression: &lt;code&gt;&amp;quot;name&amp;quot; || &#39; (&#39; || to_string(&amp;quot;total_churn&amp;quot;) || &#39;)&#39;&lt;/code&gt; to concatenate the churn value to the station name in brackets.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;map_images/busy_stations.jpg&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/london-bike-data/output_31_0.jpg&#34; alt=&#34;jpeg&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Unsurprisingly the busiest stations are in the centre where many Londoners work (Bank, Canary Wharf, Soho, Westminster) or close to major train stations (Liverpool Street, King&amp;rsquo;s Cross, Waterloo, Hop Exchange).&lt;/p&gt;&#xA;&lt;h3 id=&#34;rental-bike-availability-during-commute-hours&#34; class=&#34;content-heading&#34;&gt;Rental bike availability during commute hours&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I also want to visualise how the rental bikes move before and after morning rush hour. My expectation is that fewer bikes are initially in the city centre (zone 1) and more bikes in the outer residential areas (zones 2 and 3). Then around 11am we should see a concentration of bikes in zone 1.&lt;/p&gt;&#xA;&lt;p&gt;I drag and drop the relevant data file &lt;code&gt;available_bikes_per_h3_7_cell.parquet&lt;/code&gt; to create a new Layer. Again, I first ensure that the projection for this dataset is set to &lt;code&gt;EPSG:4326 - WGS 84&lt;/code&gt;. The hexagons should now appear on top of the map. Remember that the file has availability data for every hour of the day, so I add a Layer filter: &lt;code&gt;&amp;quot;downloaded_at&amp;quot; = &#39;2026-05-27T06:00:00.000&#39;&lt;/code&gt; to only use data from one point in time before the start of the rush hour.&lt;/p&gt;&#xA;&lt;p&gt;To style the hex fields according to the number of available bikes in the hexagon area I make the following changes in the Layer properties:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Symbology&lt;/code&gt; &amp;ndash;&amp;gt; &lt;code&gt;Graduated&lt;/code&gt; &amp;ndash;&amp;gt; Value: &lt;code&gt;nb_bikes&lt;/code&gt;, Color Ramp: &lt;code&gt;RdYlGr&lt;/code&gt;, Mode: &lt;code&gt;Equal Interval&lt;/code&gt;, Opacity: &lt;code&gt;60%&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Labels&lt;/code&gt; &amp;ndash;&amp;gt; &lt;code&gt;Single Labels&lt;/code&gt; &amp;ndash;&amp;gt; Value: &lt;code&gt;nb_bikes&lt;/code&gt;, 18Pt, Bold.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I have filtered the layer once for 6am and once for 11am and here are the two outputs:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;map_images/bike_availibility_6am.jpg&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/london-bike-data/output_34_0.jpg&#34; alt=&#34;jpeg&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;map_images/bike_availibility_11am.jpg&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/london-bike-data/output_35_0.jpg&#34; alt=&#34;jpeg&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;As expected you can see that a lot of the residential districts along the water, West Kensington, Fulham, Wandsworth, Battersea, Elephant and Castle and in the east around Limehouse, Mile End, Bethnal Green see an outflow of available bikes. The central districts around the City of London, Mayfair, King&amp;rsquo;s Cross and Westminster accumulate a lot of the bikes by 11am.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34; class=&#34;content-heading&#34;&gt;Conclusion&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;It turns out to be pretty easy to collect, explore and visualise the London bike station data. DuckDB makes it really easy to ingest hundreds of XML files and the H3 and spatial extensions allow easy geographical aggregation. This is my first time using QGIS. It took 20min to get up to speed with it, but it&amp;rsquo;s really cool how it fuses mapping data and geographical and analytical data. I will try to use it in other projects as well.&lt;/p&gt;&#xA;&lt;h2 id=&#34;references&#34; class=&#34;content-heading&#34;&gt;References&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I was inspired by &lt;a href=&#34;https://tech.marksblogg.com/ebike-fleet-monitoring.html&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Mark&#xA;Litwintschik&amp;rsquo;s ebike fleet monitoring&#xA;blog post&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;A useful QGIS Tutorial is available &lt;a href=&#34;https://www.youtube.com/watch?v=SovdBaus7pM&amp;amp;t=4127s&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;&#xA;        &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.9em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 448 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M549.7 124.1c-6.3-23.7-24.8-42.3-48.3-48.6C458.8 64 288 64 288 64S117.2 64 74.6 75.5c-23.5 6.3-42 24.9-48.3 48.6-11.4 42.9-11.4 132.3-11.4 132.3s0 89.4 11.4 132.3c6.3 23.7 24.8 41.5 48.3 47.8C117.2 448 288 448 288 448s170.8 0 213.4-11.5c23.5-6.3 42-24.2 48.3-47.8 11.4-42.9 11.4-132.3 11.4-132.3s0-89.4-11.4-132.3zm-317.5 213.5V175.2l142.7 81.2-142.7 81.2z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;&#xA;    &#xA;    &#xA;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;jupyter-notebook&#34; class=&#34;content-heading&#34;&gt;Jupyter Notebook&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;You can find the Jupyter notebook and the datasets for this post &lt;a href=&#34;https://gitlab.com/frankRi89/blog/-/tree/main/notebooks/london-bike-data&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>UK house price changes in real terms</title>
      <link>https://staticnotes.org/posts/uk-house-prices/</link>
      <pubDate>Sun, 11 Jan 2026 00:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/uk-house-prices/</guid>
      <description>&lt;p&gt;This post is a response to a newspaper article I read this morning. Every month the FT is reporting on how the housing market in the UK is performing as people love to talk about it:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;UK house prices rise less than expected in 2025 as growth slows&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;UK house prices rose by 0.6 per cent in 2025 after a slowdown at the end of the year, according to lender Nationwide. [&amp;hellip;] Prices fell 0.4 per cent between November and December to an average of £271,068. Both figures were below analysts’ expectations of a 1.2 per cent annual rise and a 0.1 per cent month-on-month expansion.    &lt;em&gt;FT Weekend (02.01.2026)&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I am asking myself how useful this statistic is for the average reader, especially for a reader who wants to buy or sell a property.&lt;/p&gt;&#xA;&lt;p&gt;Two issues are immediately obvious:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The average yearly house price change across all of the UK might not agree with the house price performance in the areas I live in or I want to move to. There are also differences by house type, e.g. flat vs. detached house vs. terraced house. Different types of property might even perform in opposite directions.&lt;/li&gt;&#xA;&lt;li&gt;British people often view property, at least partially, as an investment opportunity. However, in those cases it would help to at least report the real (inflation-adjusted) house price change, not just the nominal change. An increase of 0.6% in nominal house prices sounds different when one doesn&amp;rsquo;t mention that inflation in 2025 was around 3.6% (UK CPI). Meanwhile other forms of investments did quite well. The FTSE 100 nominally returned 21.4% (which to be fair was a positive outlier this year compared to an average of 6% over the last 10 years).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Fortunately, it is not that difficult to compute real house prices more closely to my situation. The raw data is openly available via API:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The HM Land Registry registers the ownership of property in the UK and provides aggregate monthly data of the average transactions by region and property type.&lt;/li&gt;&#xA;&lt;li&gt;The Office for National Statistics (ONS) provides monthly inflation data (CPI) for the UK.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;So, in this post I want to compute and visualise how real flat and detached house prices in specific areas performed both nominally and in real terms.&lt;/p&gt;&#xA;&lt;h2 id=&#34;querying-the-housing-price-data&#34; class=&#34;content-heading&#34;&gt;Querying the housing price data&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I am using the UK House Price Index of the Land Registry API:&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;http://landregistry.data.gov.uk/data/ukhpi/region&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;http://landregistry.data.gov.uk/data/ukhpi/region&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;This allows me to query the monthly average house price value for different regions and property types. Important to note here is that this data is based on the successful property transactions in a region which we use here as an approximation of the average value of similar properties in the region (that were or weren&amp;rsquo;t sold).&lt;/p&gt;&#xA;&lt;p&gt;I am based in London and interested in how the housing market performs close to me or areas that I am interested in living in. So I will query the data for all London boroughs as well as some South England regions around London: Kent, Surrey, Buckinghamshire, and Oxfordshire.&lt;/p&gt;&#xA;&lt;p&gt;I then resample the monthly data to quarterly data by taking the mean across the 3 months of a quarter.&lt;/p&gt;&#xA;&lt;p&gt;I then store all the data in parquet files. You can find them &lt;a href=&#34;https://gitlab.com/frankRi89/blog/-/tree/601de34ababe1dc8d3a4aaaeb30a6bbb740de3b4/notebooks/uk-house-prices&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;inspecting-the-data&#34; class=&#34;content-heading&#34;&gt;Inspecting the data&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s have a look at how the data is stored in the file:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pandas&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pd&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;warnings&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;plt&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set_option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;display.float_format&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%.2f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;warnings&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;simplefilter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;always&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;category&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;UserWarning&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Here I am loading the file for the different counties that I am interested in:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_regions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;./data/uk_house_prices.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_regions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;is_london_borough&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_regions&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sample&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ignore_index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;Quarter&lt;/th&gt;&#xA;      &lt;th&gt;Region&lt;/th&gt;&#xA;      &lt;th&gt;Price&lt;/th&gt;&#xA;      &lt;th&gt;PropertyType&lt;/th&gt;&#xA;      &lt;th&gt;is_london_borough&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;2023Q4&lt;/td&gt;&#xA;      &lt;td&gt;Surrey&lt;/td&gt;&#xA;      &lt;td&gt;517233.67&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;False&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;2011Q3&lt;/td&gt;&#xA;      &lt;td&gt;Kent&lt;/td&gt;&#xA;      &lt;td&gt;192827.67&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;False&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;2014Q2&lt;/td&gt;&#xA;      &lt;td&gt;Oxfordshire&lt;/td&gt;&#xA;      &lt;td&gt;277195.00&lt;/td&gt;&#xA;      &lt;td&gt;Semi_detached&lt;/td&gt;&#xA;      &lt;td&gt;False&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;2013Q4&lt;/td&gt;&#xA;      &lt;td&gt;London&lt;/td&gt;&#xA;      &lt;td&gt;415838.00&lt;/td&gt;&#xA;      &lt;td&gt;Semi_detached&lt;/td&gt;&#xA;      &lt;td&gt;False&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;2021Q3&lt;/td&gt;&#xA;      &lt;td&gt;Buckinghamshire&lt;/td&gt;&#xA;      &lt;td&gt;431147.67&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;False&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;and here I am loading the file for the London boroughs:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_boroughs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;./data/london_borough_prices.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_boroughs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;is_london_borough&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_boroughs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sample&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ignore_index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;Quarter&lt;/th&gt;&#xA;      &lt;th&gt;Region&lt;/th&gt;&#xA;      &lt;th&gt;Price&lt;/th&gt;&#xA;      &lt;th&gt;PropertyType&lt;/th&gt;&#xA;      &lt;th&gt;is_london_borough&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;2020Q4&lt;/td&gt;&#xA;      &lt;td&gt;Hillingdon&lt;/td&gt;&#xA;      &lt;td&gt;406610.67&lt;/td&gt;&#xA;      &lt;td&gt;Terraced&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;2024Q4&lt;/td&gt;&#xA;      &lt;td&gt;Redbridge&lt;/td&gt;&#xA;      &lt;td&gt;490087.67&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;2017Q2&lt;/td&gt;&#xA;      &lt;td&gt;Lewisham&lt;/td&gt;&#xA;      &lt;td&gt;910228.33&lt;/td&gt;&#xA;      &lt;td&gt;Detached&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;2011Q3&lt;/td&gt;&#xA;      &lt;td&gt;Islington&lt;/td&gt;&#xA;      &lt;td&gt;369223.67&lt;/td&gt;&#xA;      &lt;td&gt;Flat&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;2010Q3&lt;/td&gt;&#xA;      &lt;td&gt;Enfield&lt;/td&gt;&#xA;      &lt;td&gt;661067.33&lt;/td&gt;&#xA;      &lt;td&gt;Detached&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;You can see that the dataset shows the average quarterly housing transaction values by region. The column &lt;code&gt;PropertyType&lt;/code&gt; shows what type of property was sold (Flat, Terraced, Detached, Semi_detached).&lt;/p&gt;&#xA;&lt;h2 id=&#34;computing-real-house-prices&#34; class=&#34;content-heading&#34;&gt;Computing real house prices&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Next we adjust the nominal house prices from the &lt;em&gt;Land Registry&lt;/em&gt; for inflation and compute the real house prices in terms of &amp;ldquo;2025 pounds&amp;rdquo;.&#xA;I have queried the Office for National Statistics API to get the UK&amp;rsquo;s quarterly CPI data and stored it in a parquet file. I am loading this data here:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;cpi_df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;./data/cpi_data.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;cpi_df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tail&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;Quarter&lt;/th&gt;&#xA;      &lt;th&gt;CPI&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;146&lt;/th&gt;&#xA;      &lt;td&gt;2024Q3&lt;/td&gt;&#xA;      &lt;td&gt;134.10&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;147&lt;/th&gt;&#xA;      &lt;td&gt;2024Q4&lt;/td&gt;&#xA;      &lt;td&gt;135.20&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;148&lt;/th&gt;&#xA;      &lt;td&gt;2025Q1&lt;/td&gt;&#xA;      &lt;td&gt;136.00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;149&lt;/th&gt;&#xA;      &lt;td&gt;2025Q2&lt;/td&gt;&#xA;      &lt;td&gt;138.50&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;150&lt;/th&gt;&#xA;      &lt;td&gt;2025Q3&lt;/td&gt;&#xA;      &lt;td&gt;139.20&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;With the consumer price index, we can compute the real price of housing. This real price answers the question: &amp;ldquo;How much was the property worth in last quarter&amp;rsquo;s pounds?&amp;rdquo; If you experienced inflation, your money is worth less, and you will need to pay more for the same house in today&amp;rsquo;s money terms. If you experienced deflation, your money is worth more, and you will need to pay less for a house in today&amp;rsquo;s terms (all else equal).&lt;/p&gt;&#xA;&lt;p&gt;The formula to compute the real house price in terms of the current CPI:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;real_price_current = nominal_price_t * (CPI_current / CPI_t)&lt;/code&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Merging the dataframes here to do real price calculation in one step&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;concat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df_regions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df_boroughs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Get the most recent CPI value&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;current_cpi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cpi_df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;CPI&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iloc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;latest_quarter&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cpi_df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Quarter&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iloc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Merge CPI df with house prices df&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;merge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cpi_df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Quarter&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;how&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;left&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# For quarters without CPI data yet, use the most recent CPI&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;CPI&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;CPI&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fillna&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;current_cpi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Calculate real prices using above formula &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;RealPrice&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Price&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;current_cpi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;CPI&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sample&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ignore_index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;Quarter&lt;/th&gt;&#xA;      &lt;th&gt;Region&lt;/th&gt;&#xA;      &lt;th&gt;Price&lt;/th&gt;&#xA;      &lt;th&gt;PropertyType&lt;/th&gt;&#xA;      &lt;th&gt;is_london_borough&lt;/th&gt;&#xA;      &lt;th&gt;CPI&lt;/th&gt;&#xA;      &lt;th&gt;RealPrice&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;2012Q3&lt;/td&gt;&#xA;      &lt;td&gt;City Of Westminster&lt;/td&gt;&#xA;      &lt;td&gt;2138137.67&lt;/td&gt;&#xA;      &lt;td&gt;Semi_detached&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;      &lt;td&gt;96.10&lt;/td&gt;&#xA;      &lt;td&gt;3097073.50&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;2011Q3&lt;/td&gt;&#xA;      &lt;td&gt;Croydon&lt;/td&gt;&#xA;      &lt;td&gt;280930.00&lt;/td&gt;&#xA;      &lt;td&gt;Semi_detached&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;      &lt;td&gt;93.80&lt;/td&gt;&#xA;      &lt;td&gt;416902.52&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;2016Q3&lt;/td&gt;&#xA;      &lt;td&gt;Bromley&lt;/td&gt;&#xA;      &lt;td&gt;898828.67&lt;/td&gt;&#xA;      &lt;td&gt;Detached&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;      &lt;td&gt;100.90&lt;/td&gt;&#xA;      &lt;td&gt;1240009.42&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;2017Q4&lt;/td&gt;&#xA;      &lt;td&gt;Ealing&lt;/td&gt;&#xA;      &lt;td&gt;1160573.67&lt;/td&gt;&#xA;      &lt;td&gt;Detached&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;      &lt;td&gt;104.60&lt;/td&gt;&#xA;      &lt;td&gt;1544472.80&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;2025Q2&lt;/td&gt;&#xA;      &lt;td&gt;City Of London&lt;/td&gt;&#xA;      &lt;td&gt;792392.33&lt;/td&gt;&#xA;      &lt;td&gt;Flat&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;      &lt;td&gt;138.50&lt;/td&gt;&#xA;      &lt;td&gt;796397.20&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;As you can see we now have the column &lt;code&gt;RealPrice&lt;/code&gt; which gives us the mean house price transaction per quarter and region in real terms. Now we can visualise the data to finally see what happened.&lt;/p&gt;&#xA;&lt;h2 id=&#34;visualising-nominal-and-real-house-prices-over-time&#34; class=&#34;content-heading&#34;&gt;Visualising nominal and real house prices over time&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;My goal is to plot the nominal and real house prices over time. To keep things visually simpler on the charts I am only selecting a few London boroughs that I am interested in and only look at data since 2015. For London boroughs I am looking at Flats and Terraced houses and for the counties I am only looking at detached houses.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Quarter&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;2015Q1&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;copy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SELECTED_BOROUGHS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;Ealing&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;Hackney&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;Hammersmith And Fulham&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;Hounslow&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;Islington&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;Richmond Upon Thames&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;Wandsworth&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_boroughs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Region&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SELECTED_BOROUGHS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;PropertyType&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Flat&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Terraced&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]))]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;copy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_regions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;is_london_borough&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;PropertyType&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Detached&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;copy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;In the file &lt;code&gt;utils.py&lt;/code&gt; I added some code to create the plots and tables. You can safely skip this if not interested. Importing them here in the notebook:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;utils&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plot_prices_by_type&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;detached-houses-in-south-england-counties&#34; class=&#34;content-heading&#34;&gt;Detached Houses in South England Counties&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I am first looking at the house price performance of detached houses in five different English counties. I am plotting both the nominal prices (dashed line) and the real prices (solid line).&lt;/p&gt;&#xA;&lt;p&gt;I am also creating a table with the real price changes vs. 1 year ago, 2 years ago, 5 years ago, 10 years ago.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;fig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subplots&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;figsize&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;14&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plot_prices_by_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df_regions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Detached&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Price&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Detached Houses in South England counties&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/uk-house-prices/output_21_0.png&#34; alt=&#34;png&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;You can see that within the last 10 years most counties saw a decent increase in nominal terms and a decline in real house prices for detached properties. The only exception is Kent with a small real increase of 0.9%. London and Surrey both lost around 10% in real terms.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;regions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sorted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Region&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unique&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;gt_regions_flat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;df_regions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Detached&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;South England Counties&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;regions&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;gt_regions_flat&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div id=&#34;vuiiiwlslp&#34; style=&#34;padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;&#34;&gt;&#xA;&lt;style&gt;&#xA;#vuiiiwlslp table {&#xA;          font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe UI&#39;, Roboto, Oxygen, Ubuntu, Cantarell, &#39;Helvetica Neue&#39;, &#39;Fira Sans&#39;, &#39;Droid Sans&#39;, Arial, sans-serif;&#xA;          -webkit-font-smoothing: antialiased;&#xA;          -moz-osx-font-smoothing: grayscale;&#xA;        }&#xA;&lt;p&gt;#vuiiiwlslp thead, tbody, tfoot, tr, td, th { border-style: none !important; }&#xA;tr { background-color: transparent !important; }&#xA;#vuiiiwlslp p { margin: 0 !important; padding: 0 !important; }&#xA;#vuiiiwlslp .gt_table { display: table !important; border-collapse: collapse !important; line-height: normal !important; margin-left: auto !important; margin-right: auto !important; color: #333333 !important; font-size: 12px !important; font-weight: normal !important; font-style: normal !important; background-color: #FFFFFF !important; width: auto !important; border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #A8A8A8 !important; border-right-style: none !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #A8A8A8 !important; border-left-style: none !important; border-left-width: 2px !important; border-left-color: #D3D3D3 !important; }&#xA;#vuiiiwlslp .gt_caption { padding-top: 4px !important; padding-bottom: 4px !important; }&#xA;#vuiiiwlslp .gt_title { color: #333333 !important; font-size: 125% !important; font-weight: initial !important; padding-top: 4px !important; padding-bottom: 4px !important; padding-left: 5px !important; padding-right: 5px !important; border-bottom-color: #FFFFFF !important; border-bottom-width: 0 !important; }&#xA;#vuiiiwlslp .gt_subtitle { color: #333333 !important; font-size: 85% !important; font-weight: initial !important; padding-top: 3px !important; padding-bottom: 5px !important; padding-left: 5px !important; padding-right: 5px !important; border-top-color: #FFFFFF !important; border-top-width: 0 !important; }&#xA;#vuiiiwlslp .gt_heading { background-color: #FFFFFF !important; text-align: center !important; border-bottom-color: #FFFFFF !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; }&#xA;#vuiiiwlslp .gt_bottom_border { border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; }&#xA;#vuiiiwlslp .gt_col_headings { border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; }&#xA;#vuiiiwlslp .gt_col_heading { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: normal !important; text-transform: inherit !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; vertical-align: bottom !important; padding-top: 5px !important; padding-bottom: 5px !important; padding-left: 5px !important; padding-right: 5px !important; overflow-x: hidden !important; }&#xA;#vuiiiwlslp .gt_column_spanner_outer { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: normal !important; text-transform: inherit !important; padding-top: 0 !important; padding-bottom: 0 !important; padding-left: 4px !important; padding-right: 4px !important; }&#xA;#vuiiiwlslp .gt_column_spanner_outer:first-child { padding-left: 0 !important; }&#xA;#vuiiiwlslp .gt_column_spanner_outer:last-child { padding-right: 0 !important; }&#xA;#vuiiiwlslp .gt_column_spanner { border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; vertical-align: bottom !important; padding-top: 5px !important; padding-bottom: 5px !important; overflow-x: hidden !important; display: inline-block !important; width: 100% !important; }&#xA;#vuiiiwlslp .gt_spanner_row { border-bottom-style: hidden !important; }&#xA;#vuiiiwlslp .gt_group_heading { padding-top: 8px !important; padding-bottom: 8px !important; padding-left: 5px !important; padding-right: 5px !important; color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; text-transform: inherit !important; border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; vertical-align: middle !important; text-align: left !important; }&#xA;#vuiiiwlslp .gt_empty_group_heading { padding: 0.5px !important; color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; vertical-align: middle !important; }&#xA;#vuiiiwlslp .gt_from_md&amp;gt; :first-child { margin-top: 0 !important; }&#xA;#vuiiiwlslp .gt_from_md&amp;gt; :last-child { margin-bottom: 0 !important; }&#xA;#vuiiiwlslp .gt_row { padding-top: 8px !important; padding-bottom: 8px !important; padding-left: 5px !important; padding-right: 5px !important; margin: 10px !important; border-top-style: solid !important; border-top-width: 1px !important; border-top-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; vertical-align: middle !important; overflow-x: hidden !important; }&#xA;#vuiiiwlslp .gt_stub { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; text-transform: inherit !important; border-right-style: solid !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; padding-left: 5px !important; padding-right: 5px !important; }&#xA;#vuiiiwlslp .gt_stub_row_group { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; text-transform: inherit !important; border-right-style: solid !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; padding-left: 5px !important; padding-right: 5px !important; vertical-align: top !important; }&#xA;#vuiiiwlslp .gt_row_group_first td { border-top-width: 2px !important; }&#xA;#vuiiiwlslp .gt_row_group_first th { border-top-width: 2px !important; }&#xA;#vuiiiwlslp .gt_striped { color: #333333 !important; background-color: #F4F4F4 !important; }&#xA;#vuiiiwlslp .gt_table_body { border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; }&#xA;#vuiiiwlslp .gt_grand_summary_row { color: #333333 !important; background-color: #FFFFFF !important; text-transform: inherit !important; padding-top: 8px !important; padding-bottom: 8px !important; padding-left: 5px !important; padding-right: 5px !important; }&#xA;#vuiiiwlslp .gt_first_grand_summary_row_bottom { border-top-style: double !important; border-top-width: 6px !important; border-top-color: #D3D3D3 !important; }&#xA;#vuiiiwlslp .gt_last_grand_summary_row_top { border-bottom-style: double !important; border-bottom-width: 6px !important; border-bottom-color: #D3D3D3 !important; }&#xA;#vuiiiwlslp .gt_sourcenotes { color: #333333 !important; background-color: #FFFFFF !important; border-bottom-style: none !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 2px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; }&#xA;#vuiiiwlslp .gt_sourcenote { font-size: 90% !important; padding-top: 4px !important; padding-bottom: 4px !important; padding-left: 5px !important; padding-right: 5px !important; text-align: left !important; }&#xA;#vuiiiwlslp .gt_left { text-align: left !important; }&#xA;#vuiiiwlslp .gt_center { text-align: center !important; }&#xA;#vuiiiwlslp .gt_right { text-align: right !important; font-variant-numeric: tabular-nums !important; }&#xA;#vuiiiwlslp .gt_font_normal { font-weight: normal !important; }&#xA;#vuiiiwlslp .gt_font_bold { font-weight: bold !important; }&#xA;#vuiiiwlslp .gt_font_italic { font-style: italic !important; }&#xA;#vuiiiwlslp .gt_super { font-size: 65% !important; }&#xA;#vuiiiwlslp .gt_footnote_marks { font-size: 75% !important; vertical-align: 0.4em !important; position: initial !important; }&#xA;#vuiiiwlslp .gt_asterisk { font-size: 100% !important; vertical-align: 0 !important; }&lt;/p&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table class=&#34;gt_table&#34; data-quarto-disable-processing=&#34;false&#34; data-quarto-bootstrap=&#34;false&#34;&gt;&#xA;&lt;thead&gt;&#xA;  &lt;tr class=&#34;gt_heading&#34;&gt;&#xA;    &lt;td colspan=&#34;11&#34; class=&#34;gt_heading gt_title gt_font_normal&#34;&gt;South England Counties&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr class=&#34;gt_heading&#34;&gt;&#xA;    &lt;td colspan=&#34;11&#34; class=&#34;gt_heading gt_subtitle gt_font_normal gt_bottom_border&#34;&gt;Detached properties - Real prices (CPI-adjusted) - Q4 2025 vs 1, 2, 5, 10 years ago&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;&lt;tr class=&#34;gt_col_headings gt_spanner_row&#34;&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_left&#34; rowspan=&#34;2&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;&#34;&gt;&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2025-(Current)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2025 (Current)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2024-(1y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2024 (1y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2023-(2y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2023 (2y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2020-(5y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2020 (5y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2015-(10y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2015 (10y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr class=&#34;gt_col_headings&#34;&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2025-(Current)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2025-(Current)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2024-(1y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2024-(1y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2023-(2y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2023-(2y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2020-(5y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2020-(5y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2015-(10y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2015-(10y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&lt;tbody class=&#34;gt_table_body&#34;&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Buckinghamshire&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;853,221&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;883,178&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ecb4b1;&#34; class=&#34;gt_row gt_right&#34;&gt;−3.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;894,115&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ebaeab;&#34; class=&#34;gt_row gt_right&#34;&gt;−4.6&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;974,110&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e58882;&#34; class=&#34;gt_row gt_right&#34;&gt;−12.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;924,706&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e99f9b;&#34; class=&#34;gt_row gt_right&#34;&gt;−7.7&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Kent&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;605,363&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;620,638&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #edb9b6;&#34; class=&#34;gt_row gt_right&#34;&gt;−2.5&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;633,552&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ebafac;&#34; class=&#34;gt_row gt_right&#34;&gt;−4.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;692,871&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e58681;&#34; class=&#34;gt_row gt_right&#34;&gt;−12.6&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;599,898&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #f0cac8;&#34; class=&#34;gt_row gt_right&#34;&gt;0.9&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;London&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,132,911&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,178,785&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ecb2af;&#34; class=&#34;gt_row gt_right&#34;&gt;−3.9&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,179,862&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ecb1ae;&#34; class=&#34;gt_row gt_right&#34;&gt;−4.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,331,199&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e37b76;&#34; class=&#34;gt_row gt_right&#34;&gt;−14.9&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,265,328&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e7918d;&#34; class=&#34;gt_row gt_right&#34;&gt;−10.5&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Oxfordshire&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;680,124&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;675,726&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #f0c8c6;&#34; class=&#34;gt_row gt_right&#34;&gt;0.7&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;676,613&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc8c6;&#34; class=&#34;gt_row gt_right&#34;&gt;0.5&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;757,910&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e7928e;&#34; class=&#34;gt_row gt_right&#34;&gt;−10.3&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;723,218&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #eaa8a4;&#34; class=&#34;gt_row gt_right&#34;&gt;−6.0&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Surrey&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;975,634&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,007,309&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ecb6b3;&#34; class=&#34;gt_row gt_right&#34;&gt;−3.1&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,023,827&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ebaeab;&#34; class=&#34;gt_row gt_right&#34;&gt;−4.7&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,118,116&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e58681;&#34; class=&#34;gt_row gt_right&#34;&gt;−12.7&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,083,197&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e7948f;&#34; class=&#34;gt_row gt_right&#34;&gt;−9.9&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;flats-in-london-boroughs&#34; class=&#34;content-heading&#34;&gt;Flats in London Boroughs&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Next, I am looking at flats in London. Again I am plotting nominal and real quarterly prices for selected London boroughs and create a table with the corresponding numbers.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;fig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subplots&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;figsize&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;14&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plot_prices_by_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df_boroughs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Flat&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Price&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Flats in selected London boroughs&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/uk-house-prices/output_25_0.png&#34; alt=&#34;png&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Both the chart and the table show somewhat stable or slightly increasing nominal prices, but drastic reductions in real prices. Both Hammersmith/Fulham and Wandsworth are down about 30% in real terms since 2015. Moreover compared to last year and two years ago we still see price declines in real terms.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;regions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sorted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Region&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unique&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;gt_regions_flat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;df_boroughs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Flat&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;Selected London Boroughs&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;regions&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;gt_regions_flat&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div id=&#34;zldtaermwk&#34; style=&#34;padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;&#34;&gt;&#xA;&lt;style&gt;&#xA;#zldtaermwk table {&#xA;          font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe UI&#39;, Roboto, Oxygen, Ubuntu, Cantarell, &#39;Helvetica Neue&#39;, &#39;Fira Sans&#39;, &#39;Droid Sans&#39;, Arial, sans-serif;&#xA;          -webkit-font-smoothing: antialiased;&#xA;          -moz-osx-font-smoothing: grayscale;&#xA;        }&#xA;&lt;p&gt;#zldtaermwk thead, tbody, tfoot, tr, td, th { border-style: none !important; }&#xA;tr { background-color: transparent !important; }&#xA;#zldtaermwk p { margin: 0 !important; padding: 0 !important; }&#xA;#zldtaermwk .gt_table { display: table !important; border-collapse: collapse !important; line-height: normal !important; margin-left: auto !important; margin-right: auto !important; color: #333333 !important; font-size: 12px !important; font-weight: normal !important; font-style: normal !important; background-color: #FFFFFF !important; width: auto !important; border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #A8A8A8 !important; border-right-style: none !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #A8A8A8 !important; border-left-style: none !important; border-left-width: 2px !important; border-left-color: #D3D3D3 !important; }&#xA;#zldtaermwk .gt_caption { padding-top: 4px !important; padding-bottom: 4px !important; }&#xA;#zldtaermwk .gt_title { color: #333333 !important; font-size: 125% !important; font-weight: initial !important; padding-top: 4px !important; padding-bottom: 4px !important; padding-left: 5px !important; padding-right: 5px !important; border-bottom-color: #FFFFFF !important; border-bottom-width: 0 !important; }&#xA;#zldtaermwk .gt_subtitle { color: #333333 !important; font-size: 85% !important; font-weight: initial !important; padding-top: 3px !important; padding-bottom: 5px !important; padding-left: 5px !important; padding-right: 5px !important; border-top-color: #FFFFFF !important; border-top-width: 0 !important; }&#xA;#zldtaermwk .gt_heading { background-color: #FFFFFF !important; text-align: center !important; border-bottom-color: #FFFFFF !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; }&#xA;#zldtaermwk .gt_bottom_border { border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; }&#xA;#zldtaermwk .gt_col_headings { border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; }&#xA;#zldtaermwk .gt_col_heading { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: normal !important; text-transform: inherit !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; vertical-align: bottom !important; padding-top: 5px !important; padding-bottom: 5px !important; padding-left: 5px !important; padding-right: 5px !important; overflow-x: hidden !important; }&#xA;#zldtaermwk .gt_column_spanner_outer { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: normal !important; text-transform: inherit !important; padding-top: 0 !important; padding-bottom: 0 !important; padding-left: 4px !important; padding-right: 4px !important; }&#xA;#zldtaermwk .gt_column_spanner_outer:first-child { padding-left: 0 !important; }&#xA;#zldtaermwk .gt_column_spanner_outer:last-child { padding-right: 0 !important; }&#xA;#zldtaermwk .gt_column_spanner { border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; vertical-align: bottom !important; padding-top: 5px !important; padding-bottom: 5px !important; overflow-x: hidden !important; display: inline-block !important; width: 100% !important; }&#xA;#zldtaermwk .gt_spanner_row { border-bottom-style: hidden !important; }&#xA;#zldtaermwk .gt_group_heading { padding-top: 8px !important; padding-bottom: 8px !important; padding-left: 5px !important; padding-right: 5px !important; color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; text-transform: inherit !important; border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; vertical-align: middle !important; text-align: left !important; }&#xA;#zldtaermwk .gt_empty_group_heading { padding: 0.5px !important; color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; vertical-align: middle !important; }&#xA;#zldtaermwk .gt_from_md&amp;gt; :first-child { margin-top: 0 !important; }&#xA;#zldtaermwk .gt_from_md&amp;gt; :last-child { margin-bottom: 0 !important; }&#xA;#zldtaermwk .gt_row { padding-top: 8px !important; padding-bottom: 8px !important; padding-left: 5px !important; padding-right: 5px !important; margin: 10px !important; border-top-style: solid !important; border-top-width: 1px !important; border-top-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; vertical-align: middle !important; overflow-x: hidden !important; }&#xA;#zldtaermwk .gt_stub { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; text-transform: inherit !important; border-right-style: solid !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; padding-left: 5px !important; padding-right: 5px !important; }&#xA;#zldtaermwk .gt_stub_row_group { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; text-transform: inherit !important; border-right-style: solid !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; padding-left: 5px !important; padding-right: 5px !important; vertical-align: top !important; }&#xA;#zldtaermwk .gt_row_group_first td { border-top-width: 2px !important; }&#xA;#zldtaermwk .gt_row_group_first th { border-top-width: 2px !important; }&#xA;#zldtaermwk .gt_striped { color: #333333 !important; background-color: #F4F4F4 !important; }&#xA;#zldtaermwk .gt_table_body { border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; }&#xA;#zldtaermwk .gt_grand_summary_row { color: #333333 !important; background-color: #FFFFFF !important; text-transform: inherit !important; padding-top: 8px !important; padding-bottom: 8px !important; padding-left: 5px !important; padding-right: 5px !important; }&#xA;#zldtaermwk .gt_first_grand_summary_row_bottom { border-top-style: double !important; border-top-width: 6px !important; border-top-color: #D3D3D3 !important; }&#xA;#zldtaermwk .gt_last_grand_summary_row_top { border-bottom-style: double !important; border-bottom-width: 6px !important; border-bottom-color: #D3D3D3 !important; }&#xA;#zldtaermwk .gt_sourcenotes { color: #333333 !important; background-color: #FFFFFF !important; border-bottom-style: none !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 2px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; }&#xA;#zldtaermwk .gt_sourcenote { font-size: 90% !important; padding-top: 4px !important; padding-bottom: 4px !important; padding-left: 5px !important; padding-right: 5px !important; text-align: left !important; }&#xA;#zldtaermwk .gt_left { text-align: left !important; }&#xA;#zldtaermwk .gt_center { text-align: center !important; }&#xA;#zldtaermwk .gt_right { text-align: right !important; font-variant-numeric: tabular-nums !important; }&#xA;#zldtaermwk .gt_font_normal { font-weight: normal !important; }&#xA;#zldtaermwk .gt_font_bold { font-weight: bold !important; }&#xA;#zldtaermwk .gt_font_italic { font-style: italic !important; }&#xA;#zldtaermwk .gt_super { font-size: 65% !important; }&#xA;#zldtaermwk .gt_footnote_marks { font-size: 75% !important; vertical-align: 0.4em !important; position: initial !important; }&#xA;#zldtaermwk .gt_asterisk { font-size: 100% !important; vertical-align: 0 !important; }&lt;/p&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table class=&#34;gt_table&#34; data-quarto-disable-processing=&#34;false&#34; data-quarto-bootstrap=&#34;false&#34;&gt;&#xA;&lt;thead&gt;&#xA;  &lt;tr class=&#34;gt_heading&#34;&gt;&#xA;    &lt;td colspan=&#34;11&#34; class=&#34;gt_heading gt_title gt_font_normal&#34;&gt;Selected London Boroughs&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr class=&#34;gt_heading&#34;&gt;&#xA;    &lt;td colspan=&#34;11&#34; class=&#34;gt_heading gt_subtitle gt_font_normal gt_bottom_border&#34;&gt;Flat properties - Real prices (CPI-adjusted) - Q4 2025 vs 1, 2, 5, 10 years ago&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;&lt;tr class=&#34;gt_col_headings gt_spanner_row&#34;&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_left&#34; rowspan=&#34;2&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;&#34;&gt;&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2025-(Current)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2025 (Current)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2024-(1y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2024 (1y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2023-(2y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2023 (2y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2020-(5y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2020 (5y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2015-(10y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2015 (10y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr class=&#34;gt_col_headings&#34;&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2025-(Current)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2025-(Current)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2024-(1y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2024-(1y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2023-(2y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2023-(2y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2020-(5y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2020-(5y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2015-(10y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2015-(10y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&lt;tbody class=&#34;gt_table_body&#34;&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Ealing&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;404,408&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;419,269&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ecb4b1;&#34; class=&#34;gt_row gt_right&#34;&gt;−3.5&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;419,733&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ecb3b0;&#34; class=&#34;gt_row gt_right&#34;&gt;−3.7&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;489,258&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e16f69;&#34; class=&#34;gt_row gt_right&#34;&gt;−17.3&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;521,670&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #dd554e;&#34; class=&#34;gt_row gt_right&#34;&gt;−22.5&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Hackney&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;546,932&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;554,931&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #eebebc;&#34; class=&#34;gt_row gt_right&#34;&gt;−1.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;583,301&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #eaa6a3;&#34; class=&#34;gt_row gt_right&#34;&gt;−6.2&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;685,095&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #df615a;&#34; class=&#34;gt_row gt_right&#34;&gt;−20.2&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;667,622&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e16b65;&#34; class=&#34;gt_row gt_right&#34;&gt;−18.1&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Hammersmith And Fulham&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;577,801&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;639,856&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e79591;&#34; class=&#34;gt_row gt_right&#34;&gt;−9.7&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;707,815&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e06a63;&#34; class=&#34;gt_row gt_right&#34;&gt;−18.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;760,674&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #dc4e46;&#34; class=&#34;gt_row gt_right&#34;&gt;−24.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;883,098&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #808080;&#34; class=&#34;gt_row gt_right&#34;&gt;−34.6&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Hounslow&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;367,011&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;375,391&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #edbab7;&#34; class=&#34;gt_row gt_right&#34;&gt;−2.2&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;373,890&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #eebcb9;&#34; class=&#34;gt_row gt_right&#34;&gt;−1.8&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;441,401&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e2716b;&#34; class=&#34;gt_row gt_right&#34;&gt;−16.9&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;419,450&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e58782;&#34; class=&#34;gt_row gt_right&#34;&gt;−12.5&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Islington&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;566,442&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;599,386&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ebaaa6;&#34; class=&#34;gt_row gt_right&#34;&gt;−5.5&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;623,593&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e89893;&#34; class=&#34;gt_row gt_right&#34;&gt;−9.2&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;725,791&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #dd5851;&#34; class=&#34;gt_row gt_right&#34;&gt;−22.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;771,081&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #da4139;&#34; class=&#34;gt_row gt_right&#34;&gt;−26.5&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Richmond Upon Thames&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;483,018&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;524,730&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e99e9a;&#34; class=&#34;gt_row gt_right&#34;&gt;−7.9&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;520,433&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e9a19e;&#34; class=&#34;gt_row gt_right&#34;&gt;−7.2&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;601,897&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #df635c;&#34; class=&#34;gt_row gt_right&#34;&gt;−19.8&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;633,108&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #dc4f48;&#34; class=&#34;gt_row gt_right&#34;&gt;−23.7&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Wandsworth&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;540,034&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;568,240&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ebada9;&#34; class=&#34;gt_row gt_right&#34;&gt;−5.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;603,492&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e7918c;&#34; class=&#34;gt_row gt_right&#34;&gt;−10.5&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;715,552&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #db4b43;&#34; class=&#34;gt_row gt_right&#34;&gt;−24.5&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;761,426&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #FFFFFF; background-color: #d8352c;&#34; class=&#34;gt_row gt_right&#34;&gt;−29.1&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;terraced-houses-in-london-boroughs&#34; class=&#34;content-heading&#34;&gt;Terraced houses in London Boroughs&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Next, I am looking at terraced houses in the same London boroughs. My expectation is that they did better than flats, especially since they were more popular during the COVID pandemic, where people wanted a garden.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;fig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subplots&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;figsize&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;14&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plot_prices_by_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df_boroughs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Terraced&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Price&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Terraced houses in selected London boroughs&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/uk-house-prices/output_29_0.png&#34; alt=&#34;png&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Indeed, terraced houses did better in nominal terms with all of them up. Again in real terms we see price decreases over all considered comparison years (1,2,5,10). However, it is less drastic than for flats in the same locations.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;regions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sorted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Region&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unique&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;gt_regions_flat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;create_table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;df_boroughs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Terraced&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;Selected London Boroughs&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;regions&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;gt_regions_flat&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div id=&#34;ppuntbiqeb&#34; style=&#34;padding-left:0px;padding-right:0px;padding-top:10px;padding-bottom:10px;overflow-x:auto;overflow-y:auto;width:auto;height:auto;&#34;&gt;&#xA;&lt;style&gt;&#xA;#ppuntbiqeb table {&#xA;          font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe UI&#39;, Roboto, Oxygen, Ubuntu, Cantarell, &#39;Helvetica Neue&#39;, &#39;Fira Sans&#39;, &#39;Droid Sans&#39;, Arial, sans-serif;&#xA;          -webkit-font-smoothing: antialiased;&#xA;          -moz-osx-font-smoothing: grayscale;&#xA;        }&#xA;&lt;p&gt;#ppuntbiqeb thead, tbody, tfoot, tr, td, th { border-style: none !important; }&#xA;tr { background-color: transparent !important; }&#xA;#ppuntbiqeb p { margin: 0 !important; padding: 0 !important; }&#xA;#ppuntbiqeb .gt_table { display: table !important; border-collapse: collapse !important; line-height: normal !important; margin-left: auto !important; margin-right: auto !important; color: #333333 !important; font-size: 12px !important; font-weight: normal !important; font-style: normal !important; background-color: #FFFFFF !important; width: auto !important; border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #A8A8A8 !important; border-right-style: none !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #A8A8A8 !important; border-left-style: none !important; border-left-width: 2px !important; border-left-color: #D3D3D3 !important; }&#xA;#ppuntbiqeb .gt_caption { padding-top: 4px !important; padding-bottom: 4px !important; }&#xA;#ppuntbiqeb .gt_title { color: #333333 !important; font-size: 125% !important; font-weight: initial !important; padding-top: 4px !important; padding-bottom: 4px !important; padding-left: 5px !important; padding-right: 5px !important; border-bottom-color: #FFFFFF !important; border-bottom-width: 0 !important; }&#xA;#ppuntbiqeb .gt_subtitle { color: #333333 !important; font-size: 85% !important; font-weight: initial !important; padding-top: 3px !important; padding-bottom: 5px !important; padding-left: 5px !important; padding-right: 5px !important; border-top-color: #FFFFFF !important; border-top-width: 0 !important; }&#xA;#ppuntbiqeb .gt_heading { background-color: #FFFFFF !important; text-align: center !important; border-bottom-color: #FFFFFF !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; }&#xA;#ppuntbiqeb .gt_bottom_border { border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; }&#xA;#ppuntbiqeb .gt_col_headings { border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; }&#xA;#ppuntbiqeb .gt_col_heading { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: normal !important; text-transform: inherit !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; vertical-align: bottom !important; padding-top: 5px !important; padding-bottom: 5px !important; padding-left: 5px !important; padding-right: 5px !important; overflow-x: hidden !important; }&#xA;#ppuntbiqeb .gt_column_spanner_outer { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: normal !important; text-transform: inherit !important; padding-top: 0 !important; padding-bottom: 0 !important; padding-left: 4px !important; padding-right: 4px !important; }&#xA;#ppuntbiqeb .gt_column_spanner_outer:first-child { padding-left: 0 !important; }&#xA;#ppuntbiqeb .gt_column_spanner_outer:last-child { padding-right: 0 !important; }&#xA;#ppuntbiqeb .gt_column_spanner { border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; vertical-align: bottom !important; padding-top: 5px !important; padding-bottom: 5px !important; overflow-x: hidden !important; display: inline-block !important; width: 100% !important; }&#xA;#ppuntbiqeb .gt_spanner_row { border-bottom-style: hidden !important; }&#xA;#ppuntbiqeb .gt_group_heading { padding-top: 8px !important; padding-bottom: 8px !important; padding-left: 5px !important; padding-right: 5px !important; color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; text-transform: inherit !important; border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; vertical-align: middle !important; text-align: left !important; }&#xA;#ppuntbiqeb .gt_empty_group_heading { padding: 0.5px !important; color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; vertical-align: middle !important; }&#xA;#ppuntbiqeb .gt_from_md&amp;gt; :first-child { margin-top: 0 !important; }&#xA;#ppuntbiqeb .gt_from_md&amp;gt; :last-child { margin-bottom: 0 !important; }&#xA;#ppuntbiqeb .gt_row { padding-top: 8px !important; padding-bottom: 8px !important; padding-left: 5px !important; padding-right: 5px !important; margin: 10px !important; border-top-style: solid !important; border-top-width: 1px !important; border-top-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 1px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 1px !important; border-right-color: #D3D3D3 !important; vertical-align: middle !important; overflow-x: hidden !important; }&#xA;#ppuntbiqeb .gt_stub { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; text-transform: inherit !important; border-right-style: solid !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; padding-left: 5px !important; padding-right: 5px !important; }&#xA;#ppuntbiqeb .gt_stub_row_group { color: #333333 !important; background-color: #FFFFFF !important; font-size: 100% !important; font-weight: initial !important; text-transform: inherit !important; border-right-style: solid !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; padding-left: 5px !important; padding-right: 5px !important; vertical-align: top !important; }&#xA;#ppuntbiqeb .gt_row_group_first td { border-top-width: 2px !important; }&#xA;#ppuntbiqeb .gt_row_group_first th { border-top-width: 2px !important; }&#xA;#ppuntbiqeb .gt_striped { color: #333333 !important; background-color: #F4F4F4 !important; }&#xA;#ppuntbiqeb .gt_table_body { border-top-style: solid !important; border-top-width: 2px !important; border-top-color: #D3D3D3 !important; border-bottom-style: solid !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; }&#xA;#ppuntbiqeb .gt_grand_summary_row { color: #333333 !important; background-color: #FFFFFF !important; text-transform: inherit !important; padding-top: 8px !important; padding-bottom: 8px !important; padding-left: 5px !important; padding-right: 5px !important; }&#xA;#ppuntbiqeb .gt_first_grand_summary_row_bottom { border-top-style: double !important; border-top-width: 6px !important; border-top-color: #D3D3D3 !important; }&#xA;#ppuntbiqeb .gt_last_grand_summary_row_top { border-bottom-style: double !important; border-bottom-width: 6px !important; border-bottom-color: #D3D3D3 !important; }&#xA;#ppuntbiqeb .gt_sourcenotes { color: #333333 !important; background-color: #FFFFFF !important; border-bottom-style: none !important; border-bottom-width: 2px !important; border-bottom-color: #D3D3D3 !important; border-left-style: none !important; border-left-width: 2px !important; border-left-color: #D3D3D3 !important; border-right-style: none !important; border-right-width: 2px !important; border-right-color: #D3D3D3 !important; }&#xA;#ppuntbiqeb .gt_sourcenote { font-size: 90% !important; padding-top: 4px !important; padding-bottom: 4px !important; padding-left: 5px !important; padding-right: 5px !important; text-align: left !important; }&#xA;#ppuntbiqeb .gt_left { text-align: left !important; }&#xA;#ppuntbiqeb .gt_center { text-align: center !important; }&#xA;#ppuntbiqeb .gt_right { text-align: right !important; font-variant-numeric: tabular-nums !important; }&#xA;#ppuntbiqeb .gt_font_normal { font-weight: normal !important; }&#xA;#ppuntbiqeb .gt_font_bold { font-weight: bold !important; }&#xA;#ppuntbiqeb .gt_font_italic { font-style: italic !important; }&#xA;#ppuntbiqeb .gt_super { font-size: 65% !important; }&#xA;#ppuntbiqeb .gt_footnote_marks { font-size: 75% !important; vertical-align: 0.4em !important; position: initial !important; }&#xA;#ppuntbiqeb .gt_asterisk { font-size: 100% !important; vertical-align: 0 !important; }&lt;/p&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table class=&#34;gt_table&#34; data-quarto-disable-processing=&#34;false&#34; data-quarto-bootstrap=&#34;false&#34;&gt;&#xA;&lt;thead&gt;&#xA;  &lt;tr class=&#34;gt_heading&#34;&gt;&#xA;    &lt;td colspan=&#34;11&#34; class=&#34;gt_heading gt_title gt_font_normal&#34;&gt;Selected London Boroughs&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr class=&#34;gt_heading&#34;&gt;&#xA;    &lt;td colspan=&#34;11&#34; class=&#34;gt_heading gt_subtitle gt_font_normal gt_bottom_border&#34;&gt;Terraced properties - Real prices (CPI-adjusted) - Q4 2025 vs 1, 2, 5, 10 years ago&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;&lt;tr class=&#34;gt_col_headings gt_spanner_row&#34;&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_left&#34; rowspan=&#34;2&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;&#34;&gt;&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2025-(Current)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2025 (Current)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2024-(1y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2024 (1y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2023-(2y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2023 (2y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2020-(5y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2020 (5y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;  &lt;th class=&#34;gt_center gt_columns_top_border gt_column_spanner_outer&#34; rowspan=&#34;1&#34; colspan=&#34;2&#34; scope=&#34;colgroup&#34; id=&#34;2015-(10y-ago)&#34;&gt;&#xA;    &lt;span class=&#34;gt_column_spanner&#34;&gt;2015 (10y ago)&lt;/span&gt;&#xA;  &lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr class=&#34;gt_col_headings&#34;&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2025-(Current)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2025-(Current)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2024-(1y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2024-(1y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2023-(2y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2023-(2y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2020-(5y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2020-(5y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2015-(10y-ago)_Real&#34;&gt;Price (£)&lt;/th&gt;&#xA;  &lt;th class=&#34;gt_col_heading gt_columns_bottom_border gt_right&#34; rowspan=&#34;1&#34; colspan=&#34;1&#34; scope=&#34;col&#34; id=&#34;2015-(10y-ago)_RealChg&#34;&gt;%&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&lt;tbody class=&#34;gt_table_body&#34;&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Ealing&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;690,513&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;697,849&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #eec0be;&#34; class=&#34;gt_row gt_right&#34;&gt;−1.1&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;690,002&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc6c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.1&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;788,622&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e58782;&#34; class=&#34;gt_row gt_right&#34;&gt;−12.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;800,316&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e4817c;&#34; class=&#34;gt_row gt_right&#34;&gt;−13.7&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Hackney&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;972,274&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;966,520&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc8c6;&#34; class=&#34;gt_row gt_right&#34;&gt;0.6&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,006,975&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ecb4b1;&#34; class=&#34;gt_row gt_right&#34;&gt;−3.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,158,935&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e2756f;&#34; class=&#34;gt_row gt_right&#34;&gt;−16.1&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,073,030&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e79792;&#34; class=&#34;gt_row gt_right&#34;&gt;−9.4&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Hammersmith And Fulham&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,111,278&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,221,472&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e89894;&#34; class=&#34;gt_row gt_right&#34;&gt;−9.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,334,009&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e2726c;&#34; class=&#34;gt_row gt_right&#34;&gt;−16.7&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,392,109&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #df615a;&#34; class=&#34;gt_row gt_right&#34;&gt;−20.2&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,547,731&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #FFFFFF; background-color: #d83930;&#34; class=&#34;gt_row gt_right&#34;&gt;−28.2&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Hounslow&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;625,089&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;622,316&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc7c5;&#34; class=&#34;gt_row gt_right&#34;&gt;0.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;612,967&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #f1cfcd;&#34; class=&#34;gt_row gt_right&#34;&gt;2.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;704,956&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e68d88;&#34; class=&#34;gt_row gt_right&#34;&gt;−11.3&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;637,839&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #edbbb9;&#34; class=&#34;gt_row gt_right&#34;&gt;−2.0&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Islington&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,124,856&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,175,162&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ecb0ad;&#34; class=&#34;gt_row gt_right&#34;&gt;−4.3&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,214,208&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e9a19d;&#34; class=&#34;gt_row gt_right&#34;&gt;−7.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,380,766&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e06963;&#34; class=&#34;gt_row gt_right&#34;&gt;−18.5&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,380,624&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e06963;&#34; class=&#34;gt_row gt_right&#34;&gt;−18.5&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Richmond Upon Thames&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;890,118&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;935,936&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ebadaa;&#34; class=&#34;gt_row gt_right&#34;&gt;−4.9&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;918,218&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #edb6b3;&#34; class=&#34;gt_row gt_right&#34;&gt;−3.1&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,036,584&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e47f7a;&#34; class=&#34;gt_row gt_right&#34;&gt;−14.1&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,033,227&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e4807b;&#34; class=&#34;gt_row gt_right&#34;&gt;−13.9&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;  &lt;tr&gt;&#xA;    &lt;th class=&#34;gt_row gt_left gt_stub&#34;&gt;Wandsworth&lt;/th&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;965,788&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #efc5c3;&#34; class=&#34;gt_row gt_right&#34;&gt;0.0&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,000,163&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #ecb4b1;&#34; class=&#34;gt_row gt_right&#34;&gt;−3.4&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,050,418&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #e99d99;&#34; class=&#34;gt_row gt_right&#34;&gt;−8.1&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,214,261&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #df5f59;&#34; class=&#34;gt_row gt_right&#34;&gt;−20.5&lt;/td&gt;&#xA;    &lt;td class=&#34;gt_row gt_right&#34;&gt;&amp;#163;1,219,378&lt;/td&gt;&#xA;    &lt;td style=&#34;color: #000000; background-color: #de5e57;&#34; class=&#34;gt_row gt_right&#34;&gt;−20.8&lt;/td&gt;&#xA;  &lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;h1 id=&#34;winners-and-losers-in-real-terms-last-3-years&#34; class=&#34;content-heading&#34;&gt;Winners and Losers in real terms (last 3 years)&#xA;&lt;/h1&gt;&#xA;&lt;p&gt;Lastly I want to see how the housing market in the different London boroughs compares to each other. I am looking at the prices 3 years ago across all property types. (At first I wanted to use 5 years, but I wanted to stay clear of the COVID years which might introduce short-term anomalies into the result). I am comparing real prices even though for a relative comparison between boroughs nominal prices would be fine as well (they all experienced the same inflation).&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;selected&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;is_london_borough&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Quarter&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2025Q4&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2022Q4&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;PropertyType&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;All&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_wide&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;selected&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pivot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Region&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;PropertyType&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;columns&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Quarter&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;RealPrice&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reset_index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_wide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;%_real_price_change&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df_wide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2025Q4&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df_wide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2022Q4&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df_wide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2022Q4&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_wide&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;%_real_price_change&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ascending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ignore_index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;Quarter&lt;/th&gt;&#xA;      &lt;th&gt;Region&lt;/th&gt;&#xA;      &lt;th&gt;PropertyType&lt;/th&gt;&#xA;      &lt;th&gt;2022Q4&lt;/th&gt;&#xA;      &lt;th&gt;2025Q4&lt;/th&gt;&#xA;      &lt;th&gt;%_real_price_change&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;Lewisham&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;529841.12&lt;/td&gt;&#xA;      &lt;td&gt;503542.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.05&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;Havering&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;479610.47&lt;/td&gt;&#xA;      &lt;td&gt;450760.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.06&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;Southwark&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;647219.21&lt;/td&gt;&#xA;      &lt;td&gt;607299.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.06&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;Waltham Forest&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;569427.61&lt;/td&gt;&#xA;      &lt;td&gt;533922.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.06&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;Haringey&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;697080.71&lt;/td&gt;&#xA;      &lt;td&gt;649650.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.07&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;5&lt;/th&gt;&#xA;      &lt;td&gt;Hackney&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;681376.13&lt;/td&gt;&#xA;      &lt;td&gt;627538.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.08&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;6&lt;/th&gt;&#xA;      &lt;td&gt;Hounslow&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;588525.22&lt;/td&gt;&#xA;      &lt;td&gt;540799.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.08&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;7&lt;/th&gt;&#xA;      &lt;td&gt;Sutton&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;493375.92&lt;/td&gt;&#xA;      &lt;td&gt;452726.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.08&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;8&lt;/th&gt;&#xA;      &lt;td&gt;Hillingdon&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;526316.99&lt;/td&gt;&#xA;      &lt;td&gt;482852.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.08&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;9&lt;/th&gt;&#xA;      &lt;td&gt;Barking And Dagenham&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;387895.94&lt;/td&gt;&#xA;      &lt;td&gt;354709.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.09&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;You can see that even the best-performing borough Lewisham saw decreasing real house prices of 5% in the last 3 years. Overall a lot of these top 10 boroughs are further outside of London and generally more affordable areas. Both Hackney and Southwark are more central, but have recently undergone gentrification which might have counteracted the price pressure in other central boroughs.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_wide&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;%_real_price_change&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ascending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ignore_index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tail&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;Quarter&lt;/th&gt;&#xA;      &lt;th&gt;Region&lt;/th&gt;&#xA;      &lt;th&gt;PropertyType&lt;/th&gt;&#xA;      &lt;th&gt;2022Q4&lt;/th&gt;&#xA;      &lt;th&gt;2025Q4&lt;/th&gt;&#xA;      &lt;th&gt;%_real_price_change&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;23&lt;/th&gt;&#xA;      &lt;td&gt;Barnet&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;706765.75&lt;/td&gt;&#xA;      &lt;td&gt;606006.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.14&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;24&lt;/th&gt;&#xA;      &lt;td&gt;Camden&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;928639.42&lt;/td&gt;&#xA;      &lt;td&gt;792454.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.15&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;25&lt;/th&gt;&#xA;      &lt;td&gt;Croydon&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;464581.92&lt;/td&gt;&#xA;      &lt;td&gt;393479.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.15&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;26&lt;/th&gt;&#xA;      &lt;td&gt;Lambeth&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;654875.76&lt;/td&gt;&#xA;      &lt;td&gt;550720.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.16&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;27&lt;/th&gt;&#xA;      &lt;td&gt;Hammersmith And Fulham&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;883837.60&lt;/td&gt;&#xA;      &lt;td&gt;741308.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.16&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;28&lt;/th&gt;&#xA;      &lt;td&gt;Wandsworth&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;834257.35&lt;/td&gt;&#xA;      &lt;td&gt;695867.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.17&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;29&lt;/th&gt;&#xA;      &lt;td&gt;Tower Hamlets&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;595217.88&lt;/td&gt;&#xA;      &lt;td&gt;470209.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.21&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;30&lt;/th&gt;&#xA;      &lt;td&gt;Kensington And Chelsea&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;1637183.90&lt;/td&gt;&#xA;      &lt;td&gt;1194726.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.27&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;31&lt;/th&gt;&#xA;      &lt;td&gt;City Of Westminster&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;1273329.16&lt;/td&gt;&#xA;      &lt;td&gt;889935.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.30&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;32&lt;/th&gt;&#xA;      &lt;td&gt;City Of London&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;993657.65&lt;/td&gt;&#xA;      &lt;td&gt;607399.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.39&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;Some of the worst-performing boroughs over the last 3 years are the City of London, Westminster, Kensington &amp;amp; Chelsea, and Hammersmith and Fulham, which are all very expensive &amp;lsquo;prestige&amp;rsquo; areas.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34; class=&#34;content-heading&#34;&gt;Conclusion&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;This analysis shows that a prospective home buyer or seller only gains limited information from a national-level house price statistic. Instead, I showed that there are, unsurprisingly, vast differences in price developments between property types and locations.&lt;/p&gt;&#xA;&lt;p&gt;Moreover, in real terms almost none of the considered regions saw increasing house prices over the last 10 years (notable exception: Kent).&lt;/p&gt;&#xA;&lt;h2 id=&#34;appendix&#34; class=&#34;content-heading&#34;&gt;Appendix&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Since someone asked, here are the real price changes compared to 3 years ago for all London boroughs:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_wide&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;%_real_price_change&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ascending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ignore_index&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;Quarter&lt;/th&gt;&#xA;      &lt;th&gt;Region&lt;/th&gt;&#xA;      &lt;th&gt;PropertyType&lt;/th&gt;&#xA;      &lt;th&gt;2022Q4&lt;/th&gt;&#xA;      &lt;th&gt;2025Q4&lt;/th&gt;&#xA;      &lt;th&gt;%_real_price_change&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;Lewisham&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;529841.12&lt;/td&gt;&#xA;      &lt;td&gt;503542.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.05&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;Havering&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;479610.47&lt;/td&gt;&#xA;      &lt;td&gt;450760.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.06&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;Southwark&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;647219.21&lt;/td&gt;&#xA;      &lt;td&gt;607299.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.06&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;Waltham Forest&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;569427.61&lt;/td&gt;&#xA;      &lt;td&gt;533922.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.06&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;Haringey&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;697080.71&lt;/td&gt;&#xA;      &lt;td&gt;649650.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.07&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;5&lt;/th&gt;&#xA;      &lt;td&gt;Hackney&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;681376.13&lt;/td&gt;&#xA;      &lt;td&gt;627538.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.08&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;6&lt;/th&gt;&#xA;      &lt;td&gt;Hounslow&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;588525.22&lt;/td&gt;&#xA;      &lt;td&gt;540799.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.08&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;7&lt;/th&gt;&#xA;      &lt;td&gt;Sutton&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;493375.92&lt;/td&gt;&#xA;      &lt;td&gt;452726.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.08&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;8&lt;/th&gt;&#xA;      &lt;td&gt;Hillingdon&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;526316.99&lt;/td&gt;&#xA;      &lt;td&gt;482852.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.08&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;9&lt;/th&gt;&#xA;      &lt;td&gt;Barking And Dagenham&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;387895.94&lt;/td&gt;&#xA;      &lt;td&gt;354709.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.09&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;10&lt;/th&gt;&#xA;      &lt;td&gt;Merton&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;677772.16&lt;/td&gt;&#xA;      &lt;td&gt;618798.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.09&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;11&lt;/th&gt;&#xA;      &lt;td&gt;Harrow&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;590633.55&lt;/td&gt;&#xA;      &lt;td&gt;538433.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.09&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;12&lt;/th&gt;&#xA;      &lt;td&gt;Bromley&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;581127.96&lt;/td&gt;&#xA;      &lt;td&gt;529749.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.09&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;13&lt;/th&gt;&#xA;      &lt;td&gt;Redbridge&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;524996.77&lt;/td&gt;&#xA;      &lt;td&gt;476764.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.09&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;14&lt;/th&gt;&#xA;      &lt;td&gt;Richmond Upon Thames&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;870795.06&lt;/td&gt;&#xA;      &lt;td&gt;785086.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.10&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;15&lt;/th&gt;&#xA;      &lt;td&gt;Enfield&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;533218.77&lt;/td&gt;&#xA;      &lt;td&gt;480183.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.10&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16&lt;/th&gt;&#xA;      &lt;td&gt;Bexley&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;456886.19&lt;/td&gt;&#xA;      &lt;td&gt;410002.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.10&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;17&lt;/th&gt;&#xA;      &lt;td&gt;Islington&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;757742.76&lt;/td&gt;&#xA;      &lt;td&gt;677305.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.11&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;18&lt;/th&gt;&#xA;      &lt;td&gt;Ealing&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;645069.13&lt;/td&gt;&#xA;      &lt;td&gt;572575.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.11&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;19&lt;/th&gt;&#xA;      &lt;td&gt;Greenwich&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;533193.50&lt;/td&gt;&#xA;      &lt;td&gt;472599.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.11&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;20&lt;/th&gt;&#xA;      &lt;td&gt;Brent&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;639480.63&lt;/td&gt;&#xA;      &lt;td&gt;558093.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.13&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;21&lt;/th&gt;&#xA;      &lt;td&gt;Kingston Upon Thames&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;657636.32&lt;/td&gt;&#xA;      &lt;td&gt;573489.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.13&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;22&lt;/th&gt;&#xA;      &lt;td&gt;Newham&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;471479.67&lt;/td&gt;&#xA;      &lt;td&gt;405808.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.14&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;23&lt;/th&gt;&#xA;      &lt;td&gt;Barnet&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;706765.75&lt;/td&gt;&#xA;      &lt;td&gt;606006.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.14&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;24&lt;/th&gt;&#xA;      &lt;td&gt;Camden&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;928639.42&lt;/td&gt;&#xA;      &lt;td&gt;792454.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.15&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;25&lt;/th&gt;&#xA;      &lt;td&gt;Croydon&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;464581.92&lt;/td&gt;&#xA;      &lt;td&gt;393479.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.15&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;26&lt;/th&gt;&#xA;      &lt;td&gt;Lambeth&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;654875.76&lt;/td&gt;&#xA;      &lt;td&gt;550720.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.16&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;27&lt;/th&gt;&#xA;      &lt;td&gt;Hammersmith And Fulham&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;883837.60&lt;/td&gt;&#xA;      &lt;td&gt;741308.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.16&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;28&lt;/th&gt;&#xA;      &lt;td&gt;Wandsworth&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;834257.35&lt;/td&gt;&#xA;      &lt;td&gt;695867.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.17&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;29&lt;/th&gt;&#xA;      &lt;td&gt;Tower Hamlets&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;595217.88&lt;/td&gt;&#xA;      &lt;td&gt;470209.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.21&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;30&lt;/th&gt;&#xA;      &lt;td&gt;Kensington And Chelsea&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;1637183.90&lt;/td&gt;&#xA;      &lt;td&gt;1194726.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.27&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;31&lt;/th&gt;&#xA;      &lt;td&gt;City Of Westminster&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;1273329.16&lt;/td&gt;&#xA;      &lt;td&gt;889935.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.30&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;32&lt;/th&gt;&#xA;      &lt;td&gt;City Of London&lt;/td&gt;&#xA;      &lt;td&gt;All&lt;/td&gt;&#xA;      &lt;td&gt;993657.65&lt;/td&gt;&#xA;      &lt;td&gt;607399.00&lt;/td&gt;&#xA;      &lt;td&gt;-0.39&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;h2 id=&#34;jupyter-notebook&#34; class=&#34;content-heading&#34;&gt;Jupyter Notebook&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;You can find the Jupyter notebook for this post &lt;a href=&#34;https://gitlab.com/frankRi89/blog/-/tree/main/notebooks/uk-house-prices&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Building a local data warehouse with DuckDB, dbt, and Superset</title>
      <link>https://staticnotes.org/posts/duckdb-dbt-superset/</link>
      <pubDate>Sun, 09 Mar 2025 15:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/duckdb-dbt-superset/</guid>
      <description>&lt;p&gt;In previous blog posts, I described two DuckDB use cases for data scientists and data engineers: &lt;a href=&#34;https://staticnotes.org/posts/duckdb-for-data-scientists/&#34; &#xA;&gt;Querying remote parquet files&#xA;&lt;/a&gt; and &lt;a href=&#34;https://staticnotes.org/posts/duckdb-large-datasets/&#34; &#xA;&gt;processing larger-than-memory datasets&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Now I want to explore if I can set up a local and open-source version of the analytics data stack that we use at my company. At work, we are using Snowflake, dbt cloud, and Google&amp;rsquo;s Looker which cost us several thousand EUR per month. I am going to use the following open-source tools in my local setup:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;/th&gt;&#xA;          &lt;th&gt;cloud&lt;/th&gt;&#xA;          &lt;th&gt;local&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;analytical database&lt;/td&gt;&#xA;          &lt;td&gt;snowflake&lt;/td&gt;&#xA;          &lt;td&gt;DuckDB&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;data modelling tool&lt;/td&gt;&#xA;          &lt;td&gt;dbt cloud&lt;/td&gt;&#xA;          &lt;td&gt;local dbt&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;dashboard tool&lt;/td&gt;&#xA;          &lt;td&gt;Looker&lt;/td&gt;&#xA;          &lt;td&gt;Apache Superset&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Figure 1 shows how the components work together.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/duckdb-dbt-superset/duckdb_dbt_superset_setup.png&#34; alt=&#34;Local data warehouse&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 1. Components of my local data warehouse stack.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;I will use a toy visualisation problem to demonstrate the setup. My goal is to load the race time dataset that I used in &lt;a href=&#34;https://staticnotes.org/posts/vatternrundan-results/&#34; &#xA;&gt;Data analysis: Vätternrundan 2024 results&#xA;&lt;/a&gt; into DuckDB. I then use dbt to create data models and Superset to create an interactive dashboard to visualise the data.&lt;/p&gt;&#xA;&lt;h2 id=&#34;loading-the-raw-data-into-duckdb&#34; class=&#34;content-heading&#34;&gt;Loading the raw data into DuckDB&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I want to use DuckDB for all data processing. Therefore, I will load the raw race time data into DuckDB.&lt;/p&gt;&#xA;&lt;p&gt;I start by installing DuckDB as my analytical database. Since I use homebrew as a package manager, I can run:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install duckdb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;I then create a persistent database (a file on my machine):&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;duckdb database.duckdb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;and create a new DuckDB table from the parquet file that contains the raw data.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vatternrundan&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;startnumber&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;city&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;country&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;start_time&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;results_vatternrundan24.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;To verify that everything works, I run:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;describe&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;table&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vatternrundan&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;┌─────────────┬─────────────┬─────────┬─────────┬─────────┬─────────┐&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;column_name&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;column_type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;extra&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;varchar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;varchar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;varchar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;varchar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;varchar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;varchar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;├─────────────┼─────────────┼─────────┼─────────┼─────────┼─────────┤&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;startnumber&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;BIGINT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;YES&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;city&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;VARCHAR&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;YES&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;country&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;VARCHAR&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;YES&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;BIGINT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;YES&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;start_time&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;VARCHAR&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;YES&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;│&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;└─────────────┴─────────────┴─────────┴─────────┴─────────┴─────────┘&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h2 id=&#34;setting-up-dbt-for-data-transformations&#34; class=&#34;content-heading&#34;&gt;Setting up dbt for data transformations&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I want to use dbt to create data models on top of the raw data. I start by creating a new poetry project to install dependencies:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry init&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry add duckdb-dbt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Then I initialise the dbt project &lt;code&gt;local_warehouse&lt;/code&gt; with&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry run dbt init local_warehouse&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Next, I configure dbt to use DuckDB as the data processing backend. In my work setup, this would point at a Snowflake instance instead. I point at the local database file in the dbt profiles file &lt;code&gt;profiles.yml&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;yml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;local_warehouse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;outputs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;dev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;duckdb&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;../duckdb/database.duckdb&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;dev&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;dbt-models&#34; class=&#34;content-heading&#34;&gt;dbt models&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I define the DuckDB table &lt;code&gt;vatternrundan&lt;/code&gt; as a dbt source in &lt;code&gt;sources.yml&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;yml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;sources&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;vatternrundan_db&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;main &lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;tables&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;vatternrundan&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;This means I can now refer to this raw data in dbt.&#xA;Moreover, I want to create two more models. One thin staging layer over the raw data &lt;code&gt;stg_vatternrundan.sql&lt;/code&gt;, and one refined model that aggregates the rider data by country &lt;code&gt;average_speed_by_country.sql&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The staging model is stored in the dbt project as &lt;code&gt;models/staging/stg_vatternrundan.sql&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;startnumber&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;int64&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;startnumber&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;city&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;varchar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;city&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;country&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;varchar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;country&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_microseconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;int64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;vatternrundan_db&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;vatternrundan&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;}}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;As you can see, I refer to the DuckDB source table, define the column types, and do some light conversions.&lt;/p&gt;&#xA;&lt;p&gt;The aggregation model is stored in &lt;code&gt;models/refined/average_speed_by_country.sql&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;speeds&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;startnumber&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;country&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;datepart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;hours&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;datepart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;minutes&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time_minutes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;315&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time_minutes&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;average_speed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;err&#34;&gt;{{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;ref&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;stg_vatternrundan&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;}}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;country&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_riders&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;average_speed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;average_speed_of_country&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;speeds&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;country&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;order&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;average_speed_of_country&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;desc&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;I use this dbt model to compute the average rider speed for every country in the dataset.&lt;/p&gt;&#xA;&lt;p&gt;Now that I have defined my dbt models, I configure dbt to run them by adding the following to &lt;code&gt;dbt_project.yml&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;yml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;models&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;local_warehouse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;staging&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;+schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;staging&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;+materialized&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;table&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;refined&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;+schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;refined&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;+materialized&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;table&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;This tells dbt how to materialise the dbt models in DuckDB. So let&amp;rsquo;s run dbt to build the models:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry run dbt run --profiles-dir&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;check-tables-were-created&#34; class=&#34;content-heading&#34;&gt;Check tables were created&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I can verify in DuckDB that these tables have been created&lt;/p&gt;&#xA;&lt;p&gt;Run&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;duckdb database.duckdb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;followed by:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;show&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tables&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;which should now show:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;database.main_staging.stg_vatternrundan&#xA;database.main_refined.average_speed_by_country&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;h2 id=&#34;superset-for-data-analytics-dashboards&#34; class=&#34;content-heading&#34;&gt;Superset for data analytics dashboards&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;After modelling my data, I want to create a dashboard and visualise the data. I use Apache Superset as my dashboarding tool. Superset works with many analytical databases. However, setting it up to work with DuckDB is a bit clunky and I had to troubleshoot quite a bit.&lt;/p&gt;&#xA;&lt;h3 id=&#34;install-superset-with-duckdb-support&#34; class=&#34;content-heading&#34;&gt;Install Superset with DuckDB support&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I follow the &lt;a href=&#34;https://superset.apache.org/docs/quickstart/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Quickstart Guide&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; with some modifications. First, I download the git repository and checkout the last tagged commit:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/apache/superset&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; superset&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git checkout tags/4.1.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;I need to make two modifications before building the container.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install &lt;code&gt;duckdb-engine&lt;/code&gt; inside the container. This allows us later to select DuckDB as a database in Superset. To do this, add&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;yml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;l&#34;&gt;RUN pip install duckdb-engine&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;to the &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;I need to make the DuckDB database file available in the Docker container. I add its path as a volume. Modify &lt;code&gt;docker-compose-image-tag.yml&lt;/code&gt;:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;yml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;superset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;l&#34;&gt;...]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;./docker:/app/docker&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;superset_home:/app/superset_home&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;&amp;lt;local-machine-path-to-duckdb-database&amp;gt;:/app/duckdb  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;and force the Superset container to build from the Dockerfile and not from the image:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;yml&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;superset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;l&#34;&gt;...]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;build&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;dockerfile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Dockerfile&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;#   image: apache/superset: comment out or remove&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Then build the container with&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;and start Superset with&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sh&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose -f docker-compose-image-tag.yml up&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Then, I can access Superset with my browser under &lt;code&gt;http://localhost:8088&lt;/code&gt; and log in with username: &lt;code&gt;admin&lt;/code&gt; and password: &lt;code&gt;admin&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;configure-superset&#34; class=&#34;content-heading&#34;&gt;Configure Superset&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Now, I can add DuckDB as a database in the Superset UI. I navigate to &lt;code&gt;Settings&lt;/code&gt; -&amp;gt; &lt;code&gt;Data&lt;/code&gt; -&amp;gt; &lt;code&gt;Database Connections&lt;/code&gt; &lt;code&gt;+ Database&lt;/code&gt; -&amp;gt; &lt;code&gt;DuckDB&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;and add the link to the DuckDB database file as the &lt;code&gt;SQLAlchemy URI&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;duckdb:////app/duckdb/database.duckdb?access_mode=READ_ONLY&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;Clicking on &lt;code&gt;Test Connection&lt;/code&gt; should respond with &amp;ldquo;Connection looks good!&amp;rdquo;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;add-datasets-in-superset&#34; class=&#34;content-heading&#34;&gt;Add datasets in Superset&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;In the navbar under &lt;code&gt;Datasets&lt;/code&gt; I can add the DuckDB tables &lt;code&gt;stg_vatternrundan&lt;/code&gt; and &lt;code&gt;average_speed_by_country&lt;/code&gt; as new Superset datasets.&lt;/p&gt;&#xA;&lt;h3 id=&#34;create-dashboard-in-superset&#34; class=&#34;content-heading&#34;&gt;Create dashboard in Superset&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Creating the dashboard is self-explanatory.&#xA;In the navbar, I select &lt;code&gt;Dashboards&lt;/code&gt; and add a new Dashboard called &amp;ldquo;Vätternrundan Dashboard&amp;rdquo;. Next, I create two charts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;number of riders per country&lt;/li&gt;&#xA;&lt;li&gt;average speed of riders per country&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Just select the relevant Superset Dataset, build the charts, and add them to the dashboard. Figure 2 shows how I did it.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/duckdb-dbt-superset/superset_dashboard.jpg&#34; alt=&#34;Superset Dashboard&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 2. Visualization of Vätternrundan rider speed by country in Apache Superset.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34; class=&#34;content-heading&#34;&gt;Conclusion&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;The combination of DuckDB, dbt, and Apache Superset is a local version of &amp;ldquo;the modern datastack&amp;rdquo;. This can be useful for personal projects, and to experiment with data transformations and visualisations.&lt;/p&gt;&#xA;&lt;p&gt;I found that the integration of DuckDB and dbt worked seamlessly. On the other hand, connecting Superset to DuckDB was clunky. Superset would benefit from better DuckDB support out-of-the-box.&lt;/p&gt;&#xA;&lt;h2 id=&#34;troubleshooting&#34; class=&#34;content-heading&#34;&gt;Troubleshooting&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;DuckDB only allows one connection with read-write-access, but multiple concurrent read-only connections. Make sure you are not connected to your DuckDB database with more than one client as access mode allows write by default, e.g. Superset and the DuckDB CLI client in your terminal.&lt;/li&gt;&#xA;&lt;li&gt;Ensure to connect Superset to DuckDB in read-only mode, i.e. add &lt;code&gt;access_mode=READ_ONLY&lt;/code&gt; to the SQLAlchemy URI to connect.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Book notes: Poor Charlie’s Almanack</title>
      <link>https://staticnotes.org/posts/poor-charlies-almanack-notes/</link>
      <pubDate>Fri, 21 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/poor-charlies-almanack-notes/</guid>
      <description>&lt;p&gt;The book is a collection of speeches that Charlie Munger, partner of Warren Buffett at Berkshire Hathaway, gave over the years (1986 - 2007) at universities and institutions.&lt;/p&gt;&#xA;&lt;p&gt;I found four interesting themes across the speeches:&lt;/p&gt;&#xA;&lt;h2 id=&#34;advocating-interdisciplinary-collaboration-between-university-departments&#34; class=&#34;content-heading&#34;&gt;Advocating interdisciplinary collaboration between university departments&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;He believes that the social sciences, especially economics and psychology, are focusing on too narrow theoretical problems. Academics suffer from a &lt;em&gt;man-with-a-hammer-syndrome&lt;/em&gt;. He suggests that they collaborate more across departments, e.g. economics borrowing from psychology, and within departments, e.g. macroeconomists shouldn&amp;rsquo;t avoid microeconomic explanations. Moreover, the social sciences should try to incorporate findings / models from the hard sciences (physics, chemistry, etc.) and attribute them properly.&lt;/p&gt;&#xA;&lt;h2 id=&#34;fraud-and-advice-for-endowment-funds&#34; class=&#34;content-heading&#34;&gt;Fraud and advice for endowment funds&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;In some of his talks, he uses fictional examples of companies to show the problems with accounting and financial engineering fraud.&lt;/p&gt;&#xA;&lt;p&gt;He thinks that charitable foundations and endowment funds should as much as possible avoid wasteful investment practices. He criticises the trend of university endowment funds to employ layers of analysts and consultants to use funds of funds. These multilayered systems erode a large chunk of the endowment funds&amp;rsquo; returns when compared to simpler alternatives, like unlevered domestic equity indices. He directly criticises the practices of his audience of consultants and fund managers in talk six, but he uses humour and self-deprecation to get away with it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;inverted-advice-for-graduates&#34; class=&#34;content-heading&#34;&gt;(Inverted) Advice for Graduates&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;In his commencement speeches for university graduates, he gives advice on &lt;strong&gt;how to guarantee misery&lt;/strong&gt; in life.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Be unreliable.&lt;/li&gt;&#xA;&lt;li&gt;Don&amp;rsquo;t learn from others&amp;rsquo; mistakes. Instead, make common mistakes of others again (join a cult, drive while drunk, gamble) and don&amp;rsquo;t learn from people that came before you.&lt;/li&gt;&#xA;&lt;li&gt;Give up after adversity and failures. Just give up when the inevitable hard times occur.&lt;/li&gt;&#xA;&lt;li&gt;Don&amp;rsquo;t ever invert. Don&amp;rsquo;t attempt to learn from thinking about achieving the opposite of your goals. Don&amp;rsquo;t try to be objective.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;mental-checklist-to-analyse-problems&#34; class=&#34;content-heading&#34;&gt;Mental checklist to analyse problems&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;A recurring topic in his speeches is a checklist of mental models and human biases. He developed this checklist over time and iterated through it when analysing a problem or evaluating an investment. Using appropriate checklists and &lt;a href=&#34;https://fs.blog/inversion/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;the inversion technique&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; are two main tools that he promotes for better thinking.&lt;/p&gt;&#xA;&lt;p&gt;Here are 25 human biases from talk eleven: &lt;a href=&#34;https://fs.blog/great-talks/psychology-human-misjudgment/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;The Psychology of Human Misjudgment&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Reward and Punishment Superresponse Tendency&lt;/strong&gt;: If you want to persuade people, appeal to their own interests. Ensure the incentives of people you work with are aligned with the outcome you want. Don&amp;rsquo;t reward them for metrics that they can easily game.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Liking/Loving Tendency&lt;/strong&gt;: People are seeking love and approval from other people. Moreover, we favour people and products that are merely associated with the target of our affection. We can use this to our advantage by liking truly admirable people or ideas.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Disliking/Hating Tendency&lt;/strong&gt;: People can have a tendency to dislike things different from them or products or people that are associated with the object of their dislike.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Doubt-Avoidance Tendency&lt;/strong&gt;: Our brains are conditioned to quickly remove doubt after reaching a first decision. This tendency should be countered by forcing a delay for reflection before an important decision, e.g. jury decisions in court.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Inconsistency-Avoidance Tendency&lt;/strong&gt;: A tendency to stick to previous conclusions, habits, and ideas to avoid change. Practically, this means that it is much easier to prevent a bad habit than to change it. To counter this tendency, we should force the discussion of counterarguments before a decision can be made.&#xA;This tendency can be used to manipulate people (see also &lt;a href=&#34;https://en.wikipedia.org/wiki/Ben_Franklin_effect&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Ben Franklin effect&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Consistency_%28negotiation%29&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Cialdini&amp;rsquo;s consistency principle&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Curiosity Tendency&lt;/strong&gt;: Humans have a general tendency to be curious, which can be supercharged with today&amp;rsquo;s access to information. This fortunate tendency should be used to counteract other psychological tendencies.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Kantian Fairness Tendency&lt;/strong&gt;: People have a tendency in direct interactions to behave fairly (following Kant&amp;rsquo;s categorical imperative).&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Envy/Jealousy Tendency&lt;/strong&gt;: People&amp;rsquo;s tendency to envy someone else&amp;rsquo;s status, wealth, or compensation. &amp;ldquo;It is not greed that drives the world but envy.&amp;rdquo; (Buffett)&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Reciprocation Tendency&lt;/strong&gt;: People have a tendency to reciprocate favours and disfavours. This can also be used for manipulation, e.g. a salesman could do you a small favour to get a much better outcome in negotiation.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Influence-from-Mere-Association Tendency&lt;/strong&gt;: Valuing something by the association with another unrelated factor/idea/concept. Examples:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;association of quality with the highest price&lt;/li&gt;&#xA;&lt;li&gt;purchasing of luxury items to boost status&lt;/li&gt;&#xA;&lt;li&gt;advertising of products with unrelated but positive images&lt;/li&gt;&#xA;&lt;li&gt;associating one&amp;rsquo;s ability with past successes and making bad decisions&lt;/li&gt;&#xA;&lt;li&gt;thinking of someone worse because they are a competitor&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Simple Pain-Avoiding Psychological Denial&lt;/strong&gt;: Denying reality because it is too painful to accept, e.g. addiction, bankruptcy.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Denial of a reality that&amp;rsquo;s too painful to accept, e.g. addiction to alcohol.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Excessive Self-Regard Tendency&lt;/strong&gt;: People&amp;rsquo;s tendency to overestimate their abilities, decisions, and possessions. Moreover, their preference of people that are similar to them.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Overoptimism Tendency&lt;/strong&gt;: A tendency to be overly optimistic of the future, especially if one has done well in the past.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Deprival-Superreaction Tendency&lt;/strong&gt;: Reacting more strongly to losses than to gains, e.g. losing $10 is considered worse than gaining $10. Irrational overreaction to threatened loss of status, territory, love, friendship, or property.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Social-Proof Tendency&lt;/strong&gt;: A tendency to act and think the same way as people around you (Group-think).&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Contrast-Misreaction Tendency&lt;/strong&gt;: Making bad decisions by anchoring on an irrelevant comparison. Examples:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Adding $1000 of useless add-ons to a car only because the car costs $65k.&lt;/li&gt;&#xA;&lt;li&gt;A real estate agent presenting 3 terrible and expensive houses, then showing a merely bad house to make it look more desirable.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Stress-Influence Tendency&lt;/strong&gt;: Light stress can increase performance temporarily, while heavy stress can cause dysfunctional thinking and bad decision-making.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Availability-Misweighting Tendency&lt;/strong&gt;: Tendency to overweight or overvalue things (people, decisions, work, ideas) that are close or readily accessible to you. This also holds for metrics that are easy to measure and actions that are easy to take. This can be countered by following checklists of actions and by considering more difficult (or less accessible) alternatives.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Use-It-or-Lose-It Tendency&lt;/strong&gt;: Over time, our skills and knowledge fade. Therefore we should deliberately train and repeat the skills we want to retain. Write them down as a checklist and work through them regularly.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Drug-Misinfluence Tendency&lt;/strong&gt;: Most people can&amp;rsquo;t handle drugs responsibly over a long period of time. Not worth trying to prove that you can.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Senescence-Misinfluence Tendency:&lt;/strong&gt; Older people have a harder time learning new skills. Knowing this, the best counter is to actively maintain the accumulated knowledge, see 19).&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Authority-Misinfluence Tendency&lt;/strong&gt;: Tendency to blindly follow the leader (see also: &lt;a href=&#34;https://psychsafety.com/the-hippo/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;HiPPO effect&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Twaddle Tendency&lt;/strong&gt;: Some people waste time talking about things they are not an expert in. Try to separate these people from the experts and follow the latter.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Reason-Respecting Tendency:&lt;/strong&gt; People can learn better when they can think through the reasons behind a directive or action. Therefore, when giving orders explain your reasoning.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Lollapalooza Tendency&lt;/strong&gt;: Often multiple human biases act together to drive a certain behaviour or outcome.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;conclusion&#34; class=&#34;content-heading&#34;&gt;Conclusion&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I gave only 3/5 stars because the format of reading his talks didn&amp;rsquo;t appeal to me. I was already aware of most of the human biases listed by Munger. Some are discussed in &lt;a href=&#34;https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Thinking Fast and Slow (2011)&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/Influence:_Science_and_Practice&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Influence: Science and Practice (2001)&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. However, what I found impressive is that he talked about and used these biases already 20 years ago, before they were widely discussed. I also liked that in many speeches he directly criticises the audience that invited him to speak. However, he does it in a charming and humorous way.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>About this blog and its microfeatures</title>
      <link>https://staticnotes.org/posts/blog-microfeatures/</link>
      <pubDate>Wed, 12 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/blog-microfeatures/</guid>
      <description>&lt;p&gt;No blog would be complete without a post explaining the code and frameworks used to generate it. In fact, often tweaking the blog code is more fun than actually writing something.&lt;/p&gt;&#xA;&lt;h2 id=&#34;static-site-generator&#34; class=&#34;content-heading&#34;&gt;Static site generator&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I try to keep the tech of this blog simple. I am using the &lt;a href=&#34;https://gohugo.io/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Hugo&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; static site generator and chose one of the simplest themes &lt;a href=&#34;https://themes.gohugo.io/themes/hugo-bearcub/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Bear Cub&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; to get started. What I liked about the theme was its small code footprint, no JavaScript/ads/trackers, and it was entirely focused on text. The generated pages are small and load fast. The simple layout made it very easy for me to understand and modify it over time.&lt;/p&gt;&#xA;&lt;p&gt;The source code is hosted on GitLab and the static sites are published to GitLab Pages. This means that to publish a new post, I just have to push a commit with the changes to the remote repository.&lt;/p&gt;&#xA;&lt;h2 id=&#34;supporting-math-code-jupyter-notebooks&#34; class=&#34;content-heading&#34;&gt;Supporting math, code, Jupyter notebooks&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;At the time of starting this blog I worked as a data scientist. I wanted to be able to share reproducible Jupyter notebooks that I could easily convert to HTML and embed in this blog. &lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; All notebooks are reproducible unless the data used in the blog post is too large to be uploaded to GitLab. &lt;/small&gt;&lt;/span&gt; I put my notebooks into the &lt;code&gt;/notebooks&lt;/code&gt; folder of the repository and use the script &lt;a href=&#34;https://github.com/vlunot/nb2hugo&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;nb2hugo&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; to convert the notebooks to markdown files. At the bottom of the post you can usually find the link to the Jupyter notebook, the poetry environment, and the data. I wrote about this &lt;a href=&#34;https://staticnotes.org/posts/hugo-and-jupyter/&#34; &#xA;&gt;here&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The equations on this blog are rendered with &lt;a href=&#34;https://katex.org/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;KaTeX&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;content-types&#34; class=&#34;content-heading&#34;&gt;Content types&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;The content of this blog has four different types:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Posts&lt;/strong&gt; are normal blog posts.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;TILs&lt;/strong&gt;, or Today-I-Learned, are notes documenting something small I have learned on a day. The idea is based on &lt;a href=&#34;https://til.simonwillison.net/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Simon Willison&amp;rsquo;s TILs&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Links&lt;/strong&gt; appear in &lt;strong&gt;Feeds&lt;/strong&gt; and are links that I want to share, usually with a short comment. They can be thought of as a retweet.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Book&lt;/strong&gt; reviews.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;1-3 are shown in reverse-chronological order in the main page&amp;rsquo;s feed.&lt;/p&gt;&#xA;&lt;h2 id=&#34;microfeatures&#34; class=&#34;content-heading&#34;&gt;Microfeatures&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I like Daniel Fedorin&amp;rsquo;s post on &lt;a href=&#34;https://danilafe.com/blog/blog_microfeatures/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;blog microfeatures&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. In the same spirit, here are the microfeatures that I have added:&lt;/p&gt;&#xA;&lt;h3 id=&#34;recommendations&#34; class=&#34;content-heading&#34;&gt;Recommendations&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Most pages have post recommendations at the bottom. I compute the (cosine) similarity of posts after summarizing them with a local LLM, computing embeddings, and storing them in a local Chroma vector database. The two most similar posts and their cosine similarity are then displayed. Note that all of this is pre-generated and static. I wrote in more detail about how this works &lt;a href=&#34;https://staticnotes.org/posts/how-recommendations-work/&#34; &#xA;&gt;here&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;For this post, they look like this:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;  &lt;div class=&#34;similar-post-section&#34;&gt;&#xA;    Similar posts:&#xA;    &lt;ul class=&#34;similar-posts-list&#34;&gt;&#xA;      &#xA;        &lt;li&gt;&#xA;          &lt;div class=&#34;similar-post-title&#34;&gt;&lt;a  href=&#34;../posts/hugo-and-jupyter/&#34;&gt;How to display Jupyter notebooks on your Hugo blog&lt;/a&gt; &lt;a href=&#34;../posts/how-recommendations-work&#34;&gt;(0.55)&lt;/a&gt;&lt;/div&gt; &#xA;        &lt;/li&gt;&#xA;      &#xA;        &lt;li&gt;&#xA;          &lt;div class=&#34;similar-post-title&#34;&gt;&lt;a  href=&#34;../posts/how-recommendations-work/&#34;&gt;How related posts are computed&lt;/a&gt; &lt;a href=&#34;../posts/how-recommendations-work&#34;&gt;(0.458)&lt;/a&gt;&lt;/div&gt; &#xA;        &lt;/li&gt;&#xA;      &#xA;    &lt;/ul&gt;&#xA;  &lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h3 id=&#34;sidenotes&#34; class=&#34;content-heading&#34;&gt;Sidenotes&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I can add sidenotes&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; like this one.&lt;/small&gt;&lt;/span&gt; to a blog post by using the &lt;code&gt;{{% sidenote %}}&lt;/code&gt; shortcode. I really like to use this for comments that are additional to the primary content or later updates to a blog post.&lt;/p&gt;&#xA;&lt;h3 id=&#34;markers-for-external-links&#34; class=&#34;content-heading&#34;&gt;Markers for external links&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Internal &lt;a href=&#34;https://staticnotes.org/posts/blog-microfeatures/&#34; &#xA;&gt;links&#xA;&lt;/a&gt; on this blog have no marker and open in the same window. &lt;a href=&#34;https://www.google.com/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;External links&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; are appended with an icon and open in a new window. Inspired by &lt;a href=&#34;https://gwern.net/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;gwern.net&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;, I also added specific icons for particular sites: &lt;a href=&#34;https://x.com/jack/status/20&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;tweet&#xA;    &#xA;&#xA;        &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.9em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 448 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;&#xA;        &#xA;    &#xA;&lt;/a&gt; on x.com, &lt;a href=&#34;https://www.goodreads.com/book/show/42844155-harry-potter-and-the-philosopher-s-stone&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;book link&#xA;    &#xA;&#xA;        &#xA;    &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;        style=&#34;height: 0.7em; width: 0.9em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;        class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;        viewBox=&#34;0 0 448 512&#34;&gt;&#xA;        &lt;path fill=&#34;currentColor&#34;&#xA;            d=&#34;M299.9 191.2c5.1 37.3-4.7 79-35.9 100.7-22.3 15.5-52.8 14.1-70.8 5.7-37.1-17.3-49.5-58.6-46.8-97.2 4.3-60.9 40.9-87.9 75.3-87.5 46.9-.2 71.8 31.8 78.2 78.3zM448 88v336c0 30.9-25.1 56-56 56H56c-30.9 0-56-25.1-56-56V88c0-30.9 25.1-56 56-56h336c30.9 0 56 25.1 56 56zM330 313.2s-.1-34-.1-217.3h-29v40.3c-.8 .3-1.2-.5-1.6-1.2-9.6-20.7-35.9-46.3-76-46-51.9 .4-87.2 31.2-100.6 77.8-4.3 14.9-5.8 30.1-5.5 45.6 1.7 77.9 45.1 117.8 112.4 115.2 28.9-1.1 54.5-17 69-45.2 .5-1 1.1-1.9 1.7-2.9 .2 .1 .4 .1 .6 .2 .3 3.8 .2 30.7 .1 34.5-.2 14.8-2 29.5-7.2 43.5-7.8 21-22.3 34.7-44.5 39.5-17.8 3.9-35.6 3.8-53.2-1.2-21.5-6.1-36.5-19-41.1-41.8-.3-1.6-1.3-1.3-2.3-1.3h-26.8c.8 10.6 3.2 20.3 8.5 29.2 24.2 40.5 82.7 48.5 128.2 37.4 49.9-12.3 67.3-54.9 67.4-106.3z&#34;&gt;&#xA;        &lt;/path&gt;&#xA;    &lt;/svg&gt;&#xA;&lt;/span&gt;&#xA;&#xA;&#xA;&#xA;    &#xA;&lt;/a&gt; on goodreads, &lt;a href=&#34;https://www.youtube.com/watch?v=MiUHjLxm3V0&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;video&#xA;    &#xA;&#xA;        &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.9em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 448 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M549.7 124.1c-6.3-23.7-24.8-42.3-48.3-48.6C458.8 64 288 64 288 64S117.2 64 74.6 75.5c-23.5 6.3-42 24.9-48.3 48.6-11.4 42.9-11.4 132.3-11.4 132.3s0 89.4 11.4 132.3c6.3 23.7 24.8 41.5 48.3 47.8C117.2 448 288 448 288 448s170.8 0 213.4-11.5c23.5-6.3 42-24.2 48.3-47.8 11.4-42.9 11.4-132.3 11.4-132.3s0-89.4-11.4-132.3zm-317.5 213.5V175.2l142.7 81.2-142.7 81.2z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;&#xA;    &#xA;    &#xA;&lt;/a&gt; on youtube, and &lt;a href=&#34;https://en.wikipedia.org/wiki/Blog&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;article&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; on wikipedia.&lt;/p&gt;&#xA;&lt;h3 id=&#34;link-blog--retweets--boosts&#34; class=&#34;content-heading&#34;&gt;Link-blog / retweets / boosts&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;The main page of this blog has a section &lt;code&gt;Recent&lt;/code&gt; which displays a feed of the content being posted. It&amp;rsquo;s a mix of posts, TILs and link-blog entries and should mimic a social media profile feed.&#xA;Shared links have a reshare/boost symbol and usually a short comment about them. They also have a &lt;code&gt;via&lt;/code&gt; link to the place where I found this link. This is also inspired by Simon Willison&amp;rsquo;s main page.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/blog-microfeatures/linkblogentry.png&#34; alt=&#34;SharedLink&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 1. A shared link.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;rss&#34; class=&#34;content-heading&#34;&gt;RSS&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I provide &lt;a href=&#34;https://staticnotes.org/index.xml&#34; &#xA;&gt;RSS feeds&#xA;&lt;/a&gt; for all content types and also separate feeds for &lt;a href=&#34;https://staticnotes.org/posts.xml&#34; &#xA;&gt;Posts&#xA;&lt;/a&gt;, &lt;a href=&#34;https://staticnotes.org/til.xml&#34; &#xA;&gt;TIL&#xA;&lt;/a&gt;, &lt;a href=&#34;https://staticnotes.org/feed.xml&#34; &#xA;&gt;Feed&#xA;&lt;/a&gt;, and &lt;a href=&#34;https://staticnotes.org/books.xml&#34; &#xA;&gt;Books&#xA;&lt;/a&gt; only. I wrote more about this &lt;a href=&#34;https://staticnotes.org/til/hugo-with-separate-rss-feeds/&#34; &#xA;&gt;here&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;table-of-contents&#34; class=&#34;content-heading&#34;&gt;Table of Contents&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Longer blog posts have a table of contents section at the beginning of the post.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/blog-microfeatures/tableofcontents.png&#34; alt=&#34;TableOfContents&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 2. Some longer posts show a table of contents at the top.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;linkable-headers&#34; class=&#34;content-heading&#34;&gt;Linkable Headers&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;The main headers of blog posts have a linkable §-symbol in front of them. This means you can easily link to a specific section of the blog post.&lt;/p&gt;&#xA;&lt;h3 id=&#34;drawings&#34; class=&#34;content-heading&#34;&gt;Drawings&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I added the ability to provide an optional SVG image that is added to the background next to the post title, e.g. &lt;a href=&#34;https://staticnotes.org/posts/writing-well/&#34; &#xA;&gt;here&#xA;&lt;/a&gt; and &lt;a href=&#34;https://staticnotes.org/posts/reading-and-note-taking/&#34; &#xA;&gt;here&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/blog-microfeatures/title_drawing.png&#34; alt=&#34;TitleDrawing&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 3. Blog posts can have an SVG drawing next to the title.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;prompts--llm-responses&#34; class=&#34;content-heading&#34;&gt;Prompts / LLM responses&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;When I first wrote about &lt;a href=&#34;https://staticnotes.org/til/hugo-with-separate-rss-feeds/&#34; &#xA;&gt;using an LLM to build something&#xA;&lt;/a&gt; I thought that it would be quite common to share a prompt and the LLM&amp;rsquo;s output in your blog post. So I built a small feature to display them in a chat-like fashion. You can use &lt;code&gt;{{% prompt %}}&lt;/code&gt; to put text into a prompt chat bubble, and &lt;code&gt;{{% llm %}}&lt;/code&gt; for the model response (colored by model). Turns out, this is not something I regularly need and nobody wants to read someone else&amp;rsquo;s prompt or the LLM&amp;rsquo;s answer anymore.&lt;/p&gt;&#xA;&lt;div class=&#34;promptbox&#34;&gt;&#xA;    &lt;div class=&#34;promptbox-title&#34;&gt;&#xA;        Prompt&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;promptbox-content&#34;&gt;&#xA;        How many Rs are in the word strawberry?      &lt;/div&gt; &#xA;&lt;/div&gt;&#xA;&lt;details class=&#34;llmbox llm-anthropic&#34;&gt;&#xA;    &lt;summary class=&#34;llmbox-title&#34;&gt;&#xA;        Model: claude-opus-5-5 - response &#xA;    &lt;/summary&gt;&#xA;    &lt;div class=&#34;llmbox-content&#34;&gt;&#xA;&lt;p&gt;There are 3 Rs in &amp;ldquo;strawberry&amp;rdquo;: strawberry.&#xA;&lt;/div&gt;&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;&lt;details class=&#34;llmbox llm-openai&#34;&gt;&#xA;    &lt;summary class=&#34;llmbox-title&#34;&gt;&#xA;        Model: openai-sol-5-6 - response &#xA;    &lt;/summary&gt;&#xA;    &lt;div class=&#34;llmbox-content&#34;&gt;&#xA;&lt;p&gt;There are 3 Rs in &amp;ldquo;strawberry&amp;rdquo;: strawberry.&#xA;&lt;/div&gt;&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;&lt;details class=&#34;llmbox llm-qwen&#34;&gt;&#xA;    &lt;summary class=&#34;llmbox-title&#34;&gt;&#xA;        Model: qwen-4-3 - response &#xA;    &lt;/summary&gt;&#xA;    &lt;div class=&#34;llmbox-content&#34;&gt;&#xA;&lt;p&gt;There are 3 Rs in &amp;ldquo;strawberry&amp;rdquo;: strawberry.&#xA;&lt;/div&gt;&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;</description>
    </item>
    
    <item>
      <title>How related posts are computed</title>
      <link>https://staticnotes.org/posts/how-recommendations-work/</link>
      <pubDate>Sun, 09 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/how-recommendations-work/</guid>
      <description>&lt;p&gt;The number next to related posts at the bottom of each page is the advertised post&amp;rsquo;s &amp;ldquo;similarity&amp;rdquo; to the currently viewed page (from 1.0 to -1.0).&lt;/p&gt;&#xA;&lt;p&gt;I am using the following process to compute related posts locally:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Summarise every post and TIL using local qwen (&lt;code&gt;qwen3.5:9b&lt;/code&gt; via Ollama) with the following prompt:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;promptbox&#34;&gt;&#xA;    &lt;div class=&#34;promptbox-title&#34;&gt;&#xA;        Prompt&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;promptbox-content&#34;&gt;&#xA;        &lt;p&gt;You are an analyst and editor with many years of experience in reading and synthesizing content.&lt;/p&gt;&#xA;&lt;p&gt;Here is a blog post:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;&amp;lt;BLOGPOST&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;{ blog_post }&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;&amp;lt;/BLOGPOST&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;Please create a comprehensive and concise summary of the blog post. Focus on the main concepts, key details, and central arguments.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;&amp;lt;INSTRUCTIONS&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Include any specific technologies, methods, or frameworks mentioned.&lt;/li&gt;&#xA;&lt;li&gt;Don&amp;rsquo;t use more than 7 sentences.&lt;/li&gt;&#xA;&lt;li&gt;Respond in plaintext. Don&amp;rsquo;t add formatting or linebreak characters to your response.&lt;/li&gt;&#xA;&lt;li&gt;Don&amp;rsquo;t repeat the instructions of the task. Respond directly.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;code&gt;&amp;lt;/INSTRUCTIONS&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;      &lt;/div&gt; &#xA;&lt;/div&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;Embed the summary using a qwen embedding model &lt;code&gt;qwen3-embedding:0.6b&lt;/code&gt; and store the embedding and metadata about the post in a persistent &lt;a href=&#34;https://www.trychroma.com/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;ChromaDB&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; vector database (a file on my computer).&lt;/li&gt;&#xA;&lt;li&gt;Compute the &lt;a href=&#34;https://en.wikipedia.org/wiki/Cosine_similarity&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;cosine similarity&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; between the embeddings for each pair of posts. A score of 1.0 indicates proportional vectors, a score of 0.0 orthogonal vectors, and a score of -1.0 opposite vectors.&lt;/li&gt;&#xA;&lt;li&gt;Write a yaml file that includes for every post a link to the most similar post and their similarity.&lt;/li&gt;&#xA;&lt;li&gt;Use a Hugo partial to include the data in the yaml file about the most relevant posts at the bottom of each page.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;noteworthy&#34; class=&#34;content-heading&#34;&gt;Noteworthy&#xA;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When using Llama, I had to explicitly instruct the model not to restate the task. Otherwise, every summary would have started with &amp;ldquo;Here is your concise blog post summary in not more than 7 sentences.&amp;rdquo; which would create some artificial similarity in the embeddings.&lt;/li&gt;&#xA;&lt;li&gt;Most blog posts are shorter than 15000 characters, or 4000 tokens. I had to work this out to configure the model context correctly.&lt;/li&gt;&#xA;&lt;li&gt;ChromaDB&amp;rsquo;s default embedding model &lt;code&gt;all-MiniLM-L6-v2&lt;/code&gt; has 384 dimensions and a maximum input sequence length of 256 BERT tokens (~100&amp;ndash;150 words). I checked some of the summaries and they were around 160 &amp;ndash; 220 BERT tokens. I have since switched to a qwen embedding model which has much longer input context. A good embedding model leaderboard to help make a choice is available &lt;a href=&#34;https://huggingface.co/spaces/mteb/leaderboard&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;example&#34; class=&#34;content-heading&#34;&gt;Example&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;For the blog post &lt;a href=&#34;https://staticnotes.org/posts/uk-house-prices/&#34; &#xA;&gt;UK house price changes in real terms&#xA;&lt;/a&gt; the LLM came up with this summary which was then embedded:&lt;/p&gt;&#xA;&lt;details class=&#34;llmbox llm-qwen&#34;&gt;&#xA;    &lt;summary class=&#34;llmbox-title&#34;&gt;&#xA;        Model: qwen3.5:9b - response &#xA;    &lt;/summary&gt;&#xA;    &lt;div class=&#34;llmbox-content&#34;&gt;&#xA;&lt;p&gt;The author critiques standard UK housing market reports for presenting nominal price changes that obscure local realities and ignore inflation, arguing instead for real house prices adjusted using CPI data from ONS alongside Land Registry transaction records. To address this gap, the post demonstrates a Python-based workflow utilizing pandas to merge regional property datasets with quarterly consumer price index figures to calculate purchasing power-adjusted values in 2025 pounds. The analysis focuses on specific areas around London and South England, visualizing trends for detached houses in counties like Surrey and Kent as well as flats within selected boroughs since 2015. Results reveal that while nominal prices may show modest growth or stagnation, real house prices have actually declined significantly over the last decade in many regions due to inflation outpacing asset appreciation. The author provides interactive tables comparing current valuations against historical data points from one, two, five, and ten years prior to highlight these divergences across different property types. By leveraging open APIs for Land Registry and ONS data stored as parquet files, the post offers a reproducible method for investors and buyers to assess true market performance beyond headline statistics. Ultimately, this approach clarifies that British housing has often underperformed relative to other investments like the FTSE  100 when viewed through an inflation-adjusted lens.&#xA;&lt;/div&gt;&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;&lt;h3 id=&#34;embeddings&#34; class=&#34;content-heading&#34;&gt;Embeddings&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I can visualise the embeddings in two dimensions using &lt;a href=&#34;https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;t-SNE&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;:&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/how-recommendations-work/embeddings_visualization.png&#34; alt=&#34;Embeddings in 2D space&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 1. Plot of blog post summary embeddings in t-SNE space.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;The plot looks somewhat reasonable. The code-heavy Jupyter notebook posts are at the bottom, clustered around &lt;code&gt;duckdb-large-datasets&lt;/code&gt;. The book reviews (&lt;code&gt;4000-weeks&lt;/code&gt;, &lt;code&gt;how-big-things-get-done&lt;/code&gt;, &lt;code&gt;how-to-win-friends&lt;/code&gt;) are fairly close together. SQL related posts are clustered at the top. On the other hand, I would have expected &lt;code&gt;reading-and-note-taking&lt;/code&gt; to be closer to &lt;code&gt;writing-well&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;code&#34; class=&#34;content-heading&#34;&gt;Code&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I am using &lt;a href=&#34;https://gitlab.com/frankRi89/blog/-/blob/04aca65a2c58058e76df07f121a232885549ce1e/code/posts-similarity/src/similarity_generator.py&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;this langchain script&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; to compute the recommendations.&lt;/p&gt;&#xA;&lt;h3 id=&#34;update&#34; class=&#34;content-heading&#34;&gt;Update&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;A previous version of the code and blog post used Llama 3.1 to summarise the text and ChromaDB&amp;rsquo;s default embedding model &lt;code&gt;all-MiniLM-L6-v2&lt;/code&gt;.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Book notes: How Big Things Get Done by Bent Flyvbjerg and Dan Gardner</title>
      <link>https://staticnotes.org/posts/how-big-things-get-done/</link>
      <pubDate>Sun, 02 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/how-big-things-get-done/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://itu.dk/flyvbjerg&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Bent Flyvbjerg&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; is an economics professor at IT University of Copenhagen. He maintains a database of megaprojects (power plants, opera halls, tunnels, airports) and their planned and realised timelines and budgets. He researches the reasons why modern megaprojects often fail to deliver on time and on budget. It has recently become quite popular to &lt;a href=&#34;https://patrickcollison.com/fast&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;discuss&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; the apparent decrease in speed with which large-scale projects are realised. Examples are easy to find, e.g. the delayed &lt;a href=&#34;https://en.wikipedia.org/wiki/High_Speed_2&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;High Speed Rail 2 (HS2)&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; project or the time and cost overruns of the &lt;a href=&#34;https://en.wikipedia.org/wiki/Construction_of_Berlin_Brandenburg_Airport&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Berlin Brandenburg Airport (BER)&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. Counter-examples are less common (or less newsworthy), e.g. the 2023 Notre-Dame Reconstruction.&lt;/p&gt;&#xA;&lt;p&gt;In their book Flyvbjerg/Gardner explain the common reasons for cost and time overruns of megaprojects and how to mitigate them. I think we can apply the majority of their learnings for smaller home (kitchen renovation) and work projects (cloud migration) as well.&lt;/p&gt;&#xA;&lt;h2 id=&#34;planning-is-cheap-building-is-expensive&#34; class=&#34;content-heading&#34;&gt;Planning is cheap, building is expensive&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;In large construction projects, planning is a lot cheaper than building. Once a badly planned project is underway, unforeseen problems will be discovered. Delays tend to cause further delays. The total project time can be in itself a source of additional risk and cost.&lt;/p&gt;&#xA;&lt;p&gt;When politicians plan prestigious infrastructure projects, they have a bias for strategic misrepresentation of the cost and time to get support for it. Therefore, the government and the public need to scrutinise the project&amp;rsquo;s goal and its planning to ensure that the plan is realistic and enough alternatives have been considered. Only get involved in such a project if it has the people and funds, including contingencies, to succeed.&lt;/p&gt;&#xA;&lt;p&gt;Since planning is a lot cheaper than building for large projects, Flyvbjerg/Gardner advise investing significant time into the planning phase:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;understand the objective behind the proposed project (assume an outside view)&lt;/li&gt;&#xA;&lt;li&gt;explore alternatives and don&amp;rsquo;t commit to the first available solution (resist quick action bias)&lt;/li&gt;&#xA;&lt;li&gt;don&amp;rsquo;t forecast using the best-case scenario, instead use similar past projects to anchor your estimate&lt;/li&gt;&#xA;&lt;li&gt;experiment and iterate in the planning phase using digital modelling and simulations&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;understand-the-why&#34; class=&#34;content-heading&#34;&gt;Understand the why&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;&lt;em&gt;The project is not a goal in itself, it is how the goal is achieved&lt;/em&gt;. We want to talk to the stakeholder to understand the goal. Is the project even the right approach? Good planning needs to explore the problem before jumping to the solution. This includes considering alternatives.&lt;/p&gt;&#xA;&lt;p&gt;There is a good example in the book about a bridge project. The original goal of the project is to connect an island with the mainland. By jumping to the bridge idea, the stakeholders ignored alternatives, e.g. a tunnel, ferries, a helipad. Or maybe a physical connection is not required. If it&amp;rsquo;s about improved communication, maybe a high-speed broadband connection achieves the goal.&lt;/p&gt;&#xA;&lt;p&gt;Another framing of this idea in product development is to work backwards from the customer. Understand their needs and problems, before coming up with any solution.&lt;/p&gt;&#xA;&lt;h3 id=&#34;reduce-uncertainty-via-experimentation&#34; class=&#34;content-heading&#34;&gt;Reduce uncertainty via experimentation&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;A crucial part of the planning phase is to experiment with the solution. Ideally, we can simulate and iterate on the project, e.g. use 3D models of the building, low fidelity designs to show customers, or low effort versions of the animation movie we are trying to produce.&lt;/p&gt;&#xA;&lt;p&gt;The simulation ensures that the majority of aspects of our project are scrutinised before the building phase begins. We can assume that the project will run into problems, so we want most of the problems to occur during the &lt;em&gt;cheap&lt;/em&gt; planning phase.&lt;/p&gt;&#xA;&lt;h3 id=&#34;experience-in-people-and-technology&#34; class=&#34;content-heading&#34;&gt;Experience in people and technology&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;To maximise the chance of a successful project we should maximise &lt;em&gt;experience&lt;/em&gt;. Flyvbjerg/Gardner consider both experience in &lt;em&gt;key people&lt;/em&gt; and in &lt;em&gt;technology&lt;/em&gt;.&#xA;We should try to ensure that key people have experience in similar projects. Ask: &amp;ldquo;Have they done it before?&amp;rdquo;.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Technology is &amp;lsquo;frozen experience&amp;rsquo;.&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;All things being equal, we should use tried and tested off-the-shelf technology instead of shiny new technology. If we can, we should use existing designs and operational processes.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt;This is the same idea behind McKinley&amp;rsquo;s advice to &lt;a href=&#34;https://mcfunley.com/choose-boring-technology&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Choose Boring Technology&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/small&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;p&gt;The construction of the Empire State Building is used throughout the book as a positive example. One reason for this was the architect William Lamb who insisted on using only proven technology, and who created a design that allowed repeatable non-custom work steps. Moreover, the construction company Starrett Brothers and Eken had built several similar skyscrapers on time and budget before.&lt;/p&gt;&#xA;&lt;h3 id=&#34;reference-class-forecasting&#34; class=&#34;content-heading&#34;&gt;Reference-class forecasting&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;After the project is planned we need to forecast the project duration and its cost. Unfortunately, planners often forecast too optimistically. Instead of deriving it from the project alone, the authors suggest using &lt;em&gt;reference-class forecasting&lt;/em&gt;. The idea is to find a set of comparable projects, and to anchor our forecast based on their outcomes. Then adjust from that anchor.&lt;/p&gt;&#xA;&lt;p&gt;However, good forecasting cannot protect the project from fat-tailed risks. Since those risks can kill our project, we need to identify the (known) high risk events and try to mitigate them.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Successful project leaders focus every day on not losing, while keeping a keen eye on the [&amp;hellip;] goal they are trying to achieve.&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;after-the-planning-is-done-build-quickly&#34; class=&#34;content-heading&#34;&gt;After the planning is done, build quickly&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;The project duration is in itself a source of budget and time risk.&#xA;After planning, simulating, and forecasting, we therefore need to act fast once the building phase starts. To do this we should ideally use an experienced team and a modular building pattern.&lt;/p&gt;&#xA;&lt;h3 id=&#34;build-with-an-experienced-team&#34; class=&#34;content-heading&#34;&gt;Build with an experienced team&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;If possible, hire, what the authors call, a masterbuilder. That is someone who has experience in similar projects and can pick the right team. If such a team doesn&amp;rsquo;t exist, you or them need to create it.&lt;/p&gt;&#xA;&lt;p&gt;Moreover, we need to ensure that the incentives of participating contractors are aligned with ours by sharing risks and rewards, e.g. pay a bonus for early completion. Don&amp;rsquo;t always pick the contractor that submits the lowest bid, because the lowest bid doesn&amp;rsquo;t necessarily lead to the lowest cost. Moreover, we will try to choose companies that we have successfully collaborated with before.&lt;/p&gt;&#xA;&lt;h3 id=&#34;whats-our-lego&#34; class=&#34;content-heading&#34;&gt;What&amp;rsquo;s our Lego?&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Nuclear power plant constructions belong to the class of projects that most likely exceed cost and time budgets. Flyvbjerg/Gardner argue that you are building one large thing that has few repeatable, standardised parts. Solar power plants are the opposite. The core ingredient, the solar modules, can be produced rapidly and repeatedly in factories, and then assembled in a modular fashion.&lt;/p&gt;&#xA;&lt;p&gt;When possible we should try to build modules. We can then produce and assemble the modules in a repeatable process. This delivers value in stages. After we have completed a module, we can use the learnings to iterate on the module&amp;rsquo;s design and assembly process. So we should always ask ourselves:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;What&amp;rsquo;s our basic building block, the thing we will repeatedly make, becoming smarter and better each time. What&amp;rsquo;s our Lego?&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;additional-thoughts-about-the-book&#34; class=&#34;content-heading&#34;&gt;Additional thoughts about the book&#xA;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;incentives-and-identity&#34; class=&#34;content-heading&#34;&gt;Incentives and identity&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;There is a section in the book that discusses why the Heathrow Terminal 5 project was completed on time. The authors argue that a large part was the alignment of incentives between the project managers, the contractors, and the workers. Contractors were aligned via contractual bonuses and established working relationships. Workers were treated well, their feedback was actively encouraged, and they felt like they were contributing to a historic project in their country. Not part of the book, but the Notre-Dame reconstruction after the fire, was also accomplished on time. I believe that the history of the building, and the feeling of being part of a national project are very powerful motivators that aligned the participants of the project.&lt;/p&gt;&#xA;&lt;h3 id=&#34;cost-overruns-by-project-type&#34; class=&#34;content-heading&#34;&gt;Cost overruns by project type&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I found the table in the book that shows the mean cost overrun by category interesting.&lt;/p&gt;&#xA;&lt;p&gt;The table shows the mean (base rate) cost overrun for each project type, the fatness of the distribution (% of projects in the upper tail), and the cost overrun for projects in that tail.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th style=&#34;text-align: center&#34;&gt;Project type&lt;/th&gt;&#xA;          &lt;th style=&#34;text-align: center&#34;&gt;Mean cost overrun (%)&lt;/th&gt;&#xA;          &lt;th style=&#34;text-align: center&#34;&gt;% of projects in tail (&amp;gt;= 50% overrun)&lt;/th&gt;&#xA;          &lt;th style=&#34;text-align: center&#34;&gt;Mean overrun of projects in tail (%)&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Nuclear storage&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;238&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;48&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;427&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Olympic Games&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;157&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;76&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;200&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Nuclear power&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;120&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;55&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;204&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;IT&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;73&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;18&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;447&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;&amp;hellip;&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;&amp;hellip;&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;&amp;hellip;&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;&amp;hellip;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Buildings&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;62&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;39&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;206&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Rail&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;39&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;28&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;116&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Airport&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;39&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;43&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;88&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Tunnels&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;37&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;28&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;103&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;&amp;hellip;&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;&amp;hellip;&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;&amp;hellip;&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;&amp;hellip;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Wind energy&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;13&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;7&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;97&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Energy transmission&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;8&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;4&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;166&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;Solar power&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;1&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;2&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: center&#34;&gt;50&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;It makes sense that (non-standard, non-modular) nuclear projects have the highest base rate for cost increase. On the opposite side are wind energy and solar power projects, that can be pre-produced in factories and assembled on-site. Organising Olympic Games suffers from the fact that they are highly complex, and usually held in a city that hasn&amp;rsquo;t hosted them before (inexperience). As a tech worker, I am intrigued to see IT projects at the top of the list. Moreover, when IT projects overrun they incur a 447% cost overrun, the highest among all project types.&lt;/p&gt;&#xA;&lt;h3 id=&#34;learnings-for-software-projects&#34; class=&#34;content-heading&#34;&gt;Learnings for software projects&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;How applicable is the advice for day-to-day data and software projects? I think much of the advice applies. I found that chunking larger projects into small value-delivering modules is a great way to ensure continuous progress (especially in large refactoring projects).&lt;/p&gt;&#xA;&lt;p&gt;The emphasis on planning vs. building is probably not as relevant in normal day-to-day software projects. There is less of a cost difference between planning and building a feature (in both cases mostly the software engineers&amp;rsquo; time) compared to construction projects.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>LLM prompt heuristics that definitely maybe work</title>
      <link>https://staticnotes.org/posts/prompt-heuristics/</link>
      <pubDate>Fri, 11 Oct 2024 14:56:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/prompt-heuristics/</guid>
      <description>&lt;p&gt;Effective prompt writing for large language models continues to be a dark art. Having read the prompt engineering blogs from Meta, Anthropic, and OpenAI and watched some of Anthropic&amp;rsquo;s prompt discussions online, it does feel more like design than engineering. Even employees from the same lab don&amp;rsquo;t agree what tricks actually work. If you have time watch &lt;a href=&#34;https://www.youtube.com/watch?v=hkhDdcM5V94&amp;amp;pp=ygUqcHJvbXB0IGVuZ2luZWVyaW5nIG1hc3RlcmNsYXNzIGFpIGVuZ2luZWVy&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;this video&#xA;    &#xA;&#xA;        &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.9em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 448 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M549.7 124.1c-6.3-23.7-24.8-42.3-48.3-48.6C458.8 64 288 64 288 64S117.2 64 74.6 75.5c-23.5 6.3-42 24.9-48.3 48.6-11.4 42.9-11.4 132.3-11.4 132.3s0 89.4 11.4 132.3c6.3 23.7 24.8 41.5 48.3 47.8C117.2 448 288 448 288 448s170.8 0 213.4-11.5c23.5-6.3 42-24.2 48.3-47.8 11.4-42.9 11.4-132.3 11.4-132.3s0-89.4-11.4-132.3zm-317.5 213.5V175.2l142.7 81.2-142.7 81.2z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;&#xA;    &#xA;    &#xA;&lt;/a&gt; of one of Anthropic&amp;rsquo;s prompt engineers running a prompting masterclass. While giving good heuristics to the audience he is careful not to make any definite statements.&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t believe it is a good investment to try to become a world-class prompter. All heuristics are highly dependent on the model architecture, training data, and training procedure. This means that with every iteration of the models, heuristics could become obsolete or harmful to performance.&lt;/p&gt;&#xA;&lt;p&gt;However, the current attention-based architecture doesn&amp;rsquo;t seem to be going anywhere&#xA;soon. Therefore, it is reasonable to expect that we can continue to use the prompt context to help the model to move the embeddings of the user task into directions that contain a lot of nuance and information about the domain of the task.&lt;/p&gt;&#xA;&lt;p&gt;Therefore, I am collecting the advice into a few guidelines that I can use with the current models. I will caveat this by saying that in 90% of my use-cases the model response is parsed by a human: me. Therefore, I&#xA;am not as worried about hallucinations as someone that puts the model outputs in front of their customers or inside data parsing pipelines.&lt;/p&gt;&#xA;&lt;p&gt;Here is what seems to work in October 2024 with Claude Sonnet 3.5, GPT-4o, and&#xA;Llama 3.2.&lt;/p&gt;&#xA;&lt;h3 id=&#34;prompt-specificity&#34; class=&#34;content-heading&#34;&gt;Prompt specificity&#xA;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Make the prompt as specific to the task as you can. This is probably the&#xA;biggest return on your time. Good advice given in &lt;a href=&#34;https://www.youtube.com/watch?v=T9aRN5JkmL8&amp;amp;t=1769s&amp;amp;pp=ygUccHJvbXB0IGVuZ2luZWVyaW5nIGFudGhyb3BpYw%3D%3D&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;this discussion&#xA;    &#xA;&#xA;        &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.9em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 448 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M549.7 124.1c-6.3-23.7-24.8-42.3-48.3-48.6C458.8 64 288 64 288 64S117.2 64 74.6 75.5c-23.5 6.3-42 24.9-48.3 48.6-11.4 42.9-11.4 132.3-11.4 132.3s0 89.4 11.4 132.3c6.3 23.7 24.8 41.5 48.3 47.8C117.2 448 288 448 288 448s170.8 0 213.4-11.5c23.5-6.3 42-24.2 48.3-47.8 11.4-42.9 11.4-132.3 11.4-132.3s0-89.4-11.4-132.3zm-317.5 213.5V175.2l142.7 81.2-142.7 81.2z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;&#xA;    &#xA;    &#xA;&lt;/a&gt; is to&#xA;imagine printing out the prompt and giving it to a new hire at your company. Then see if they could solve the task. This forces you to give all necessary context and constraints of the task.&lt;/li&gt;&#xA;&lt;li&gt;Components of a role prompt: The role, its place in an organisation, its&#xA;perspective and the perspective of the person or organisation being addressed.&lt;/li&gt;&#xA;&lt;li&gt;No lazy role prompts. Make the role and the context clear.&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;Bad: You are a cab driver.&#xA;Good: You are a cab driver, driving people as your full-time job in London for twenty years and are knowledgeable about the city, its roads, and its sights. &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;If the model is used inside a product, tell it about it:&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;Bad: You are an assistant writing document summaries.&#xA;Good: You are an assistant used in a product for law firms that summarizes&#xA;legal documents.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;order-of-prompt-components&#34; class=&#34;content-heading&#34;&gt;Order of prompt components&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Order the components of your prompts in the following order:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Specific role and context description (put into system prompt if part of interactive&#xA;use of the model)&lt;/li&gt;&#xA;&lt;li&gt;Input data, e.g. documents, code snippets, CSV files&lt;/li&gt;&#xA;&lt;li&gt;Task description&lt;/li&gt;&#xA;&lt;li&gt;(Optional:) Good examples and bad examples&lt;/li&gt;&#xA;&lt;li&gt;Task constraints&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;use-xml-tags-for-prompt-components&#34; class=&#34;content-heading&#34;&gt;Use XML tags for prompt components&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Use XML tags to separate different components of a prompt.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;You are an experienced post-doc at a reputable research institute in the US. You are an expert in the research field of the following paper:&#xA;&#xA;&amp;lt;Research_paper&amp;gt;&#xA;{{research_paper}}  &#xA;&amp;lt;/Research_paper&amp;gt;&#xA;&#xA;Your task is to summarize the findings of the research paper given to you in&#xA;&amp;lt;Research_paper&amp;gt; tags.&#xA;&#xA;&amp;lt;Instructions&amp;gt;&#xA;- List between 1 - 5 most important findings of the paper. Don&amp;#39;t list more&#xA;  than 5 findings.&#xA;- more instructions...&#xA;&amp;lt;/Instructions&amp;gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;using-examples-few-shot-prompting&#34; class=&#34;content-heading&#34;&gt;Using examples (few shot prompting)&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;It can help to provide both good and bad examples for a specific task with an&#xA;explanation why they are good or bad. In the above example we could provide&#xA;an example research paper with a summary of findings we wrote ourselves as a&#xA;good example.&lt;/p&gt;&#xA;&lt;h3 id=&#34;instructions&#34; class=&#34;content-heading&#34;&gt;Instructions&#xA;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Response length limit. Instead of writing &amp;ldquo;Be concise&amp;rdquo;, tell the model what that means for your context, e.g. &amp;ldquo;Answer in no more than 4 sentences.&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;Avoid open-ended instructions.&lt;/li&gt;&#xA;&lt;li&gt;Instruct for style, formatting, and restrictions.&lt;/li&gt;&#xA;&lt;li&gt;Instruct to ask for sources of evidence to reduce hallucinations.&lt;/li&gt;&#xA;&lt;li&gt;Ask it to respond in a chain-of-thought to increase performance.&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;You are a logician and love to solve logic puzzles. Carefully read the following puzzle.&#xA;&#xA;&amp;lt;PUZZLE&amp;gt;&#xA;Simon is looking at Charlie. Charlie is looking at Sarah. You know that Simon is married and Sarah is not married. Is a married person looking at an unmarried person?&#xA;&amp;lt;/PUZZLE&amp;gt;&#xA;Let&amp;#39;s think step by step before giving an answer.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;grammar-and-style&#34; class=&#34;content-heading&#34;&gt;Grammar and style&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Avoid typos and wrong punctuation as that &lt;em&gt;can&lt;/em&gt; deteriorate the quality of the response.&lt;/p&gt;&#xA;&lt;h3 id=&#34;parse-able-output&#34; class=&#34;content-heading&#34;&gt;Parse-able output&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Often LLMs add a preamble at the beginning or an epilogue at the end of a response. If you want to force the model to respond only with valid json, you can:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Use the &amp;ldquo;Prefill Claude&amp;rsquo;s response&amp;rdquo; feature&lt;/li&gt;&#xA;&lt;li&gt;Ask the model to put the json into &lt;JSON&gt;&lt;/JSON&gt; tags and then extract that&#xA;block from the response&lt;/li&gt;&#xA;&lt;li&gt;Prefill the response yourself by adding at the end of your prompt: &lt;code&gt;Here is the JSON: {&lt;/code&gt;. The open bracket conditions the model to start the&#xA;answer with the first JSON key. You then need to prepend the &amp;ldquo;{&amp;rdquo; to the&#xA;response to make it valid.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;other-tricks&#34; class=&#34;content-heading&#34;&gt;Other tricks&#xA;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;If your prompt includes logic that could be handled in code, handle it in&#xA;code.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;Bad: You are part of a role-playing game that is used for training of customer support agents in a Fortune 500 company. &#xA;&#xA;You can assume any of the following roles based on user input. &#xA;&#xA;If the user asks for Role1 assume the role of a customer asking questions about the company&amp;#39;s products. If the user asks for Role2, assume the role of a helpful customer support agent.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;Good: Define two different prompts for each role and use code to switch&#xA;prompts based on what role the operator wants the model to assume.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Give the model a way out if it doesn&amp;rsquo;t know the answer.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;Good: {{prompt}}&#xA;If something weird happens and you are unsure about what to do, simply print out&#xA;&amp;#34;UNSURE&amp;#34;.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Use a temperature of 0 for fact-based, less creative tasks.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;iterative-prompt-design&#34; class=&#34;content-heading&#34;&gt;Iterative prompt design&#xA;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You can use the LLM to generate examples for a task and select the good&#xA;examples. Then use those examples in the prompt that is used &amp;ldquo;in production&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;If the model responds incorrectly, tell it about the mistake and ask it how&#xA;you should modify the prompt.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Processing 112M rows of steam reviews locally with DuckDB</title>
      <link>https://staticnotes.org/posts/duckdb-large-datasets/</link>
      <pubDate>Sat, 28 Sep 2024 13:43:40 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/duckdb-large-datasets/</guid>
      <description>&lt;p&gt;In &lt;a href=&#34;https://staticnotes.org/posts/duckdb-for-data-scientists/&#34; &#xA;&gt;DuckDB use cases for data scientists: Querying remote S3 files&#xA;&lt;/a&gt; I wrote about how I use DuckDB as a convenient way to query data from CSV or Parquet files in S3. Another use case for data scientists and data engineers is DuckDB&amp;rsquo;s ability to process larger-than-memory data on your local machine. For us data scientists this fills the gap between&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;small data that you can transform with pandas&lt;/li&gt;&#xA;&lt;li&gt;big data that typically requires a multi-node processing engine like PySpark.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In this post I am going to run some exploratory queries against this &lt;a href=&#34;https://www.kaggle.com/datasets/kieranpoc/steam-reviews/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;kaggle Steam review dataset&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. It contains 112M rows of Steam game reviews and comes as an uncompressed 46GB CSV file (17GB compressed). Let&amp;rsquo;s find out how my MacBook copes with it. Later I am going to run a small comparison against &lt;a href=&#34;https://docs.pola.rs/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;polars&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;, a DataFrame library, which is often mentioned for out-of-memory processing.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt;I am not comparing against pandas because its inability to work with large datasets was one of the reasons why I explored this topic. However, you could do this &lt;a href=&#34;https://pandas.pydata.org/docs/user_guide/scale.html#use-chunking&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;with chunking&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/small&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;useful-commands-and-settings&#34; class=&#34;content-heading&#34;&gt;Useful commands and settings&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Before I start, here are some useful DuckDB commands and settings that I often use:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Command&lt;/th&gt;&#xA;          &lt;th&gt;What is it good for?&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;.timer on&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Prints the execution time after each SQL command&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;FROM duckdb_memory();&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Gives an overview of how much memory is used by DuckDB&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;SET enable_progress_bar = true;&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Prints a progress bar for query runs&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;SET memory_limit = &#39;2GB&#39;;&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Controls how much data DuckDB can keep in RAM.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;.mode line&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Prints query results one at a time (useful if many columns). Default: &lt;code&gt;.mode duckbox&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;SUMMARIZE (select *)&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Summarizes the contents of a table.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;.exit&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Stops DuckDB.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;steam-review-dataset&#34; class=&#34;content-heading&#34;&gt;Steam review dataset&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;First, I want to familiarise myself with the dataset. I downloaded the 46GB file &lt;code&gt;all_reviews.csv&lt;/code&gt; to my 2023 MacBook Pro M3 with 18GB RAM. After starting a non-persistent session with the &lt;code&gt;duckdb&lt;/code&gt; command, I use the above commands to activate the timer and line mode. I then take a look at an example row with:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;all_reviews.csv&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ignore_errors&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;limit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;              recommendationid = 148919893&#xA;                         appid = 10&#xA;                          game = Counter-Strike&#xA;                author_steamid = 76561199036724879&#xA;        author_num_games_owned = 0&#xA;            author_num_reviews = 3&#xA;       author_playtime_forever = 197&#xA;author_playtime_last_two_weeks = 197&#xA;     author_playtime_at_review = 197&#xA;            author_last_played = 1698336369&#xA;                      language = russian&#xA;                        review = старость&#xA;             timestamp_created = 1698336397&#xA;             timestamp_updated = 1698336397&#xA;                      voted_up = 1&#xA;                      votes_up = 0&#xA;                   votes_funny = 0&#xA;           weighted_vote_score = 0.0&#xA;                 comment_count = 0&#xA;                steam_purchase = 1&#xA;             received_for_free = 0&#xA;   written_during_early_access = 0&#xA;         hidden_in_steam_china = 1&#xA;          steam_china_location = &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;This gives me an overview of the file columns and an idea of their content.&lt;/p&gt;&#xA;&lt;h2 id=&#34;processing-the-file-directly&#34; class=&#34;content-heading&#34;&gt;Processing the file directly&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Rather than slowly loading all data into DuckDB, I want to test DuckDB&amp;rsquo;s stream processing capabilities. Instead of fully materialising the data in memory, the execution engine reads and processes the data in chunks.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt;This is a useful feature if you want to convert larger-than-memory files from one format to another format, e.g. CSV to Parquet. But that&amp;rsquo;s not what we are here for today.&lt;/small&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;p&gt;I am going to use two aggregation queries for my benchmark:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The first query counts the number of English reviews per steam account and sorts them from highest to lowest&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;D select author_steamid, &#xA;COUNT(*) AS num_reviews  &#xA;FROM read_csv(&amp;#39;all_reviews.csv&amp;#39;, ignore_errors = true)  &#xA;WHERE language = &amp;#39;english&amp;#39; &#xA;GROUP BY author_steamid &#xA;ORDER BY num_reviews DESC;&#xA;100% ▕████████████████████████████████████████████████████████████▏ &#xA;┌───────────────────┬─────────────┐&#xA;│  author_steamid   │ num_reviews │&#xA;│       int64       │    int64    │&#xA;├───────────────────┼─────────────┤&#xA;│ 76561198030784015 │        9674 │&#xA;│ 76561198024340430 │        5930 │&#xA;│ 76561198067298289 │        5534 │&#xA;│ 76561198094803808 │        4341 │&#xA;│ 76561198125392509 │        4124 │&#xA;│ 76561198027267313 │        4124 │&#xA;│ 76561197960373660 │        3350 │&#xA;│ 76561197970602587 │        3212 │&#xA;│ 76561197961017729 │        2810 │&#xA;│ 76561198155150242 │        2554 │&#xA;│ 76561198066590240 │        2490 │&#xA;│ 76561198045381877 │        2280 │&#xA;│ 76561198069159152 │        2216 │&#xA;│ 76561197960319772 │        1978 │&#xA;│ 76561198062813911 │        1940 │&#xA;│ 76561198025731804 │        1928 │&#xA;│ 76561198137285867 │        1898 │&#xA;│ 76561198043135631 │        1883 │&#xA;│ 76561198036629241 │        1875 │&#xA;│ 76561198055119582 │        1843 │&#xA;│         ·         │           · │&#xA;│         ·         │           · │&#xA;│         ·         │           · │&#xA;│ 76561198111175247 │           1 │&#xA;├───────────────────┴─────────────┤&#xA;│    15324507 rows (40 shown)     │&#xA;└─────────────────────────────────┘&#xA;Run Time (s): real 22.556 user 166.382276 sys 9.815767&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;This query processes the 112M rows in a surprisingly short 22.5s. The most active Steam user has written 9674 game reviews. You can find them &lt;a href=&#34;https://www.steamidfinder.com/lookup/76561198030784015/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I made the second query intentionally more complex. I filter for reviews that contain the word &lt;code&gt;love&lt;/code&gt; and I also compute the mean of the &lt;code&gt;votes_up&lt;/code&gt; score and the sum of the &lt;code&gt;votes_funny&lt;/code&gt; score for each user. I then filter the aggregation using &lt;code&gt;having&lt;/code&gt; for only users that have a &lt;code&gt;sum_votes_funny&lt;/code&gt; score of more than 100.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;terminal&#34;&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-terminal&#34; data-lang=&#34;terminal&#34;&gt;D SELECT author_steamid, &#xA;    COUNT(*) AS num_reviews,&#xA;    avg(votes_up) as mean_votes_up, &#xA;    sum(votes_funny) as sum_votes_funny,&#xA;    FROM read_csv(&amp;#39;all_reviews.csv&amp;#39;, ignore_errors = true) &#xA;    WHERE language = &amp;#39;english&amp;#39; and review LIKE &amp;#39;%love%&amp;#39;&#xA;    GROUP BY author_steamid &#xA;    having sum_votes_funny &amp;gt; 100 &#xA;    ORDER BY num_reviews DESC; &#xA;100% ▕████████████████████████████████████████████████████████████▏ &#xA;┌───────────────────┬─────────────┬────────────────────┬─────────────────┐&#xA;│  author_steamid   │ num_reviews │   mean_votes_up    │ sum_votes_funny │&#xA;│       int64       │    int64    │       double       │     int128      │&#xA;├───────────────────┼─────────────┼────────────────────┼─────────────────┤&#xA;│ 76561198155150242 │         777 │   1.09009009009009 │             362 │&#xA;│ 76561198042406453 │         665 │ 13.478195488721804 │             341 │&#xA;│ 76561198043135631 │         475 │ 2.9410526315789474 │             116 │&#xA;│ 76561198149437416 │         352 │ 1.2386363636363635 │             256 │&#xA;│ 76561198007343154 │         342 │  4.038011695906433 │             375 │&#xA;│ 76561198066590240 │         273 │  9.293040293040294 │             247 │&#xA;│ 76561197970314107 │         241 │  38.15767634854772 │             319 │&#xA;│ 76561197961017729 │         237 │ 10.278481012658228 │             251 │&#xA;│ 76561197981638563 │         231 │ 26.372294372294373 │             509 │&#xA;│ 76561197972040704 │         223 │  8.560538116591928 │             123 │&#xA;│ 76561197992694498 │         223 │   73.1390134529148 │             759 │&#xA;│ 76561197970761123 │         222 │ 22.603603603603602 │             150 │&#xA;│ 76561198043609914 │         217 │ 18.792626728110598 │             129 │&#xA;│ 76561198053422627 │         202 │  17.04950495049505 │             284 │&#xA;│ 76561198007888370 │         196 │  93.96938775510205 │            3345 │&#xA;│ 76561198040884867 │         191 │  38.41884816753927 │             509 │&#xA;│ 76561198817597644 │         166 │ 22.542168674698797 │             119 │&#xA;│ 76561198356141989 │         166 │ 19.246987951807228 │             216 │&#xA;│ 76561198031599084 │         165 │ 17.163636363636364 │             171 │&#xA;│ 76561198011647032 │         159 │  6.345911949685535 │             192 │&#xA;│         ·         │           · │                ·   │              ·  │&#xA;│         ·         │           · │                ·   │              ·  │&#xA;│         ·         │           · │                ·   │              ·  │&#xA;│ 76561198106232693 │           1 │               96.0 │             155 │&#xA;├───────────────────┴─────────────┴────────────────────┴─────────────────┤&#xA;│ 2383 rows (40 shown)                                         4 columns │&#xA;└────────────────────────────────────────────────────────────────────────┘&#xA;Run Time (s): real 26.648 user 213.432443 sys 7.281861&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;With ~26s this is on par with the previous query. User &lt;code&gt;76561198155150242&lt;/code&gt; used the word &amp;ldquo;love&amp;rdquo; in 777 reviews and collected 362 funny upvotes across their reviews.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;These timings show how incredibly convenient DuckDB is to analyse large datasets. &amp;lt;30s is still in the realm where I can interactively work with the dataset and explore different queries.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt;You can push DuckDB to the limit by using a blocking operator, e.g. a rank() window function. This query will be slow because the entire input needs to be buffered to compute the result.&lt;/small&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;p&gt;When I explore data it is more common that I work in a notebook instead of the CLI. Fortunately, I can run the same queries using the &lt;a href=&#34;https://duckdb.org/docs/guides/python/install&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;DuckDB Python client&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. In the next section I am going to compare it against polars, another relatively new kid on the block for out-of-memory analytics.&lt;/p&gt;&#xA;&lt;h2 id=&#34;working-in-a-jupyter-notebook&#34; class=&#34;content-heading&#34;&gt;Working in a Jupyter notebook&#xA;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;duckdb-python-client&#34; class=&#34;content-heading&#34;&gt;DuckDB Python client&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I am going to write the code to run the above queries using the &lt;code&gt;duckdb&lt;/code&gt; Python package and return the results as a &lt;code&gt;pandas&lt;/code&gt; dataframe.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;duckdb&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pandas&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pd&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Connect to DuckDB&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;duckdb&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;:memory:&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Define the queries&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;query1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;SELECT author_steamid, COUNT(*) AS num_reviews &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;FROM read_csv(&amp;#39;./steam_reviews/all_reviews/all_reviews.csv&amp;#39;, ignore_errors = true) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;WHERE language = &amp;#39;english&amp;#39; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;GROUP BY author_steamid &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;ORDER BY num_reviews DESC &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;query2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;SELECT author_steamid, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;COUNT(*) AS num_reviews,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;avg(votes_up) as mean_votes_up, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;sum(votes_funny) as sum_votes_funny,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;FROM read_csv(&amp;#39;./steam_reviews/all_reviews/all_reviews.csv&amp;#39;, ignore_errors = true) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;WHERE language = &amp;#39;english&amp;#39; and review LIKE &amp;#39;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%lo&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;ve%&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;GROUP BY author_steamid &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;having sum_votes_funny &amp;gt; 100 &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;ORDER BY num_reviews DESC &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;%%&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;timeit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Execute the query&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;result1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Convert the result to a pandas DataFrame&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;16.6 s ± 627 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;author_steamid&lt;/th&gt;&#xA;      &lt;th&gt;num_reviews&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;76561198030784015&lt;/td&gt;&#xA;      &lt;td&gt;9674&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;76561198024340430&lt;/td&gt;&#xA;      &lt;td&gt;5930&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;76561198067298289&lt;/td&gt;&#xA;      &lt;td&gt;5534&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;76561198094803808&lt;/td&gt;&#xA;      &lt;td&gt;4341&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;76561198027267313&lt;/td&gt;&#xA;      &lt;td&gt;4124&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;%%&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;timeit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Execute the query&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;result2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Convert the result to a pandas DataFrame&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;19.9 s ± 343 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;author_steamid&lt;/th&gt;&#xA;      &lt;th&gt;num_reviews&lt;/th&gt;&#xA;      &lt;th&gt;mean_votes_up&lt;/th&gt;&#xA;      &lt;th&gt;sum_votes_funny&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;76561198155150242&lt;/td&gt;&#xA;      &lt;td&gt;777&lt;/td&gt;&#xA;      &lt;td&gt;1.090090&lt;/td&gt;&#xA;      &lt;td&gt;362.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;76561198042406453&lt;/td&gt;&#xA;      &lt;td&gt;665&lt;/td&gt;&#xA;      &lt;td&gt;13.478195&lt;/td&gt;&#xA;      &lt;td&gt;341.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;76561198043135631&lt;/td&gt;&#xA;      &lt;td&gt;475&lt;/td&gt;&#xA;      &lt;td&gt;2.941053&lt;/td&gt;&#xA;      &lt;td&gt;116.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;76561198149437416&lt;/td&gt;&#xA;      &lt;td&gt;352&lt;/td&gt;&#xA;      &lt;td&gt;1.238636&lt;/td&gt;&#xA;      &lt;td&gt;256.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;76561198007343154&lt;/td&gt;&#xA;      &lt;td&gt;342&lt;/td&gt;&#xA;      &lt;td&gt;4.038012&lt;/td&gt;&#xA;      &lt;td&gt;375.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;Not surprisingly this gives the same results as the queries run from the CLI. Having the aggregated results as a pandas dataframe allows me to use it in downstream work. I don&amp;rsquo;t need to learn another syntax.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;## clear memory &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;gc&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;del&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;gc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;collect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;polars&#34; class=&#34;content-heading&#34;&gt;Polars&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Since polars is often brought up as a faster and better pandas, I want to do a performance comparison. Polars supports lazy dataframes, which allows me to define operations on the dataframe without loading it fully into memory first.&lt;/p&gt;&#xA;&lt;p&gt;Below are the two equivalent queries written using polars syntax.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;  &lt;span class=&#34;nn&#34;&gt;polars&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pl&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Create a lazy DataFrame&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_lazy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scan_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;./steam_reviews/all_reviews/all_reviews.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ignore_errors&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;%%&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Define the query using lazy operations&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;result_polars1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;df_lazy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;col&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;language&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;english&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;group_by&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;author_steamid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;agg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alias&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;num_reviews&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;num_reviews&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;descending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Execute the query and collect the results&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_polars1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result_polars1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;collect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_polars1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;CPU times: user 1min 3s, sys: 22.1 s, total: 1min 26s&#xA;Wall time: 2min 7s&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;style&gt;&#xA;.dataframe &gt; thead &gt; tr,&#xA;.dataframe &gt; tbody &gt; tr {&#xA;  text-align: right;&#xA;  white-space: pre-wrap;&#xA;}&#xA;&lt;/style&gt;&#xA;&lt;small&gt;shape: (5, 2)&lt;/small&gt;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;author_steamid&lt;/th&gt;&lt;th&gt;num_reviews&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;i64&lt;/td&gt;&lt;td&gt;u32&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;76561198030784015&lt;/td&gt;&lt;td&gt;9822&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;76561198024340430&lt;/td&gt;&lt;td&gt;5983&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;76561198067298289&lt;/td&gt;&lt;td&gt;5577&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;76561198094803808&lt;/td&gt;&lt;td&gt;4408&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;76561198125392509&lt;/td&gt;&lt;td&gt;4203&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;%%&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;result_polars2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;df_lazy&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;col&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;language&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;english&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;col&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;review&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;contains&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;love&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;group_by&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;author_steamid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;agg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alias&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;num_reviews&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;col&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;votes_up&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alias&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mean_votes_up&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;col&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;votes_funny&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alias&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sum_votes_funny&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;col&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sum_votes_funny&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;num_reviews&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;descending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Execute the query and collect the results&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_polars2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result_polars2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;collect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df_polars2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;timed exec&amp;gt;:9: DeprecationWarning: `pl.count()` is deprecated. Please use `pl.len()` instead.&#xA;&#xA;&#xA;CPU times: user 1min 21s, sys: 42.7 s, total: 2min 4s&#xA;Wall time: 5min 14s&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;style&gt;&#xA;.dataframe &gt; thead &gt; tr,&#xA;.dataframe &gt; tbody &gt; tr {&#xA;  text-align: right;&#xA;  white-space: pre-wrap;&#xA;}&#xA;&lt;/style&gt;&#xA;&lt;small&gt;shape: (5, 4)&lt;/small&gt;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;author_steamid&lt;/th&gt;&lt;th&gt;num_reviews&lt;/th&gt;&lt;th&gt;mean_votes_up&lt;/th&gt;&lt;th&gt;sum_votes_funny&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;i64&lt;/td&gt;&lt;td&gt;u32&lt;/td&gt;&lt;td&gt;f64&lt;/td&gt;&lt;td&gt;i64&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;76561198155150242&lt;/td&gt;&lt;td&gt;786&lt;/td&gt;&lt;td&gt;1.094148&lt;/td&gt;&lt;td&gt;369&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;76561198042406453&lt;/td&gt;&lt;td&gt;673&lt;/td&gt;&lt;td&gt;13.43685&lt;/td&gt;&lt;td&gt;345&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;76561198043135631&lt;/td&gt;&lt;td&gt;480&lt;/td&gt;&lt;td&gt;2.922917&lt;/td&gt;&lt;td&gt;116&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;76561198149437416&lt;/td&gt;&lt;td&gt;360&lt;/td&gt;&lt;td&gt;1.216667&lt;/td&gt;&lt;td&gt;256&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;76561198007343154&lt;/td&gt;&lt;td&gt;354&lt;/td&gt;&lt;td&gt;4.014124&lt;/td&gt;&lt;td&gt;381&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&#xA;&lt;p&gt;Now we can compare DuckDB vs. polars execution times for the two queries:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;wall time&lt;/th&gt;&#xA;          &lt;th&gt;DuckDB&lt;/th&gt;&#xA;          &lt;th&gt;polars&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;query 1&lt;/td&gt;&#xA;          &lt;td&gt;17s&lt;/td&gt;&#xA;          &lt;td&gt;2min 7s&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;query 2&lt;/td&gt;&#xA;          &lt;td&gt;20s&lt;/td&gt;&#xA;          &lt;td&gt;5min 14s&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;conclusion&#34; class=&#34;content-heading&#34;&gt;Conclusion&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;This investigation shows that DuckDB is a powerful and convenient tool to process larger-than-memory datasets on a single machine. As a data scientist this is useful, because I can focus on exploring the data in the early exploration phase. I don&amp;rsquo;t yet have to spend time setting up more complex tools or work on a remote machine. The quick comparison with polars also shows its speed advantages and that it can be used as a drop-in when aggregating data in Jupyter notebooks.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Interest rate expectations</title>
      <link>https://staticnotes.org/posts/interest-rate-expecations/</link>
      <pubDate>Sat, 14 Sep 2024 00:00:00 +0100</pubDate>
      
      <guid>https://staticnotes.org/posts/interest-rate-expecations/</guid>
      <description>&lt;p&gt;This morning, the top headline on the front page of my weekly newspaper was:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Bets rise on bumper rate cut by Fed&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Investors have sharply increased their bets on half percentage point interest rate cut by the Federal reserve next week as the US central bank prepares to lower borrowing cost for the first time in more than four years. Traders in swaps markets are pricing in a 43 percent chance the Fed will opt for a bumper cut in a bid to prevent high rates damaging the economy. -  &lt;em&gt;FT Weekend (14.9.2024)&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I often read news about expectations on how &lt;em&gt;the Fed&lt;/em&gt; will set interest rates. I have a vague sense that it is related to the price of some interest rate related futures. I just asked myself if I wanted to look up what the market expectation is next week, where would I actually go to look? This detail is regularly glossed over in news articles. It turns out that the maths behind the expectation approximation is fairly simple. Let us work it out.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-federal-funds-rate&#34; class=&#34;content-heading&#34;&gt;The Federal Funds Rate&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Banks are required to put a certain percentage of their deposits into accounts at a Federal Reserve Bank. This is to maintain liquidity to cover depositors&amp;rsquo; withdrawals in the short-term. This reserve requirement is loosely a percentage of the bank&amp;rsquo;s deposits at the end of the day averaged over a two-week period. If at the end of the day a bank has excess reserve balances it can lend it overnight to another bank that is undercapitalised. Banks do that a lot and negotiate an interest rate for this overnight loan. The weighted average of all these deals for the day is the effective federal funds rate (EFFR).&lt;/p&gt;&#xA;&lt;p&gt;The Fed&amp;rsquo;s federal funds rate (FFR) target range is set by the Federal Open Market Committee and is the desired range for the EFFR. While the Fed can&amp;rsquo;t directly impact the EFFR it can influence it via their own deposit interest rates or changes to the monetary supply. This tells us what today&amp;rsquo;s FFR range and EFFR are (both are published by the Fed). But how do we compute the market&amp;rsquo;s expectations on changes to the FFR range?&lt;/p&gt;&#xA;&lt;h2 id=&#34;federal-funds-futures&#34; class=&#34;content-heading&#34;&gt;Federal Funds Futures&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;We can infer the expectations of FFR range changes at the next committee meeting by looking into how FFR future contracts are priced. Those are traded on the Chicago Mercantile Exchange (CME). You can view the monthly future quotes on the &lt;a href=&#34;https://www.cmegroup.com/markets/interest-rates/stirs/30-day-federal-fund.quotes.html&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;CME website&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;These futures are used by banks and fixed-income portfolio managers to hedge against short-term interest rate fluctuations. The 30-day futures are monthly contracts that are settled on the last business day of every month. The contract price payable is the arithmetic mean of the daily EFFR during the contract month as &lt;a href=&#34;https://www.newyorkfed.org/markets/reference-rates/effr&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;reported by&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; the Federal Reserve Bank of New York, subtracted from 100. For example if the average interest rate was 3.5% for a given month, then the contract price would be 100 - 3.5 = $96.5. Unfortunately, the minimum contract size is the price times 4167, which for this example would be $96.5 * 4167 = $416,796.5. A bit too high for my personal hedging needs.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-do-the-federal-funds-futures-hold&#34; class=&#34;content-heading&#34;&gt;What do the Federal Funds Future(s) hold?&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Now that we know about the EFFR and Federal Funds futures, we can collect all ingredients to compute the expectations:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The current FFR range was set in the July meeting to 5.25% - 5.5%.&lt;/li&gt;&#xA;&lt;li&gt;The dates of the next committee meetings are published here on &lt;a href=&#34;https://www.federalreserve.gov/monetarypolicy/fomccalendars.htm&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;federalreserve.gov&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. The remaining meetings this year are scheduled for: 18.9.2024, 7.11.2024, 18.12.2024.&lt;/li&gt;&#xA;&lt;li&gt;The expected EFFR from the futures contracts for the month of the next committee meeting and the following month. For the remaining year they were on the 14.9.2024:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pandas&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pd&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DataFrame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;MONTH&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;09-2024&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;10-2024&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;11-2024&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;12-2024&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;PRICE&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;94.81&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;95.03&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;95.315&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;95.58&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;MEETING&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;18&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;18&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set_index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;MONTH&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;PRICE&lt;/th&gt;&#xA;      &lt;th&gt;MEETING&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;MONTH&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;09-2024&lt;/th&gt;&#xA;      &lt;td&gt;94.810&lt;/td&gt;&#xA;      &lt;td&gt;18.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;10-2024&lt;/th&gt;&#xA;      &lt;td&gt;95.030&lt;/td&gt;&#xA;      &lt;td&gt;NaN&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;11-2024&lt;/th&gt;&#xA;      &lt;td&gt;95.315&lt;/td&gt;&#xA;      &lt;td&gt;7.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;12-2024&lt;/th&gt;&#xA;      &lt;td&gt;95.580&lt;/td&gt;&#xA;      &lt;td&gt;18.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;The next month without a committee meeting is October. This means that October&amp;rsquo;s average EFFR can only be impacted by the September committee meeting. This means that the October future contract price of $95.03 is the expected average EFFR for October.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;r_october_avg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;10-2024&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;PRICE&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;r_september_avg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;09-2024&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;PRICE&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;It is also the expected EFFR on the last day of September (and the first day of November).&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;r_september_end&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r_october_avg&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;We are interested in the implied difference in EFFR at the beginning and the end of the month. If there is a difference, then this would imply that the FED committee changed the FFR range.&lt;/p&gt;&#xA;&lt;p&gt;Keep in mind that the contract price is the arithmetic mean of the realised EFFR on every day in September. Assume that the FED committee does lower the price on the 18th of the month, then we will have 18 days at a higher rate and 30-18 = 12 days at a lower rate. All of that is captured in the future price (the average EFFR) for September.&lt;/p&gt;&#xA;&lt;p&gt;Therefore we can use:&lt;/p&gt;&#xA;&lt;p&gt;\[&#xA;EFFR(\text{average of Sep}) = \frac{N}{30} EFFR(\text{start of Sep}) +\frac{30-N}{30} EFFR(\text{end of Sep})&#xA;\]&lt;/p&gt;&#xA;&lt;p&gt;\[&#xA;\Leftrightarrow EFFR(\text{start of Sep}) = \left( EFFR(\text{average of Sep}) - \frac{30-N}{30}\cdot EFFR(\text{end of Sep}))\right) \cdot \frac{30}{N}&#xA;\]&lt;/p&gt;&#xA;&lt;p&gt;where \(N\) is the number of days before the committee meeting in September.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;days_month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;30&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;days_before_meeting&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;09-2024&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;MEETING&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;days_after_meeting&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days_month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days_before_meeting&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;r_september_start&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r_september_avg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;days_after_meeting&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;days_month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r_september_end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;days_month&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;days_before_meeting&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;The expected EFFR for the start of September is &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r_september_start&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;%.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;The expected EFFR for the start of September is 5.34%.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Since today is the 14th of September, we can already look up the realised EFFR up until today. If today were the 25th of August, then we need to calculate the expected \(EFFR(\text{start of Sep})\) with the above formula.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;r_september_change&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r_september_end&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r_september_start&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Comparing the expected EFFR at beginning and end of month we have a delta of &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r_september_change&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;Comparing the expected EFFR at beginning and end of month we have a delta of -0.37.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The market&amp;rsquo;s expectation for September is that we will have 37bps lower EFFR at the end of the month. If we buy the futures contract today we will make money if the FED committee cuts the rate in such a way that the realised EFFR will decrease more than 37bps compared to the beginning of the month.&lt;/p&gt;&#xA;&lt;p&gt;Traditionally, the committee changes the FFR range by 25bps (however 50 and 100 basis point changes do occur, e.g. after 9/11, after the 2007-2008 housing market crash and during the COVID-19 pandemic).&lt;/p&gt;&#xA;&lt;p&gt;However, we can see that the market prices in a 37bps lower EFFR. This means we can calculate the probability of a 25bps cut vs. a 50bps cut.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;The price implies &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r_september_change&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; x 25bps rate cuts.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;The price implies 1.47 x 25bps rate cuts.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;probability_of_25_bps_cut&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r_september_change&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;This implies a probability of &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;probability_of_25_bps_cut&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;% that the committee announces a 25bps rate cut.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;This implies a probability of 53.33% that the committee announces a 25bps rate cut.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;probability_of_50_bps_cut&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r_september_change&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;This implies a probability of &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;probability_of_50_bps_cut&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;% that the committee announces a 50bps rate cut.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;This implies a probability of 46.67% that the committee announces a 50bps rate cut.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The calculation confirms the newspaper article&amp;rsquo;s claim that the rate decision is priced as a coin flip between a 25bps and a 50bps rate cut.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Update 18.9.2024&lt;/strong&gt;: The FOMC &lt;a href=&#34;https://www.federalreserve.gov/newsevents/pressreleases/monetary20240918a.htm&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;decided&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; on a 50bps cut to a target range of 4.75% - 5.0%.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-about-europe&#34; class=&#34;content-heading&#34;&gt;What about Europe?&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;If you are interested in the expectations for the interest rates set by the Bank of England, you can use &lt;a href=&#34;https://www.ice.com/products/66380299/One-Month-SONIA-Index-Futures&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;One Month SONIA Index Futures&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. Similarly, for the ECB interest rates expectations you can check &lt;a href=&#34;https://www.ice.com/products/83046794/ECB-Dated-ESTR-Futures&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;ECB Dated ESTR Futures&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;jupyter-notebook&#34; class=&#34;content-heading&#34;&gt;Jupyter Notebook&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;You can find the Jupyter notebook for this post &lt;a href=&#34;https://gitlab.com/frankRi89/blog/-/tree/main/notebooks/interest-rate-expectations&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Clearing up confusion around IPython, ipykernel, and Jupyter notebooks</title>
      <link>https://staticnotes.org/posts/jupyter-confusion/</link>
      <pubDate>Mon, 26 Aug 2024 00:00:00 +0100</pubDate>
      
      <guid>https://staticnotes.org/posts/jupyter-confusion/</guid>
      <description>&lt;p&gt;One of my big recurring time sinks while doing data science work used to be trying to get my colleagues&amp;rsquo; Jupyter notebooks to run on my machine. The main contributing factors:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;My team generally uses poetry environments to improve reproducibility, but sometimes dependencies aren&amp;rsquo;t specified&lt;/li&gt;&#xA;&lt;li&gt;I use VS code and the Jupyter extension to edit notebooks in VS code which requires more configuration than running the Jupyter web UI.&lt;/li&gt;&#xA;&lt;li&gt;I lacked a clear understanding of the differences between &lt;code&gt;IPython&lt;/code&gt;, &lt;code&gt;ipykernel&lt;/code&gt;, &lt;code&gt;jupyter&lt;/code&gt; and which Python environments are being used when running a notebook.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;So this is my attempt at a &lt;a href=&#34;https://www.swyx.io/friendcatchers&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;friendcatcher&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. I hope this saves you a few minutes the next time you run into similar issues.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-different-components&#34; class=&#34;content-heading&#34;&gt;The different components&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s distinguish the components that play a role in running a Jupyter notebook:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Jupyter Notebook platform&lt;/strong&gt;: A web-based interactive computing platform that supports different languages via different kernels, e.g. for Python (ipykernel), Julia (IJulia), R (IRKernel)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Jupyter notebook&lt;/strong&gt; (extension &lt;code&gt;.ipynb&lt;/code&gt;):  is a document in json format that holds metadata and cell code.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;IPython command shell&lt;/strong&gt;: The shell has two components:&#xA;&lt;ol&gt;&#xA;&lt;li&gt;An interactive Python shell. You can start it with &lt;code&gt;ipython&lt;/code&gt;. It&amp;rsquo;s like the default Python REPL but with enhanced features, e.g. object introspection, tab completion, input history, magic commands, etc.&lt;/li&gt;&#xA;&lt;li&gt;A Jupyter kernel &lt;code&gt;ipykernel&lt;/code&gt;. This is the backend process where user Python code runs and which can be connected to different frontends. One frontend is indeed the IPython shell, another one a Jupyter notebook. You can install &lt;code&gt;ipykernel&lt;/code&gt; as a standalone package into your Python environment.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;jupyter&lt;/code&gt; Python package&lt;/strong&gt;. This is a metapackage which installs the notebook, qtconsole, and ipykernel.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre class=&#34;mermaid&#34;&gt;graph TD;&#xA;&#xA;colab(Google Colab UI) &lt;--&gt; ipykernel(ipykernel)&#xA;vs(VS Code UI) &lt;--&gt; ipykernel&#xA;ui(jupyter notebook UI) &lt;--&gt;  server&#xA;server(jupyter server) &lt;--&gt;  ipykernel&#xA;ipykernel &lt;--&gt;  ipython[IPython] &#xA;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;jupyter-kernels-vs-shell-environment&#34; class=&#34;content-heading&#34;&gt;Jupyter kernels vs. shell environment&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;One source of confusion is that a Jupyter kernel can point to a different Python executable than your shell environment.&lt;/p&gt;&#xA;&lt;p&gt;To get an overview of available Jupyter executables you can use:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;List all available Jupyter executables in your system:&lt;/strong&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; -a jupyter&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;List all available Jupyter kernels:&lt;/strong&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ jupyter kernelspec list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Every Jupyter kernel folder includes a &lt;code&gt;kernel.json&lt;/code&gt; file that links to the Python executable that is being used. Note this can be different from the Python executable referenced by your current shell. Moreover, the shell environment of a Jupyter notebook uses the Python executable used to &lt;em&gt;launch&lt;/em&gt; the notebook.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Print path of currently used Python executable:&lt;/strong&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt; python&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;or in a notebook cell:&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;!type python&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Print path of Python executable of current kernel:&lt;/strong&gt;&#xA;In a notebook cell:&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;import sys&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sys.executable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;You can create new kernels using the &lt;code&gt;ipykernel&lt;/code&gt; package:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ python -m ipykernel install --user --name envname --display-name &lt;span class=&#34;s2&#34;&gt;&amp;#34;Python (envname)&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h2 id=&#34;dependency-management&#34; class=&#34;content-heading&#34;&gt;Dependency management&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Since I use VS Code as my frontend I just need to add the &lt;code&gt;ipykernel&lt;/code&gt; package into the virtual environment that I use to manage all other dependencies used to run the notebook. This ensures that the same Python executable is used for the kernel and the shell environment.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt;This is well explained &lt;a href=&#34;https://jakevdp.github.io/blog/2017/12/05/installing-python-packages-from-jupyter/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/small&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;p&gt;These are the steps to create a new environment for a Jupyter notebook:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Create project folder:&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ mkdir notebook_project&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Create new virtual environment in the folder, then activate it&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; notebook_project&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ python3 -m venv .venv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; .venv/bin/activate&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Install &lt;code&gt;ipykernel&lt;/code&gt; (and other dependencies) using pip (make sure the venv is activated):&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ python3 -m pip install ipykernel&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ python3 -m pip install pandas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Create a new notebook&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ touch mynotebook.ipynb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Open notebook in VS Code and in the top right corner select &lt;code&gt;Select Kernel&lt;/code&gt; &amp;ndash;&amp;gt; &lt;code&gt;Python Environment&lt;/code&gt; &amp;ndash;&amp;gt; &lt;code&gt;.venv (.venv/bin/python)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;You should now be able to run the notebook and use the pandas package inside the notebook.&lt;/li&gt;&#xA;&lt;li&gt;To add new dependencies:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Use the terminal: &lt;code&gt;$ python3 -m pip install &amp;lt;package_name&amp;gt;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Install from within a notebook cell:&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sys&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;executable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pip&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;install&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;package_name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Specify your dependencies in a &lt;code&gt;requirements.txt&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;I use &lt;a href=&#34;https://python-poetry.org/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;poetry&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; for virtual environments and dependency management. So in step 2 I would instead use:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; notebook_project&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ poetry init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;and install packages via:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ poetry add ipykernel&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ poetry add pandas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;If I want to use the default Jupyter UI, I can install the &lt;code&gt;jupyter&lt;/code&gt;  metapackage into my environment and then start the UI with:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;bash&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ poetry add jupyter&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ poetry run jupyter notebook&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://jakevdp.github.io/blog/2017/12/05/installing-python-packages-from-jupyter/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;https://jakevdp.github.io/blog/2017/12/05/installing-python-packages-from-jupyter/&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://code.visualstudio.com/docs/datascience/jupyter-kernel-management&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;https://code.visualstudio.com/docs/datascience/jupyter-kernel-management&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.jupyter.org/en/latest/projects/architecture/content-architecture.html&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;https://docs.jupyter.org/en/latest/projects/architecture/content-architecture.html&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Analysing the Vätternrundan 2024 cycling results</title>
      <link>https://staticnotes.org/posts/vatternrundan-results/</link>
      <pubDate>Sat, 03 Aug 2024 00:00:00 +0100</pubDate>
      
      <guid>https://staticnotes.org/posts/vatternrundan-results/</guid>
      <description>&lt;p&gt;In 2024, I was foolish enough to participate in the &lt;a href=&#34;https://vatternrundan.se/en/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Vätternrundan&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;, which is a 315km distance bike sportive around Sweden&amp;rsquo;s second biggest lake. It took me and my friends a little less than 11.5 hours of cycling (15h including breaks).&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;vatternrundan_map_lake.jpg&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;600px&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/vatternrundan-results/output_2_0.jpg&#34; alt=&#34;jpeg&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;The above image shows the route. The event starts and ends in Motala (the big black dot on the map) and the riders ride clock-wise around the lake.&lt;/p&gt;&#xA;&lt;p&gt;Since this event is a &lt;a href=&#34;https://en.wikipedia.org/wiki/Cyclosportive&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;sportive&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; the organizers only publish finishing times via a bib number search on &lt;a href=&#34;https://vatternrundan.se/en/participants-results/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;their website&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. However, I was curious to understand how well my group did overall.&#xA;To get my hands on the data I wrote a small scraping script to collect all finish times from the results page.&lt;/p&gt;&#xA;&lt;p&gt;With this data I then analyse:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;summary statistics about the participants, e.g. what countries had a lot of starters?&lt;/li&gt;&#xA;&lt;li&gt;distribution of race times, e.g. how fast is the median rider?&lt;/li&gt;&#xA;&lt;li&gt;what percentage of people finished the race&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;scraping-the-dataset&#34; class=&#34;content-heading&#34;&gt;Scraping the dataset&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Since getting the timing information from the results page involves several clicks for each start number, I had to write a script that can click through the browser pages. I use &lt;a href=&#34;https://www.selenium.dev/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;selenium&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; for the browser automation. The script performs the actions for each start number between 1 and 30,000 and collects the timing information. Some start numbers are not used and many people didn&amp;rsquo;t finish the race. All the data is stored in a single parquet file that is used for the data analysis in the next section. I had to do some light data cleaning, e.g. converting scraped strings to &lt;code&gt;timedelta&lt;/code&gt;, removing data for unused startnumbers, etc.&lt;/p&gt;&#xA;&lt;h2 id=&#34;loading-the-dataset&#34; class=&#34;content-heading&#34;&gt;Loading the dataset&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;First, I load the data from the parquet file into a pandas dataframe. I then perform a few data cleaning steps to make the dataset easier to use.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pandas&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pd&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;numpy&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;np&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;dt&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;plt&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;seaborn&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sns&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;matplotlib.ticker&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FuncFormatter&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;IPython.display&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;results_vatternrundan24.parquet&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time_minutes&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;average_speed&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time_minutes&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;315&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isna&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;timing_consistent&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;The dataset contains &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; entries.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;The dataset contains 15813 entries.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;analysing-the-dataset&#34; class=&#34;content-heading&#34;&gt;Analysing the dataset&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;The dataset has the following columns:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;startnumber&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;initials&lt;/code&gt;: initials of the rider&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;club&lt;/code&gt;: club of the rider&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;city&lt;/code&gt;: home city of the rider&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;country&lt;/code&gt;: home country of the rider&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;result_time&lt;/code&gt;: full duration between crossing start and finish lines (includes breaks at food stations)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;average_speed&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;is_sub9&lt;/code&gt;: whether the rider was part of a sub9 group that started later in the day (after 11:30 on Saturday)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;has_finished&lt;/code&gt;: a boolean whether a rider completed the event or dropped out&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;You can see a few example rows of rider information below:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;startnumber&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;initials&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;club&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;city&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;average_speed&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dtypes&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;startnumber&lt;/th&gt;&#xA;      &lt;th&gt;initials&lt;/th&gt;&#xA;      &lt;th&gt;club&lt;/th&gt;&#xA;      &lt;th&gt;city&lt;/th&gt;&#xA;      &lt;th&gt;country&lt;/th&gt;&#xA;      &lt;th&gt;result_time&lt;/th&gt;&#xA;      &lt;th&gt;average_speed&lt;/th&gt;&#xA;      &lt;th&gt;has_finished&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;40&lt;/th&gt;&#xA;      &lt;td&gt;5121&lt;/td&gt;&#xA;      &lt;td&gt;JK&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;Mantorp&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;0 days 15:11:00&lt;/td&gt;&#xA;      &lt;td&gt;20.746432&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;41&lt;/th&gt;&#xA;      &lt;td&gt;5122&lt;/td&gt;&#xA;      &lt;td&gt;MI&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;Skärblacka&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;0 days 15:11:00&lt;/td&gt;&#xA;      &lt;td&gt;20.746432&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;42&lt;/th&gt;&#xA;      &lt;td&gt;5123&lt;/td&gt;&#xA;      &lt;td&gt;TP&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;Höör&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;0 days 14:35:00&lt;/td&gt;&#xA;      &lt;td&gt;21.600000&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;43&lt;/th&gt;&#xA;      &lt;td&gt;5124&lt;/td&gt;&#xA;      &lt;td&gt;KH&lt;/td&gt;&#xA;      &lt;td&gt;Trimgutta&lt;/td&gt;&#xA;      &lt;td&gt;Løvenstad&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 14:47:00&lt;/td&gt;&#xA;      &lt;td&gt;21.307779&lt;/td&gt;&#xA;      &lt;td&gt;True&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;44&lt;/th&gt;&#xA;      &lt;td&gt;5125&lt;/td&gt;&#xA;      &lt;td&gt;HN&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;Jessheim&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;NaT&lt;/td&gt;&#xA;      &lt;td&gt;NaN&lt;/td&gt;&#xA;      &lt;td&gt;False&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;startnumber                      int64&#xA;initials                        object&#xA;club                            object&#xA;city                            object&#xA;country                         object&#xA;result_time            timedelta64[ns]&#xA;start_time                      object&#xA;station_records                 object&#xA;timing_consistent                 bool&#xA;is_sub9                           bool&#xA;result_time_minutes            float64&#xA;average_speed                  float64&#xA;has_finished                      bool&#xA;dtype: object&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;the-riders&#34; class=&#34;content-heading&#34;&gt;The riders&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s first look at the top countries, cities, and clubs that are in this dataset. Not surprisingly, Sweden (SE) has the most participants, followed by Germany (DE), Norway (NO), and Finland (FI).&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;groupby&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;agg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_starters&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;startnumber&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;count&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_finishers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;sum&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;perc_finished&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;mean&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mean_result_time&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;mean&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fastest_finisher&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;min&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;num_starters&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ascending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;num_starters&lt;/th&gt;&#xA;      &lt;th&gt;num_finishers&lt;/th&gt;&#xA;      &lt;th&gt;perc_finished&lt;/th&gt;&#xA;      &lt;th&gt;mean_result_time&lt;/th&gt;&#xA;      &lt;th&gt;fastest_finisher&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;country&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;SE&lt;/th&gt;&#xA;      &lt;td&gt;12035&lt;/td&gt;&#xA;      &lt;td&gt;9904&lt;/td&gt;&#xA;      &lt;td&gt;0.822933&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:38:44.486094316&lt;/td&gt;&#xA;      &lt;td&gt;0 days 05:15:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;DE&lt;/th&gt;&#xA;      &lt;td&gt;1437&lt;/td&gt;&#xA;      &lt;td&gt;1174&lt;/td&gt;&#xA;      &lt;td&gt;0.816980&lt;/td&gt;&#xA;      &lt;td&gt;0 days 14:30:54.331914893&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:37:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;NO&lt;/th&gt;&#xA;      &lt;td&gt;846&lt;/td&gt;&#xA;      &lt;td&gt;658&lt;/td&gt;&#xA;      &lt;td&gt;0.777778&lt;/td&gt;&#xA;      &lt;td&gt;0 days 11:15:29.272727272&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:16:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;FI&lt;/th&gt;&#xA;      &lt;td&gt;402&lt;/td&gt;&#xA;      &lt;td&gt;335&lt;/td&gt;&#xA;      &lt;td&gt;0.833333&lt;/td&gt;&#xA;      &lt;td&gt;0 days 12:56:00.537313432&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:09:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;DK&lt;/th&gt;&#xA;      &lt;td&gt;346&lt;/td&gt;&#xA;      &lt;td&gt;281&lt;/td&gt;&#xA;      &lt;td&gt;0.812139&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:24:26.501766784&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:57:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;GB&lt;/th&gt;&#xA;      &lt;td&gt;269&lt;/td&gt;&#xA;      &lt;td&gt;194&lt;/td&gt;&#xA;      &lt;td&gt;0.721190&lt;/td&gt;&#xA;      &lt;td&gt;0 days 14:24:04.307692307&lt;/td&gt;&#xA;      &lt;td&gt;0 days 02:54:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;NL&lt;/th&gt;&#xA;      &lt;td&gt;87&lt;/td&gt;&#xA;      &lt;td&gt;77&lt;/td&gt;&#xA;      &lt;td&gt;0.885057&lt;/td&gt;&#xA;      &lt;td&gt;0 days 14:25:03.896103896&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:53:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;td&gt;43&lt;/td&gt;&#xA;      &lt;td&gt;36&lt;/td&gt;&#xA;      &lt;td&gt;0.837209&lt;/td&gt;&#xA;      &lt;td&gt;0 days 15:36:35&lt;/td&gt;&#xA;      &lt;td&gt;0 days 09:01:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;US&lt;/th&gt;&#xA;      &lt;td&gt;38&lt;/td&gt;&#xA;      &lt;td&gt;25&lt;/td&gt;&#xA;      &lt;td&gt;0.657895&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:39:55.384615384&lt;/td&gt;&#xA;      &lt;td&gt;0 days 09:19:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;PL&lt;/th&gt;&#xA;      &lt;td&gt;38&lt;/td&gt;&#xA;      &lt;td&gt;30&lt;/td&gt;&#xA;      &lt;td&gt;0.789474&lt;/td&gt;&#xA;      &lt;td&gt;0 days 12:52:26&lt;/td&gt;&#xA;      &lt;td&gt;0 days 09:20:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;The cities with most participants are all Swedish: Stockholm, Göteborg, Linköping, Uppsala, Malmö.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;groupby&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;city&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;agg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_starters&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;startnumber&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;count&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_finishers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;sum&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;perc_finished&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;mean&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mean_result_time&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;mean&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fastest_finisher&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;min&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;num_starters&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ascending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;num_starters&lt;/th&gt;&#xA;      &lt;th&gt;num_finishers&lt;/th&gt;&#xA;      &lt;th&gt;perc_finished&lt;/th&gt;&#xA;      &lt;th&gt;mean_result_time&lt;/th&gt;&#xA;      &lt;th&gt;fastest_finisher&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;city&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Stockholm&lt;/th&gt;&#xA;      &lt;td&gt;851&lt;/td&gt;&#xA;      &lt;td&gt;726&lt;/td&gt;&#xA;      &lt;td&gt;0.853114&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:37:09.752066115&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:31:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Göteborg&lt;/th&gt;&#xA;      &lt;td&gt;613&lt;/td&gt;&#xA;      &lt;td&gt;516&lt;/td&gt;&#xA;      &lt;td&gt;0.841762&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:30:09.266409266&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:35:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Linköping&lt;/th&gt;&#xA;      &lt;td&gt;378&lt;/td&gt;&#xA;      &lt;td&gt;313&lt;/td&gt;&#xA;      &lt;td&gt;0.828042&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:48:16.815286624&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:31:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Uppsala&lt;/th&gt;&#xA;      &lt;td&gt;323&lt;/td&gt;&#xA;      &lt;td&gt;268&lt;/td&gt;&#xA;      &lt;td&gt;0.829721&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:50:19.029850746&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:37:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Malmö&lt;/th&gt;&#xA;      &lt;td&gt;233&lt;/td&gt;&#xA;      &lt;td&gt;191&lt;/td&gt;&#xA;      &lt;td&gt;0.819742&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:52:36.125654450&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:31:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Örebro&lt;/th&gt;&#xA;      &lt;td&gt;230&lt;/td&gt;&#xA;      &lt;td&gt;184&lt;/td&gt;&#xA;      &lt;td&gt;0.800000&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:34:19.677419354&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:19:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Motala&lt;/th&gt;&#xA;      &lt;td&gt;223&lt;/td&gt;&#xA;      &lt;td&gt;186&lt;/td&gt;&#xA;      &lt;td&gt;0.834081&lt;/td&gt;&#xA;      &lt;td&gt;0 days 14:07:49.354838709&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:35:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Västerås&lt;/th&gt;&#xA;      &lt;td&gt;186&lt;/td&gt;&#xA;      &lt;td&gt;142&lt;/td&gt;&#xA;      &lt;td&gt;0.763441&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:25:54.929577464&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:37:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Lund&lt;/th&gt;&#xA;      &lt;td&gt;168&lt;/td&gt;&#xA;      &lt;td&gt;138&lt;/td&gt;&#xA;      &lt;td&gt;0.821429&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:56:18.260869565&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:16:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Jönköping&lt;/th&gt;&#xA;      &lt;td&gt;147&lt;/td&gt;&#xA;      &lt;td&gt;124&lt;/td&gt;&#xA;      &lt;td&gt;0.843537&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:49:49.354838709&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:55:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;The following clubs had the most riders.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;groupby&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;club&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;agg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;city&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;city&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;first&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_starters&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;startnumber&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;count&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_finishers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;sum&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;perc_finished&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;mean&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mean_result_time&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;mean&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fastest_finisher&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;min&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;num_starters&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ascending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;city&lt;/th&gt;&#xA;      &lt;th&gt;num_starters&lt;/th&gt;&#xA;      &lt;th&gt;num_finishers&lt;/th&gt;&#xA;      &lt;th&gt;perc_finished&lt;/th&gt;&#xA;      &lt;th&gt;mean_result_time&lt;/th&gt;&#xA;      &lt;th&gt;fastest_finisher&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;club&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;IMOVEFORCANCER&lt;/th&gt;&#xA;      &lt;td&gt;Karlskrona&lt;/td&gt;&#xA;      &lt;td&gt;69&lt;/td&gt;&#xA;      &lt;td&gt;58&lt;/td&gt;&#xA;      &lt;td&gt;0.840580&lt;/td&gt;&#xA;      &lt;td&gt;0 days 09:54:26.896551724&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:37:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Fredrikshof&lt;/th&gt;&#xA;      &lt;td&gt;Stockholm&lt;/td&gt;&#xA;      &lt;td&gt;56&lt;/td&gt;&#xA;      &lt;td&gt;48&lt;/td&gt;&#xA;      &lt;td&gt;0.857143&lt;/td&gt;&#xA;      &lt;td&gt;0 days 10:46:42.500000&lt;/td&gt;&#xA;      &lt;td&gt;0 days 09:20:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Örebrocyklisterna&lt;/th&gt;&#xA;      &lt;td&gt;Kumla&lt;/td&gt;&#xA;      &lt;td&gt;55&lt;/td&gt;&#xA;      &lt;td&gt;42&lt;/td&gt;&#xA;      &lt;td&gt;0.763636&lt;/td&gt;&#xA;      &lt;td&gt;0 days 11:31:47.142857142&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:04:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Team Kungälv&lt;/th&gt;&#xA;      &lt;td&gt;Kungälv&lt;/td&gt;&#xA;      &lt;td&gt;43&lt;/td&gt;&#xA;      &lt;td&gt;29&lt;/td&gt;&#xA;      &lt;td&gt;0.674419&lt;/td&gt;&#xA;      &lt;td&gt;0 days 10:37:20&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:53:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;schulz sportreisen&lt;/th&gt;&#xA;      &lt;td&gt;Dresden&lt;/td&gt;&#xA;      &lt;td&gt;40&lt;/td&gt;&#xA;      &lt;td&gt;36&lt;/td&gt;&#xA;      &lt;td&gt;0.900000&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:47:45&lt;/td&gt;&#xA;      &lt;td&gt;0 days 10:20:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;KCE - Kävlinge Cykelentusiaster&lt;/th&gt;&#xA;      &lt;td&gt;Kävlinge&lt;/td&gt;&#xA;      &lt;td&gt;38&lt;/td&gt;&#xA;      &lt;td&gt;32&lt;/td&gt;&#xA;      &lt;td&gt;0.842105&lt;/td&gt;&#xA;      &lt;td&gt;0 days 11:50:01.875000&lt;/td&gt;&#xA;      &lt;td&gt;0 days 09:41:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Fredrikshofs IF Cykelklubb&lt;/th&gt;&#xA;      &lt;td&gt;Enskede&lt;/td&gt;&#xA;      &lt;td&gt;35&lt;/td&gt;&#xA;      &lt;td&gt;30&lt;/td&gt;&#xA;      &lt;td&gt;0.857143&lt;/td&gt;&#xA;      &lt;td&gt;0 days 11:29:52&lt;/td&gt;&#xA;      &lt;td&gt;0 days 09:44:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Försvarsmakten&lt;/th&gt;&#xA;      &lt;td&gt;Örebro&lt;/td&gt;&#xA;      &lt;td&gt;32&lt;/td&gt;&#xA;      &lt;td&gt;29&lt;/td&gt;&#xA;      &lt;td&gt;0.906250&lt;/td&gt;&#xA;      &lt;td&gt;0 days 13:51:00&lt;/td&gt;&#xA;      &lt;td&gt;0 days 09:21:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Team Sportia Uppsala&lt;/th&gt;&#xA;      &lt;td&gt;Uppsala&lt;/td&gt;&#xA;      &lt;td&gt;31&lt;/td&gt;&#xA;      &lt;td&gt;29&lt;/td&gt;&#xA;      &lt;td&gt;0.935484&lt;/td&gt;&#xA;      &lt;td&gt;0 days 10:50:47.586206896&lt;/td&gt;&#xA;      &lt;td&gt;0 days 09:24:00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;number-of-finishers&#34; class=&#34;content-heading&#34;&gt;Number of finishers&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;315km is a long event. Let&amp;rsquo;s check how many of the participants finished the event:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;num_starters&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;num_finishers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shape&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Among the &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_starters&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; starting riders in the dataset, we found recorded and consistent finishing times for &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_finishers&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;. &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;This is a finishing rate of &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_finishers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_starters&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;%.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;Among the 15813 starting riders in the dataset, we found recorded and consistent finishing times for 12920. This is a finishing rate of 81.70%.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;the-podium-and-top-10&#34; class=&#34;content-heading&#34;&gt;The podium and top 10&#xA;&lt;/h3&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;fastest_rider&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;The fastest rider &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fastest_rider&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;initials&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; from &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fastest_rider&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;city&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; only needed &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;timedelta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microseconds&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fastest_rider&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; to complete the 315km. &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;That is a mindblowing average speed of &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fastest_rider&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;average_speed&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;.1f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; km/h.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;The fastest rider JL from Lund only needed 7:16:00 to complete the 315km. That is a mindblowing average speed of 43.3 km/h.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The 10 fastest riders were below 7h 32min.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)[[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;startnumber&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;initials&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;city&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;club&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;average_speed&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ascending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;startnumber&lt;/th&gt;&#xA;      &lt;th&gt;initials&lt;/th&gt;&#xA;      &lt;th&gt;city&lt;/th&gt;&#xA;      &lt;th&gt;club&lt;/th&gt;&#xA;      &lt;th&gt;country&lt;/th&gt;&#xA;      &lt;th&gt;result_time&lt;/th&gt;&#xA;      &lt;th&gt;average_speed&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16311&lt;/th&gt;&#xA;      &lt;td&gt;27012&lt;/td&gt;&#xA;      &lt;td&gt;JL&lt;/td&gt;&#xA;      &lt;td&gt;Lund&lt;/td&gt;&#xA;      &lt;td&gt;Kjekkas IF&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:16:00&lt;/td&gt;&#xA;      &lt;td&gt;43.348624&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16301&lt;/th&gt;&#xA;      &lt;td&gt;27002&lt;/td&gt;&#xA;      &lt;td&gt;TJ&lt;/td&gt;&#xA;      &lt;td&gt;Slattum&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:16:00&lt;/td&gt;&#xA;      &lt;td&gt;43.348624&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16304&lt;/th&gt;&#xA;      &lt;td&gt;27005&lt;/td&gt;&#xA;      &lt;td&gt;EO&lt;/td&gt;&#xA;      &lt;td&gt;Nittedal&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:16:00&lt;/td&gt;&#xA;      &lt;td&gt;43.348624&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16308&lt;/th&gt;&#xA;      &lt;td&gt;27009&lt;/td&gt;&#xA;      &lt;td&gt;BHB&lt;/td&gt;&#xA;      &lt;td&gt;Follebu&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:16:00&lt;/td&gt;&#xA;      &lt;td&gt;43.348624&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16310&lt;/th&gt;&#xA;      &lt;td&gt;27011&lt;/td&gt;&#xA;      &lt;td&gt;DT&lt;/td&gt;&#xA;      &lt;td&gt;Oslo&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:16:00&lt;/td&gt;&#xA;      &lt;td&gt;43.348624&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16316&lt;/th&gt;&#xA;      &lt;td&gt;27017&lt;/td&gt;&#xA;      &lt;td&gt;JK&lt;/td&gt;&#xA;      &lt;td&gt;Lillehammer&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:16:00&lt;/td&gt;&#xA;      &lt;td&gt;43.348624&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16314&lt;/th&gt;&#xA;      &lt;td&gt;27015&lt;/td&gt;&#xA;      &lt;td&gt;SD&lt;/td&gt;&#xA;      &lt;td&gt;Oslo - Norway&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:16:00&lt;/td&gt;&#xA;      &lt;td&gt;43.348624&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16781&lt;/th&gt;&#xA;      &lt;td&gt;27482&lt;/td&gt;&#xA;      &lt;td&gt;HD&lt;/td&gt;&#xA;      &lt;td&gt;Kalmar&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:31:00&lt;/td&gt;&#xA;      &lt;td&gt;41.906874&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16782&lt;/th&gt;&#xA;      &lt;td&gt;27483&lt;/td&gt;&#xA;      &lt;td&gt;TE&lt;/td&gt;&#xA;      &lt;td&gt;Rockneby&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:31:00&lt;/td&gt;&#xA;      &lt;td&gt;41.906874&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16783&lt;/th&gt;&#xA;      &lt;td&gt;27484&lt;/td&gt;&#xA;      &lt;td&gt;JL&lt;/td&gt;&#xA;      &lt;td&gt;Ekerö&lt;/td&gt;&#xA;      &lt;td&gt;-&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;0 days 07:31:00&lt;/td&gt;&#xA;      &lt;td&gt;41.906874&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;The 10 fastest riders that didn&amp;rsquo;t ride as part of a sub-9 registered team were:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished and not is_sub9&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)[[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;startnumber&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;initials&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;city&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;club&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;average_speed&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ascending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;startnumber&lt;/th&gt;&#xA;      &lt;th&gt;initials&lt;/th&gt;&#xA;      &lt;th&gt;city&lt;/th&gt;&#xA;      &lt;th&gt;club&lt;/th&gt;&#xA;      &lt;th&gt;country&lt;/th&gt;&#xA;      &lt;th&gt;result_time&lt;/th&gt;&#xA;      &lt;th&gt;average_speed&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;8860&lt;/th&gt;&#xA;      &lt;td&gt;16661&lt;/td&gt;&#xA;      &lt;td&gt;MN&lt;/td&gt;&#xA;      &lt;td&gt;Haslum&lt;/td&gt;&#xA;      &lt;td&gt;Team Tøff i Tryne&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:02:00&lt;/td&gt;&#xA;      &lt;td&gt;39.211618&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;8850&lt;/th&gt;&#xA;      &lt;td&gt;16651&lt;/td&gt;&#xA;      &lt;td&gt;HL&lt;/td&gt;&#xA;      &lt;td&gt;Oslo&lt;/td&gt;&#xA;      &lt;td&gt;Team Tøff i Trynet&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:02:00&lt;/td&gt;&#xA;      &lt;td&gt;39.211618&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;28298&lt;/th&gt;&#xA;      &lt;td&gt;18529&lt;/td&gt;&#xA;      &lt;td&gt;MS&lt;/td&gt;&#xA;      &lt;td&gt;Otalampi&lt;/td&gt;&#xA;      &lt;td&gt;Team Wassu&lt;/td&gt;&#xA;      &lt;td&gt;FI&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:12:00&lt;/td&gt;&#xA;      &lt;td&gt;38.414634&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;28297&lt;/th&gt;&#xA;      &lt;td&gt;18528&lt;/td&gt;&#xA;      &lt;td&gt;JK&lt;/td&gt;&#xA;      &lt;td&gt;Kotka&lt;/td&gt;&#xA;      &lt;td&gt;Team Wassu&lt;/td&gt;&#xA;      &lt;td&gt;FI&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:12:00&lt;/td&gt;&#xA;      &lt;td&gt;38.414634&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;28295&lt;/th&gt;&#xA;      &lt;td&gt;18526&lt;/td&gt;&#xA;      &lt;td&gt;JP&lt;/td&gt;&#xA;      &lt;td&gt;Helsinki&lt;/td&gt;&#xA;      &lt;td&gt;Team Wassu&lt;/td&gt;&#xA;      &lt;td&gt;FI&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:12:00&lt;/td&gt;&#xA;      &lt;td&gt;38.414634&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;8849&lt;/th&gt;&#xA;      &lt;td&gt;16650&lt;/td&gt;&#xA;      &lt;td&gt;SG&lt;/td&gt;&#xA;      &lt;td&gt;Eiksmarka&lt;/td&gt;&#xA;      &lt;td&gt;Team Tøff i Trynet&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:17:00&lt;/td&gt;&#xA;      &lt;td&gt;38.028169&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;28296&lt;/th&gt;&#xA;      &lt;td&gt;18527&lt;/td&gt;&#xA;      &lt;td&gt;JS&lt;/td&gt;&#xA;      &lt;td&gt;Hamina&lt;/td&gt;&#xA;      &lt;td&gt;Team Wassu&lt;/td&gt;&#xA;      &lt;td&gt;FI&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:21:00&lt;/td&gt;&#xA;      &lt;td&gt;37.724551&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;8861&lt;/th&gt;&#xA;      &lt;td&gt;16662&lt;/td&gt;&#xA;      &lt;td&gt;FA&lt;/td&gt;&#xA;      &lt;td&gt;Oslo&lt;/td&gt;&#xA;      &lt;td&gt;Team Tøff i Trynet&lt;/td&gt;&#xA;      &lt;td&gt;NO&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:23:00&lt;/td&gt;&#xA;      &lt;td&gt;37.574553&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;11817&lt;/th&gt;&#xA;      &lt;td&gt;23218&lt;/td&gt;&#xA;      &lt;td&gt;WG&lt;/td&gt;&#xA;      &lt;td&gt;Lemgo&lt;/td&gt;&#xA;      &lt;td&gt;RC Sprintax Bielefeld&lt;/td&gt;&#xA;      &lt;td&gt;DE&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:24:00&lt;/td&gt;&#xA;      &lt;td&gt;37.500000&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;11819&lt;/th&gt;&#xA;      &lt;td&gt;23220&lt;/td&gt;&#xA;      &lt;td&gt;CB&lt;/td&gt;&#xA;      &lt;td&gt;Bielefeld&lt;/td&gt;&#xA;      &lt;td&gt;RC Sprintax Bielefeld&lt;/td&gt;&#xA;      &lt;td&gt;DE&lt;/td&gt;&#xA;      &lt;td&gt;0 days 08:24:00&lt;/td&gt;&#xA;      &lt;td&gt;37.500000&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;lanterne-rouge&#34; class=&#34;content-heading&#34;&gt;Lanterne rouge&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;The slowest finisher took almost 28h.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)[[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;startnumber&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;initials&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;city&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;country&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;average_speed&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort_values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ascending&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tail&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;startnumber&lt;/th&gt;&#xA;      &lt;th&gt;initials&lt;/th&gt;&#xA;      &lt;th&gt;city&lt;/th&gt;&#xA;      &lt;th&gt;country&lt;/th&gt;&#xA;      &lt;th&gt;result_time&lt;/th&gt;&#xA;      &lt;th&gt;average_speed&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3416&lt;/th&gt;&#xA;      &lt;td&gt;2367&lt;/td&gt;&#xA;      &lt;td&gt;AH&lt;/td&gt;&#xA;      &lt;td&gt;Danderyd&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;1 days 02:37:00&lt;/td&gt;&#xA;      &lt;td&gt;11.834690&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1464&lt;/th&gt;&#xA;      &lt;td&gt;415&lt;/td&gt;&#xA;      &lt;td&gt;MP&lt;/td&gt;&#xA;      &lt;td&gt;Östersund&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;1 days 02:49:00&lt;/td&gt;&#xA;      &lt;td&gt;11.746426&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1465&lt;/th&gt;&#xA;      &lt;td&gt;416&lt;/td&gt;&#xA;      &lt;td&gt;ZYP&lt;/td&gt;&#xA;      &lt;td&gt;Stockholm&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;1 days 02:49:00&lt;/td&gt;&#xA;      &lt;td&gt;11.746426&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1260&lt;/th&gt;&#xA;      &lt;td&gt;211&lt;/td&gt;&#xA;      &lt;td&gt;HB&lt;/td&gt;&#xA;      &lt;td&gt;Svedala&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;1 days 03:36:00&lt;/td&gt;&#xA;      &lt;td&gt;11.413043&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1109&lt;/th&gt;&#xA;      &lt;td&gt;60&lt;/td&gt;&#xA;      &lt;td&gt;KH&lt;/td&gt;&#xA;      &lt;td&gt;Skara&lt;/td&gt;&#xA;      &lt;td&gt;SE&lt;/td&gt;&#xA;      &lt;td&gt;1 days 03:44:00&lt;/td&gt;&#xA;      &lt;td&gt;11.358173&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;finishing-times-excluding-sub-9-groups&#34; class=&#34;content-heading&#34;&gt;Finishing times (excluding sub-9 groups)&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;To get a better sense of the finishing times, I plot the histogram and get some summary statistics of the &lt;code&gt;result_time&lt;/code&gt; column for every finisher.&#xA;I only consider the times of the regular riders below. This means excluding the sub-9 cycling teams that start separately later on Saturday.&#xA;With a little less than 15h total (11.5h moving time) my group was slower than the median rider. Next time, we might want to take shorter breaks.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;has_finished and not is_sub9&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;describe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;count                        12175&#xA;mean     0 days 13:55:05.829979466&#xA;std      0 days 02:57:47.200342638&#xA;min                0 days 08:02:00&#xA;25%                0 days 11:37:00&#xA;50%                0 days 13:44:00&#xA;75%                0 days 15:48:00&#xA;max                1 days 03:44:00&#xA;Name: result_time, dtype: object&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;To be among the top 5% fastest finishers, you need to beat &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quantile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;q&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;To be among the top 10% fastest finishers, you need to beat &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quantile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;q&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;To be among the top 25% fastest finishers, you need to beat &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;result_time&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quantile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;q&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;To be among the top 5% fastest finishers, you need to beat 0 days 09:44:00.&#xA;To be among the top 10% fastest finishers, you need to beat 0 days 10:10:00.&#xA;To be among the top 25% fastest finishers, you need to beat 0 days 11:37:00.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;To plot the distribution of result times, I am binning the result time in minutes and also add some vertical lines indicating the 0.1- and 0.25- percentiles. It&amp;rsquo;s not surprising that the distribution is right-skewed with many riders that have very long finishing times, but nobody faster than 8 hours.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;minutes_to_hours_minutes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Define a function to convert minutes to HH:MM. Used for the axis labelling.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;hours&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;//&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;minutes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hours&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;02d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minutes&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;02d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# create histogram plot of result time distribution&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;figure&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;figsize&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sns&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;histplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;result_time_minutes&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;binwidth&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gca&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xaxis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set_major_formatter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FuncFormatter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minutes_to_hours_minutes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# draw colored vertical percentile lines&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axvline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time_minutes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;median&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;red&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linestyle&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linewidth&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axvline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time_minutes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quantile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;green&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linestyle&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linewidth&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axvline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time_minutes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quantile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linestyle&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linewidth&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time_minutes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;median&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ylim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.95&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Median&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;red&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ha&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;left&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;va&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;bottom&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time_minutes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quantile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ylim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.95&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Top 25%&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;green&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ha&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;center&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;va&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;bottom&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;times&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result_time_minutes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;quantile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ylim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.95&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Top 10%&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ha&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;right&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;va&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;bottom&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xlabel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Finish time (incl. breaks)&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;https://staticnotes.org/posts/vatternrundan-results/output_32_0.png&#34; alt=&#34;png&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Participating in this race with a group of friends was great fun and the Swedish locals are very supportive. I can highly recommend this event if you are a confident cyclist.&#xA;If you are planning to race next year&amp;rsquo;s Vatternrundan, this distribution might give you an indication of what to expect and a time to aim for.&lt;/p&gt;&#xA;&lt;h3 id=&#34;jupyter-notebook&#34; class=&#34;content-heading&#34;&gt;Jupyter Notebook&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;You can find the jupyter notebook and the datasets for this post &lt;a href=&#34;https://gitlab.com/frankRi89/blog/-/tree/main/notebooks/vatternrundan_results&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>How to better remember books</title>
      <link>https://staticnotes.org/posts/reading-and-note-taking/</link>
      <pubDate>Sun, 26 May 2024 00:00:00 +0100</pubDate>
      
      <guid>https://staticnotes.org/posts/reading-and-note-taking/</guid>
      <description>&lt;p&gt;In this article I am going to describe the system that I use to retain more information from the non-fiction books that I read. There seem to be two schools of thought about how to best retain the content of non-fiction books.&#xA;The first approach is best described by the quote:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;I cannot remember the books I’ve read any more than the meals I have eaten; even so, they have made me.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;- Ralph Waldo Emerson&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;By reading a lot, our brain retains what it finds interesting. Our prior beliefs are updated and specific ideas are reinforced within us when we encounter the same or related concepts in different sources.&lt;/p&gt;&#xA;&lt;p&gt;Some argue that proper retention can only be achieved by actively working through the material while reading it. This second approach commonly involves taking notes on the major ideas of the book.&lt;/p&gt;&#xA;&lt;p&gt;While I do experience &lt;em&gt;surprise connection&lt;/em&gt; moments occasionally, there are two reasons why I invest time into taking good notes:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The first approach has an inherent survivorship bias. I do remember concepts from books and I am able to link them to other things. This always feels great. However, I don&amp;rsquo;t know about the missed opportunities of ideas that I have forgotten and that will never resurface.&lt;/li&gt;&#xA;&lt;li&gt;Reading a non-fiction book is quite a significant time investment. For me it takes between a few days and several weeks. Taking at least basic notes seems to be a marginal additional cost for the certainty of improved retention and better ability to digest the book in the future.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;I use a simple multi-pass approach that involves both analog and digital notes. I mostly read physical books, because I like to browse books on my shelf that I have read in the past. However, you can easily adapt this approach to ebooks.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Skim the table of contents, and try to understand the structure of the book.&lt;/li&gt;&#xA;&lt;li&gt;Read the book and use a pencil to mark interesting sentences or paragraphs with a line in the margin (Fig. 1). In rare cases I use double lines to highlight especially noteworthy ideas. This helps later to quickly re-familiarise myself with the main concepts of a chapter without having to fully re-read it. I don&amp;rsquo;t typically write a lot of notes into the margin because there is usually not a lot of space available.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/reading-and-note-taking/notes_in_margin.jpg&#34; alt=&#34;Margin notes in book&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 1. I use a pencil to mark relevant sentences in the margin and occasionally add some notes.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;After finishing one or several chapters, I review the marked paragraphs and summarise the main points of each chapter on the empty space at the beginning or end of the chapter (Fig. 2). By writing the notes into the book I get two benefits. Firstly, there is a higher chance for these analog notes to still be accessible to me in a decade. Secondly, these notes might be interesting to friends that I lend the book to.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;image-wrapper&#34;&gt;&#xA;  &lt;img src=&#34;https://staticnotes.org/posts/reading-and-note-taking/notes_in_book.jpg&#34; alt=&#34;Chapter Notes in Book&#34; loading=&#34;lazy&#34; /&gt;&#xA;  &lt;figcaption&gt;Figure 2. I summarize the main points of each chapter on the blank space at the beginning or end of the chapter.&lt;/figcaption&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;Once I have finished the book, I transfer the chapter notes into a markdown file (in &lt;a href=&#34;https://joplinapp.org/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Joplin&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;). While copying the notes I sometimes rework or modify them.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; Since 2025 I actually take a photo of the handwritten notes and ask Gemini/Claude/GPT to produce a markdown file for me.&lt;/small&gt;&lt;/span&gt; I might also link to other digital notes that have a connection to the book.&lt;/li&gt;&#xA;&lt;li&gt;Optional: If I want to share my notes with an audience I will write about the major learnings from the notes and bring them into context with concepts from other books/articles/experiences.&lt;/li&gt;&#xA;&lt;li&gt;Optional: Most books will have some learnings that I want to periodically and actively recall. For those I create atomic &lt;a href=&#34;https://apps.ankiweb.net/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Anki cards&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; which will prompt me to regularly review the concepts. I am trying &lt;a href=&#34;https://andymatuschak.org/prompts/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;to write good prompts&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; for these cards. This can be a mix of facts like &amp;ldquo;Where was Napoleon born?&amp;rdquo; or higher level concepts I don&amp;rsquo;t want to forget, e.g. &amp;ldquo;Give an example of an infinite game as defined by J. P. Carse&amp;rdquo;.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;The most important rule for this note taking system is that I arbitrarily break the rules for certain books and skip some of these steps when I feel they are not worth the time. However, this system ensures that I do multiple passes of the content, that I have both durable analog and searchable digital notes, and that I am periodically prompted for the most interesting concepts.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>A great weekend</title>
      <link>https://staticnotes.org/posts/great-weekend/</link>
      <pubDate>Sun, 25 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/great-weekend/</guid>
      <description>&lt;p&gt;When you start working you suddenly put much higher value on the &amp;ldquo;free&amp;rdquo; weekend hours. At the beginning this sometimes meant that I was quite restless and felt like those valuable hours had to be used optimally. Of course this way of thinking was not relaxing at all.&lt;/p&gt;&#xA;&lt;p&gt;Over time I realised that the most rewarding/recharging weekends are those that involve random unplanned activities, other people/community, and hobbies done for their own sake (&lt;em&gt;atelic activities&lt;/em&gt;).&lt;/p&gt;&#xA;&lt;p&gt;My &lt;em&gt;great weekends&lt;/em&gt; often involve one or more of the following activities:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;spending time in nature, e.g. hiking on a local trail or going to the nearest park or forest&lt;/li&gt;&#xA;&lt;li&gt;exploring a new neighbourhood in my city without a particular goal in mind&lt;/li&gt;&#xA;&lt;li&gt;cooking a nice meal for myself, my wife and/or friends&lt;/li&gt;&#xA;&lt;li&gt;completing a household chore at the beginning of your day&lt;/li&gt;&#xA;&lt;li&gt;meeting a friend for a coffee/museum walk&lt;/li&gt;&#xA;&lt;li&gt;organising a day trip to somewhere else&lt;/li&gt;&#xA;&lt;li&gt;small talk with someone in my local community, e.g. one of my neighbours&lt;/li&gt;&#xA;&lt;li&gt;messaging or calling a friend who doesn&amp;rsquo;t live close&lt;/li&gt;&#xA;&lt;li&gt;exercising (running, cycling, swimming, gym)&lt;/li&gt;&#xA;&lt;li&gt;playing or learning a board game (my recommendations: &lt;a href=&#34;https://boardgamegeek.com/boardgame/154597/hive-pocket&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;&lt;em&gt;Hive&lt;/em&gt;&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;, &lt;a href=&#34;https://boardgamegeek.com/boardgame/121921/robinson-crusoe-adventures-on-the-cursed-island&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;&lt;em&gt;Robinson Crusoe&lt;/em&gt;&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;, &lt;a href=&#34;https://boardgamegeek.com/boardgame/266192/wingspan&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;&lt;em&gt;Wingspan&lt;/em&gt;&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;, &lt;a href=&#34;https://boardgamegeek.com/boardgame/162886/spirit-island&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;&lt;em&gt;Spirit Island&lt;/em&gt;&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;watching a documentary with full attention&lt;/li&gt;&#xA;&lt;li&gt;fixing something broken at home, e.g. my bicycle, water filter, squeaky door, broken light&lt;/li&gt;&#xA;&lt;li&gt;reading a fiction or history book&lt;/li&gt;&#xA;&lt;li&gt;reading the weekly edition of a newspaper (especially a section of the paper I would normally skip)&lt;/li&gt;&#xA;&lt;li&gt;listening to the radio or a music genre that I would not normally listen to&lt;/li&gt;&#xA;&lt;li&gt;following a yoga / stretching / meditation routine&lt;/li&gt;&#xA;&lt;li&gt;learning and taking notes about a topic that is &lt;em&gt;not&lt;/em&gt; relevant for my work or career (learning for the sake of learning)&lt;/li&gt;&#xA;&lt;li&gt;practicing a different language&lt;/li&gt;&#xA;&lt;li&gt;calling my parents&lt;/li&gt;&#xA;&lt;li&gt;volunteering at a local event&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    
    <item>
      <title>DuckDB use cases for data scientists: Querying remote S3 files</title>
      <link>https://staticnotes.org/posts/duckdb-for-data-scientists/</link>
      <pubDate>Sun, 25 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/duckdb-for-data-scientists/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://duckdb.org/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;DuckDB&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; is a pretty cool &lt;em&gt;in-process&lt;/em&gt; OLAP analytical database that I started to spin up on the fly for quick data analysis. What SQLite is to &lt;em&gt;Postgres&lt;/em&gt;, DuckDB is to &lt;em&gt;Snowflake&lt;/em&gt;. It is a single executable without dependencies and stores databases in local files.&lt;/p&gt;&#xA;&lt;p&gt;I can think of four use cases for data science work:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;DuckDB supports larger-than-memory workloads by loading data sequentially. You can use it to analyse datasets that are too large for Pandas (and too small to justify PySpark).&lt;/li&gt;&#xA;&lt;li&gt;I can query CSV, parquet, and JSON files directly from remote endpoints, e.g. S3, using SQL.&lt;/li&gt;&#xA;&lt;li&gt;I can replace Snowflake queries with DuckDB queries in unit / integration tests.&lt;/li&gt;&#xA;&lt;li&gt;I can set up a &lt;a href=&#34;https://duckdb.org/2022/10/12/modern-data-stack-in-a-box.html&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;(DuckDB + dbt)&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; data warehouse for local development.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;I want to share here my workflow for the second use case. Inspecting parquet files in AWS S3 is a pain because I can&amp;rsquo;t easily inspect them in the AWS console. For a few months now I have used DuckDB to load, inspect, and analyse parquet files from the command line. I found this reduced my cognitive load in situations where I quickly want to check a remote file, because I don&amp;rsquo;t have to download the parquet file and write a Python script to inspect it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;installing-duckdb&#34; class=&#34;content-heading&#34;&gt;Installing DuckDB&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I use macOS and can install DuckDB via homebrew: &lt;code&gt;brew install duckdb&lt;/code&gt;. To work with remote files I also install the &lt;code&gt;httpfs&lt;/code&gt; extension.&lt;/p&gt;&#xA;&lt;p&gt;I start the DuckDB shell with &lt;code&gt;duckdb&lt;/code&gt; and run the SQL commands:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;INSTALL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;httpfs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;LOAD&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;httpfs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h2 id=&#34;authentication-with-aws&#34; class=&#34;content-heading&#34;&gt;Authentication with AWS&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;To load files from S3, I need to configure AWS credentials. I am assuming here that your workplace has configured AWS SSO temporary credentials, but this works also with static credentials (&lt;code&gt;ACCESS_KEY_ID&lt;/code&gt;, &lt;code&gt;SECRET_ACCESS_KEY&lt;/code&gt;). There are two ways of doing this:&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-set-aws-credentials-in-the-session&#34; class=&#34;content-heading&#34;&gt;1. Set AWS credentials in the session:&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I can set AWS credentials inside a DuckDB session like this:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;LOAD&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;httpfs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SET&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s3_region&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;eu-west-2&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SET&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s3_access_key_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;???&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SET&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s3_secret_access_key&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;???&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;2-let-aws-vault-handle-credentials&#34; class=&#34;content-heading&#34;&gt;2. Let aws vault handle credentials&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I use the AWS credentials management tool &lt;code&gt;aws vault&lt;/code&gt; (see &lt;a href=&#34;https://github.com/99designs/aws-vault&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;) which manages my temporary AWS credentials in the background and exposes them to my shell sub-process. I create the DuckDB shell with &lt;code&gt;aws-vault exec [profile-name] -- duckdb&lt;/code&gt; which ensures that AWS credentials are automatically set and updated.&lt;/p&gt;&#xA;&lt;h2 id=&#34;querying-parquet-files&#34; class=&#34;content-heading&#34;&gt;Querying parquet files&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s assume that I have multiple parquet files stored in an S3 bucket &lt;code&gt;work-project&lt;/code&gt; and they all have the same schema:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;s3://work-project/clickdata_001.parquet&#xA;s3://work-project/clickdata_002.parquet&#xA;[...]&#xA;s3://work-project/clickdata_100.parquet&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;These files might be placed in this S3 bucket as part of an ETL pipeline before they are loaded into a table in a data warehouse. Let&amp;rsquo;s imagine I want to investigate a bug in the pipeline and need to inspect the files.&lt;/p&gt;&#xA;&lt;h3 id=&#34;inspect-schema-of-parquet-file&#34; class=&#34;content-heading&#34;&gt;Inspect schema of parquet file&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;To familiarise myself with the schema I run &lt;code&gt;parquet_schema&lt;/code&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;sql&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;LOAD&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;httpfs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- once at the beginning of the session&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parquet_schema&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://work-project/clickdata_001.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;which will return:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;clicked_at::timestamp&#xA;user_id::int&#xA;event_type::string&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;query-a-parquet-file&#34; class=&#34;content-heading&#34;&gt;Query a parquet file&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;I can use postgres SQL dialect to query the parquet files with the &lt;code&gt;read_parquet&lt;/code&gt; function, e.g.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;SQL&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-SQL&#34; data-lang=&#34;SQL&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;--- count number of events in the file&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://work-project/clickdata_001.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;--- find the last event time of a particular user&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clicked_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://work-project/clickdata_001.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1234&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;query-multiple-parquet-files&#34; class=&#34;content-heading&#34;&gt;Query multiple parquet files&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Say I want to find the users with the highest number of events across all files. I can use &lt;a href=&#34;https://duckdb.org/docs/data/multiple_files/overview.html#glob-syntax&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;glob syntax&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; with &lt;code&gt;*&lt;/code&gt; to run a query against all files as if they were one table:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;SQL&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-SQL&#34; data-lang=&#34;SQL&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_events&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://work-project/*.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;order&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;by&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_events&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;create-table-from-files&#34; class=&#34;content-heading&#34;&gt;Create table from files&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s assume that all clickdata files together have a size of 500MB. It would be annoying if I had to download these files for every query that I want to run. Let&amp;rsquo;s instead create a table from the files.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;SQL&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-SQL&#34; data-lang=&#34;SQL&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;create&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;table&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clickdata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://work-project/*.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;This table is stored in memory until we close the shell, which allows me to run different queries against it until I am done with my analysis, e.g.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;SQL&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-SQL&#34; data-lang=&#34;SQL&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clickdata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;I can also store the table in a local database on my computer in case I need to work with the data for a longer time.&#xA;The following SQL statement&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;SQL&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-SQL&#34; data-lang=&#34;SQL&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;EXPORT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DATABASE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;mydatabase&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FORMAT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PARQUET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;will create a local folder &lt;code&gt;mydatabase&lt;/code&gt; which stores the tables currently in memory. In a later DuckDB session I can reload the table from the database using the following command&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;SQL&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-SQL&#34; data-lang=&#34;SQL&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;IMPORT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;DATABASE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;mydatabase&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;query-column-statistics&#34; class=&#34;content-heading&#34;&gt;Query column statistics&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;A nice feature of the parquet file format is that it stores &lt;a href=&#34;https://arrow.apache.org/docs/python/generated/pyarrow.parquet.Statistics.html&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;statistics about each column&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;, e.g. &lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;null_count&lt;/code&gt;, &lt;code&gt;distinct_count&lt;/code&gt;.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; If you are interested, you can inspect parquet file metadata using &lt;code&gt;select * from parquet_metadata(&#39;file.parquet&#39;);&lt;/code&gt;&lt;/small&gt;&lt;/span&gt;&#xA;Assume the click event dataset is several GB large and I want to identify the earliest &lt;code&gt;clicked_at&lt;/code&gt; time. I would run the query below.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;SQL&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-SQL&#34; data-lang=&#34;SQL&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clicked_at&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://work-project/*.parquet&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Fortunately, DuckDB uses the column statistics stored in the parquet files to compute the answer without having to download the whole dataset from S3. Simon Willison &lt;a href=&#34;https://til.simonwillison.net/duckdb/remote-parquet&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;shows&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; a more extreme example of this feature.&lt;/p&gt;&#xA;&lt;p&gt;DuckDB is a great tool for quick investigations of remotely hosted files. Especially after having configured automatic handling of AWS credentials I can spin up a DuckDB shell with one command. I hope it becomes a time saver for you too.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>How to display Jupyter notebooks on your Hugo blog</title>
      <link>https://staticnotes.org/posts/hugo-and-jupyter/</link>
      <pubDate>Sat, 20 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/hugo-and-jupyter/</guid>
      <description>&lt;p&gt;I like the simplicity and ease of use of Hugo, the static site generator that powers this blog.&#xA;However, as a data scientist I want to be able to make an argument using code, data, and graphs in a Jupyter notebook. This post explains how I convert a Jupyter notebook into a blog post for this website, such as &lt;a href=&#34;../posts/covid_bipartisan_bayesian/&#34; &#xA;&gt;this&#xA;&lt;/a&gt;. Before I started, my requirements were:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I wanted to be able to easily share both the original notebook (and accompanying data) as well as the website version.&lt;/li&gt;&#xA;&lt;li&gt;I wanted to regenerate the website version from the notebook file with at most one command and without any post-processing. This is important because I usually work iteratively on notebooks.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;writing-the-notebook&#34; class=&#34;content-heading&#34;&gt;Writing the notebook&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;The source code for this blog is available in this &lt;a href=&#34;https://gitlab.com/frankRi89/blog&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Gitlab repository&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;. I created a new top-level folder &lt;code&gt;notebooks/&lt;/code&gt; and a subfolder for each notebook project I want to post about. This allows me to easily link to the Jupyter notebook and data to make it reproducible.&lt;/p&gt;&#xA;&lt;p&gt;It is important that you start the notebook with a cell that contains the front matter of the blog post, e.g.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;# My notebook title&#xA;&#xA;Date: 2018-06-01  &#xA;Author: firstname lastname  &#xA;Categories: category1, category2  &#xA;Tags: tag1, tag2, tag3  &#xA;&amp;lt;!--eofm--&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;The &lt;code&gt;&amp;lt;!--eofm--&amp;gt;&lt;/code&gt; is important to divide the front matter from the rest of the notebook.&lt;/p&gt;&#xA;&lt;h2 id=&#34;converting-to-markdown&#34; class=&#34;content-heading&#34;&gt;Converting to markdown&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;To align with the markdown-based workflow of Hugo we need to convert the notebook to markdown. The script  &lt;a href=&#34;https://github.com/vlunot/nb2hugo&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;nb2hugo&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; does exactly that. We can install it for example via: &lt;code&gt;pip install nb2hugo&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;To convert the notebook to markdown we navigate into the notebook folder and run&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34;&gt;&lt;pre&gt;&lt;code&gt;nb2hugo covid_bipartisan_bayesian.ipynb --site-dir /Users/rob/hugoblog/ --section posts&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;p&gt;This command writes the output markdown file &lt;code&gt;covid_bipartisan_bayesian.md&lt;/code&gt; into the specified folder &lt;code&gt;posts/&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;adjusting-the-website-css&#34; class=&#34;content-heading&#34;&gt;Adjusting the website CSS&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;I made two more adjustments to the style of this blog to better display the &amp;ldquo;markdown-ified&amp;rdquo; notebook. Both pandas code and displayed dataframes are quite wide so I:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;increased the content width slightly to &lt;code&gt;800px&lt;/code&gt;,&lt;/li&gt;&#xA;&lt;li&gt;decreased the font-size for the text in the code cells to &lt;code&gt;0.75rem&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;While still not perfect, I think this gives a decent result.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Reproducing Nate Silver&#39;s regression analysis on COVID death rates</title>
      <link>https://staticnotes.org/posts/covid_bipartisan_bayesian/</link>
      <pubDate>Mon, 20 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://staticnotes.org/posts/covid_bipartisan_bayesian/</guid>
      <description>&lt;p&gt;I spent some time recently studying causal inference methods. Two great resources for this are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://matheusfacure.github.io/python-causality-handbook/landing-page.html&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Causal Inference for The Brave and True&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; (frequentist view)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://xcelab.net/rm/statistical-rethinking/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Statistical Rethinking&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; (Bayesian view).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;When I learn about an unfamiliar topic, I will always try to look for real-world examples. In this case I keep my eyes open about articles sharing statistical findings, where I can attempt to reproduce the results.&lt;/p&gt;&#xA;&lt;p&gt;In Nate Silver&amp;rsquo;s recent article &lt;a href=&#34;https://www.natesilver.net/p/fine-ill-run-a-regression-analysis&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Fine, I&amp;rsquo;ll run a regression analysis. But it won&amp;rsquo;t make you happy&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; he shows the effect of state partisanship and COVID vaccination rates on COVID death rates. The models used are simple linear regressions with one to three independent variables (partisanship, age, vaccination rates).&lt;/p&gt;&#xA;&lt;p&gt;Silver&amp;rsquo;s point in the article is only partially about his finding that state partisanship is a good predictor for COVID death rates in that state. Instead, he tries to dismiss critics that argue that simple models are not valid when they leave out additional variables, e.g. age, co-morbidities. While he agrees that one has to justify a particular model design, simple models can deliver true insights while standing up to scrutiny. Moreover he adds that &amp;ldquo;there&amp;rsquo;s a general tendency [in the profession] to overfit models.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;This post is not about Silver&amp;rsquo;s point or the political aspect of the result. I simply wanted to reproduce the findings in the article.&lt;/p&gt;&#xA;&lt;p&gt;In his article Silver runs four linear regressions:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;impact of state partisanship on COVID death rates&lt;/li&gt;&#xA;&lt;li&gt;impact of state partisanship and state age on COVID death rates&lt;/li&gt;&#xA;&lt;li&gt;impact of state partisanship, state age, and state vaccination rates on COVID death rates&lt;/li&gt;&#xA;&lt;li&gt;impact of state age and state vaccination rates on COVID death rates&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;We need to collect data for every US state on partisanship, age structure, vaccination rates, and COVID death rates. It turned out, perhaps not surprisingly, that finding and assembling the dataset from open sources took significantly more time than setting up the regressions. I had three issues when I tried to assemble the data from the sources that the article links to:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;one source didn&amp;rsquo;t allow me to download the data as a file and I didn&amp;rsquo;t want to scrape or copy-paste from the website&lt;/li&gt;&#xA;&lt;li&gt;one source didn&amp;rsquo;t allow me to view the data on the same reference day as in the article&lt;/li&gt;&#xA;&lt;li&gt;one source didn&amp;rsquo;t provide the data as a file for free&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;So I had to use in some cases different sources.&lt;/p&gt;&#xA;&lt;h1 id=&#34;building-the-data-set&#34; class=&#34;content-heading&#34;&gt;Building the data set&#xA;&lt;/h1&gt;&#xA;&lt;p&gt;We are building the data set from four sources:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;US states COVID cases and deaths: &lt;a href=&#34;https://github.com/nytimes/covid-19-data/blob/62ef34cfcb60214be873a38d73619da9ea57d50b/us-states.csv&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;https://github.com/nytimes/covid-19-data/blob/62ef34cfcb60214be873a38d73619da9ea57d50b/us-states.csv&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;US states age statistics: &lt;a href=&#34;https://www.prb.org/resources/which-us-states-are-the-oldest/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;https://www.prb.org/resources/which-us-states-are-the-oldest/&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;US states vaccination rates: &lt;a href=&#34;https://web.archive.org/web/20241113065036/https://ourworldindata.org/us-states-vaccinations&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;ourworldindata.org (archive.org version)&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;US states election results 2020: &lt;a href=&#34;https://www.kaggle.com/code/paultimothymooney/2020-usa-election-vote-percentages-by-state/output&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;https://www.kaggle.com/code/paultimothymooney/2020-usa-election-vote-percentages-by-state/output&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;covid-death-rates&#34; class=&#34;content-heading&#34;&gt;COVID death rates&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;We want to calculate the COVID death rates (COVID deaths per 1M population) between two points in time (1. February 2021 when vaccines became widely available and 23. March 2023 as in the article). Silver links to &lt;a href=&#34;https://www.worldometers.info/coronavirus/country/us/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;worldometer.info&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; as his dataset for covid deaths per state. However, I couldn&amp;rsquo;t find a way to download the data in timeseries form (numbers for each day) without scraping the website. Instead we are using the equivalent numbers published by the New York Times. Let&amp;rsquo;s load the CSV file into a pandas dataframe:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pandas&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pd&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;numpy&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;np&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;statsmodels.api&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sm&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;plt&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;us-states.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;date&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_datetime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;date&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# create two series for the two dates of interest and rename the columns&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;deaths_february&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;date&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;2021-02-01&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;columns&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_2021_02_01&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;deaths_last&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;date&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;2023-03-23&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;columns&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_2023_03_23&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;With the two pandas series &lt;code&gt;deaths_february&lt;/code&gt; and &lt;code&gt;deaths_last&lt;/code&gt; we can calculate the number of deaths in this time period.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;deaths&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deaths_last&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;merge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;deaths_february&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;how&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;left&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;on&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;state&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dropna&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;index&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;deaths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_after_vaccine&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deaths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_2023_03_23&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deaths&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_2021_02_01&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Now we can look at the state numbers for COVID deaths between 01.02.2021 and 23.03.2023:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;deaths&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;state&lt;/th&gt;&#xA;      &lt;th&gt;deaths_2023_03_23&lt;/th&gt;&#xA;      &lt;th&gt;deaths_2021_02_01&lt;/th&gt;&#xA;      &lt;th&gt;deaths_after_vaccine&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;Alabama&lt;/td&gt;&#xA;      &lt;td&gt;21631&lt;/td&gt;&#xA;      &lt;td&gt;7688.0&lt;/td&gt;&#xA;      &lt;td&gt;13943.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;Alaska&lt;/td&gt;&#xA;      &lt;td&gt;1438&lt;/td&gt;&#xA;      &lt;td&gt;253.0&lt;/td&gt;&#xA;      &lt;td&gt;1185.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;Arizona&lt;/td&gt;&#xA;      &lt;td&gt;33190&lt;/td&gt;&#xA;      &lt;td&gt;13124.0&lt;/td&gt;&#xA;      &lt;td&gt;20066.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;Arkansas&lt;/td&gt;&#xA;      &lt;td&gt;13068&lt;/td&gt;&#xA;      &lt;td&gt;4895.0&lt;/td&gt;&#xA;      &lt;td&gt;8173.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;5&lt;/th&gt;&#xA;      &lt;td&gt;California&lt;/td&gt;&#xA;      &lt;td&gt;104277&lt;/td&gt;&#xA;      &lt;td&gt;41284.0&lt;/td&gt;&#xA;      &lt;td&gt;62993.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;6&lt;/th&gt;&#xA;      &lt;td&gt;Colorado&lt;/td&gt;&#xA;      &lt;td&gt;14245&lt;/td&gt;&#xA;      &lt;td&gt;5737.0&lt;/td&gt;&#xA;      &lt;td&gt;8508.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;7&lt;/th&gt;&#xA;      &lt;td&gt;Connecticut&lt;/td&gt;&#xA;      &lt;td&gt;12270&lt;/td&gt;&#xA;      &lt;td&gt;7119.0&lt;/td&gt;&#xA;      &lt;td&gt;5151.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;8&lt;/th&gt;&#xA;      &lt;td&gt;Delaware&lt;/td&gt;&#xA;      &lt;td&gt;3352&lt;/td&gt;&#xA;      &lt;td&gt;1101.0&lt;/td&gt;&#xA;      &lt;td&gt;2251.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;9&lt;/th&gt;&#xA;      &lt;td&gt;District of Columbia&lt;/td&gt;&#xA;      &lt;td&gt;1432&lt;/td&gt;&#xA;      &lt;td&gt;916.0&lt;/td&gt;&#xA;      &lt;td&gt;516.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;10&lt;/th&gt;&#xA;      &lt;td&gt;Florida&lt;/td&gt;&#xA;      &lt;td&gt;87141&lt;/td&gt;&#xA;      &lt;td&gt;26684.0&lt;/td&gt;&#xA;      &lt;td&gt;60457.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;11&lt;/th&gt;&#xA;      &lt;td&gt;Georgia&lt;/td&gt;&#xA;      &lt;td&gt;41055&lt;/td&gt;&#xA;      &lt;td&gt;13821.0&lt;/td&gt;&#xA;      &lt;td&gt;27234.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;12&lt;/th&gt;&#xA;      &lt;td&gt;Guam&lt;/td&gt;&#xA;      &lt;td&gt;416&lt;/td&gt;&#xA;      &lt;td&gt;130.0&lt;/td&gt;&#xA;      &lt;td&gt;286.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;13&lt;/th&gt;&#xA;      &lt;td&gt;Hawaii&lt;/td&gt;&#xA;      &lt;td&gt;1851&lt;/td&gt;&#xA;      &lt;td&gt;407.0&lt;/td&gt;&#xA;      &lt;td&gt;1444.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;14&lt;/th&gt;&#xA;      &lt;td&gt;Idaho&lt;/td&gt;&#xA;      &lt;td&gt;5456&lt;/td&gt;&#xA;      &lt;td&gt;1737.0&lt;/td&gt;&#xA;      &lt;td&gt;3719.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;15&lt;/th&gt;&#xA;      &lt;td&gt;Illinois&lt;/td&gt;&#xA;      &lt;td&gt;41618&lt;/td&gt;&#xA;      &lt;td&gt;21273.0&lt;/td&gt;&#xA;      &lt;td&gt;20345.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;16&lt;/th&gt;&#xA;      &lt;td&gt;Indiana&lt;/td&gt;&#xA;      &lt;td&gt;26179&lt;/td&gt;&#xA;      &lt;td&gt;9989.0&lt;/td&gt;&#xA;      &lt;td&gt;16190.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;17&lt;/th&gt;&#xA;      &lt;td&gt;Iowa&lt;/td&gt;&#xA;      &lt;td&gt;10770&lt;/td&gt;&#xA;      &lt;td&gt;4906.0&lt;/td&gt;&#xA;      &lt;td&gt;5864.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;18&lt;/th&gt;&#xA;      &lt;td&gt;Kansas&lt;/td&gt;&#xA;      &lt;td&gt;10232&lt;/td&gt;&#xA;      &lt;td&gt;3809.0&lt;/td&gt;&#xA;      &lt;td&gt;6423.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;19&lt;/th&gt;&#xA;      &lt;td&gt;Kentucky&lt;/td&gt;&#xA;      &lt;td&gt;18348&lt;/td&gt;&#xA;      &lt;td&gt;3995.0&lt;/td&gt;&#xA;      &lt;td&gt;14353.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;20&lt;/th&gt;&#xA;      &lt;td&gt;Louisiana&lt;/td&gt;&#xA;      &lt;td&gt;18835&lt;/td&gt;&#xA;      &lt;td&gt;8912.0&lt;/td&gt;&#xA;      &lt;td&gt;9923.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;21&lt;/th&gt;&#xA;      &lt;td&gt;Maine&lt;/td&gt;&#xA;      &lt;td&gt;2981&lt;/td&gt;&#xA;      &lt;td&gt;595.0&lt;/td&gt;&#xA;      &lt;td&gt;2386.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;22&lt;/th&gt;&#xA;      &lt;td&gt;Maryland&lt;/td&gt;&#xA;      &lt;td&gt;16672&lt;/td&gt;&#xA;      &lt;td&gt;7154.0&lt;/td&gt;&#xA;      &lt;td&gt;9518.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;23&lt;/th&gt;&#xA;      &lt;td&gt;Massachusetts&lt;/td&gt;&#xA;      &lt;td&gt;24441&lt;/td&gt;&#xA;      &lt;td&gt;14607.0&lt;/td&gt;&#xA;      &lt;td&gt;9834.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;24&lt;/th&gt;&#xA;      &lt;td&gt;Michigan&lt;/td&gt;&#xA;      &lt;td&gt;42311&lt;/td&gt;&#xA;      &lt;td&gt;15527.0&lt;/td&gt;&#xA;      &lt;td&gt;26784.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;25&lt;/th&gt;&#xA;      &lt;td&gt;Minnesota&lt;/td&gt;&#xA;      &lt;td&gt;14964&lt;/td&gt;&#xA;      &lt;td&gt;6270.0&lt;/td&gt;&#xA;      &lt;td&gt;8694.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;26&lt;/th&gt;&#xA;      &lt;td&gt;Mississippi&lt;/td&gt;&#xA;      &lt;td&gt;13431&lt;/td&gt;&#xA;      &lt;td&gt;6056.0&lt;/td&gt;&#xA;      &lt;td&gt;7375.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;27&lt;/th&gt;&#xA;      &lt;td&gt;Missouri&lt;/td&gt;&#xA;      &lt;td&gt;23998&lt;/td&gt;&#xA;      &lt;td&gt;7182.0&lt;/td&gt;&#xA;      &lt;td&gt;16816.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;28&lt;/th&gt;&#xA;      &lt;td&gt;Montana&lt;/td&gt;&#xA;      &lt;td&gt;3701&lt;/td&gt;&#xA;      &lt;td&gt;1235.0&lt;/td&gt;&#xA;      &lt;td&gt;2466.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;29&lt;/th&gt;&#xA;      &lt;td&gt;Nebraska&lt;/td&gt;&#xA;      &lt;td&gt;5068&lt;/td&gt;&#xA;      &lt;td&gt;2031.0&lt;/td&gt;&#xA;      &lt;td&gt;3037.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;30&lt;/th&gt;&#xA;      &lt;td&gt;Nevada&lt;/td&gt;&#xA;      &lt;td&gt;12093&lt;/td&gt;&#xA;      &lt;td&gt;4281.0&lt;/td&gt;&#xA;      &lt;td&gt;7812.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;31&lt;/th&gt;&#xA;      &lt;td&gt;New Hampshire&lt;/td&gt;&#xA;      &lt;td&gt;3018&lt;/td&gt;&#xA;      &lt;td&gt;1059.0&lt;/td&gt;&#xA;      &lt;td&gt;1959.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;32&lt;/th&gt;&#xA;      &lt;td&gt;New Jersey&lt;/td&gt;&#xA;      &lt;td&gt;36097&lt;/td&gt;&#xA;      &lt;td&gt;21513.0&lt;/td&gt;&#xA;      &lt;td&gt;14584.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;33&lt;/th&gt;&#xA;      &lt;td&gt;New Mexico&lt;/td&gt;&#xA;      &lt;td&gt;9110&lt;/td&gt;&#xA;      &lt;td&gt;3297.0&lt;/td&gt;&#xA;      &lt;td&gt;5813.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;34&lt;/th&gt;&#xA;      &lt;td&gt;New York&lt;/td&gt;&#xA;      &lt;td&gt;80109&lt;/td&gt;&#xA;      &lt;td&gt;43354.0&lt;/td&gt;&#xA;      &lt;td&gt;36755.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;35&lt;/th&gt;&#xA;      &lt;td&gt;North Carolina&lt;/td&gt;&#xA;      &lt;td&gt;29746&lt;/td&gt;&#xA;      &lt;td&gt;9397.0&lt;/td&gt;&#xA;      &lt;td&gt;20349.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;36&lt;/th&gt;&#xA;      &lt;td&gt;North Dakota&lt;/td&gt;&#xA;      &lt;td&gt;2529&lt;/td&gt;&#xA;      &lt;td&gt;1447.0&lt;/td&gt;&#xA;      &lt;td&gt;1082.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;37&lt;/th&gt;&#xA;      &lt;td&gt;Northern Mariana Islands&lt;/td&gt;&#xA;      &lt;td&gt;41&lt;/td&gt;&#xA;      &lt;td&gt;2.0&lt;/td&gt;&#xA;      &lt;td&gt;39.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;38&lt;/th&gt;&#xA;      &lt;td&gt;Ohio&lt;/td&gt;&#xA;      &lt;td&gt;42061&lt;/td&gt;&#xA;      &lt;td&gt;11233.0&lt;/td&gt;&#xA;      &lt;td&gt;30828.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;39&lt;/th&gt;&#xA;      &lt;td&gt;Oklahoma&lt;/td&gt;&#xA;      &lt;td&gt;16549&lt;/td&gt;&#xA;      &lt;td&gt;3564.0&lt;/td&gt;&#xA;      &lt;td&gt;12985.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;40&lt;/th&gt;&#xA;      &lt;td&gt;Oregon&lt;/td&gt;&#xA;      &lt;td&gt;9451&lt;/td&gt;&#xA;      &lt;td&gt;1980.0&lt;/td&gt;&#xA;      &lt;td&gt;7471.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;41&lt;/th&gt;&#xA;      &lt;td&gt;Pennsylvania&lt;/td&gt;&#xA;      &lt;td&gt;50701&lt;/td&gt;&#xA;      &lt;td&gt;21741.0&lt;/td&gt;&#xA;      &lt;td&gt;28960.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;42&lt;/th&gt;&#xA;      &lt;td&gt;Puerto Rico&lt;/td&gt;&#xA;      &lt;td&gt;5848&lt;/td&gt;&#xA;      &lt;td&gt;1836.0&lt;/td&gt;&#xA;      &lt;td&gt;4012.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;43&lt;/th&gt;&#xA;      &lt;td&gt;Rhode Island&lt;/td&gt;&#xA;      &lt;td&gt;3915&lt;/td&gt;&#xA;      &lt;td&gt;2173.0&lt;/td&gt;&#xA;      &lt;td&gt;1742.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;44&lt;/th&gt;&#xA;      &lt;td&gt;South Carolina&lt;/td&gt;&#xA;      &lt;td&gt;20192&lt;/td&gt;&#xA;      &lt;td&gt;7283.0&lt;/td&gt;&#xA;      &lt;td&gt;12909.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;45&lt;/th&gt;&#xA;      &lt;td&gt;South Dakota&lt;/td&gt;&#xA;      &lt;td&gt;3222&lt;/td&gt;&#xA;      &lt;td&gt;1778.0&lt;/td&gt;&#xA;      &lt;td&gt;1444.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;46&lt;/th&gt;&#xA;      &lt;td&gt;Tennessee&lt;/td&gt;&#xA;      &lt;td&gt;29035&lt;/td&gt;&#xA;      &lt;td&gt;9660.0&lt;/td&gt;&#xA;      &lt;td&gt;19375.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;47&lt;/th&gt;&#xA;      &lt;td&gt;Texas&lt;/td&gt;&#xA;      &lt;td&gt;94518&lt;/td&gt;&#xA;      &lt;td&gt;37405.0&lt;/td&gt;&#xA;      &lt;td&gt;57113.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;48&lt;/th&gt;&#xA;      &lt;td&gt;Utah&lt;/td&gt;&#xA;      &lt;td&gt;5316&lt;/td&gt;&#xA;      &lt;td&gt;1669.0&lt;/td&gt;&#xA;      &lt;td&gt;3647.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;49&lt;/th&gt;&#xA;      &lt;td&gt;Vermont&lt;/td&gt;&#xA;      &lt;td&gt;939&lt;/td&gt;&#xA;      &lt;td&gt;175.0&lt;/td&gt;&#xA;      &lt;td&gt;764.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;50&lt;/th&gt;&#xA;      &lt;td&gt;Virgin Islands&lt;/td&gt;&#xA;      &lt;td&gt;130&lt;/td&gt;&#xA;      &lt;td&gt;24.0&lt;/td&gt;&#xA;      &lt;td&gt;106.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;51&lt;/th&gt;&#xA;      &lt;td&gt;Virginia&lt;/td&gt;&#xA;      &lt;td&gt;23782&lt;/td&gt;&#xA;      &lt;td&gt;6474.0&lt;/td&gt;&#xA;      &lt;td&gt;17308.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;52&lt;/th&gt;&#xA;      &lt;td&gt;Washington&lt;/td&gt;&#xA;      &lt;td&gt;15905&lt;/td&gt;&#xA;      &lt;td&gt;4404.0&lt;/td&gt;&#xA;      &lt;td&gt;11501.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;53&lt;/th&gt;&#xA;      &lt;td&gt;West Virginia&lt;/td&gt;&#xA;      &lt;td&gt;8132&lt;/td&gt;&#xA;      &lt;td&gt;2028.0&lt;/td&gt;&#xA;      &lt;td&gt;6104.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;54&lt;/th&gt;&#xA;      &lt;td&gt;Wisconsin&lt;/td&gt;&#xA;      &lt;td&gt;16485&lt;/td&gt;&#xA;      &lt;td&gt;6439.0&lt;/td&gt;&#xA;      &lt;td&gt;10046.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;55&lt;/th&gt;&#xA;      &lt;td&gt;Wyoming&lt;/td&gt;&#xA;      &lt;td&gt;2014&lt;/td&gt;&#xA;      &lt;td&gt;596.0&lt;/td&gt;&#xA;      &lt;td&gt;1418.0&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;age-characteristics&#34; class=&#34;content-heading&#34;&gt;Age characteristics&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;We load data for US states population age characteristics and calculate the proportion of the state population aged 65 or older. We would expect that states with an older population are more severely affected by COVID (all else being equal).&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;states_population&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;states_population_age_2020.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;thousands&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;drop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Rank&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Population Ages 65+ (percent of state population)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;states_population&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;states_population&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;columns&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;State&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Total Resident Population (thousands)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;total_population_thousands&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Population Ages 65+ (thousands)&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;population_age65_thousands&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;states_population&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;perc_over_65&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;states_population&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;population_age65_thousands&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;states_population&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;total_population_thousands&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;100.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Next we add the &lt;code&gt;perc_over_65&lt;/code&gt; column to the deaths dataframe.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# drop due to missing population data for DC, Guam, Puerto Rico, Northern Mariana Islands, Virgin Islands&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;deaths_and_states&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deaths&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;merge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;states_population&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;total_population_thousands&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;perc_over_65&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;on&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;state&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;how&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;left&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dropna&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Moreover, to use the same variable scaling as in the article, we scale the &lt;code&gt;deaths_after_vaccine&lt;/code&gt; variable from absolute numbers to be COVID deaths per million population.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;deaths_and_states&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_per_million&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deaths_and_states&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_after_vaccine&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;deaths_and_states&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;total_population_thousands&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1_000_000&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# dataframe with deaths, population, and age variable&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;deaths_and_states&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;state&lt;/th&gt;&#xA;      &lt;th&gt;deaths_2023_03_23&lt;/th&gt;&#xA;      &lt;th&gt;deaths_2021_02_01&lt;/th&gt;&#xA;      &lt;th&gt;deaths_after_vaccine&lt;/th&gt;&#xA;      &lt;th&gt;total_population_thousands&lt;/th&gt;&#xA;      &lt;th&gt;perc_over_65&lt;/th&gt;&#xA;      &lt;th&gt;deaths_per_million&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;Alabama&lt;/td&gt;&#xA;      &lt;td&gt;21631&lt;/td&gt;&#xA;      &lt;td&gt;7688.0&lt;/td&gt;&#xA;      &lt;td&gt;13943.0&lt;/td&gt;&#xA;      &lt;td&gt;4922.0&lt;/td&gt;&#xA;      &lt;td&gt;17.757009&lt;/td&gt;&#xA;      &lt;td&gt;2832.791548&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;Alaska&lt;/td&gt;&#xA;      &lt;td&gt;1438&lt;/td&gt;&#xA;      &lt;td&gt;253.0&lt;/td&gt;&#xA;      &lt;td&gt;1185.0&lt;/td&gt;&#xA;      &lt;td&gt;731.0&lt;/td&gt;&#xA;      &lt;td&gt;13.132695&lt;/td&gt;&#xA;      &lt;td&gt;1621.067031&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;Arizona&lt;/td&gt;&#xA;      &lt;td&gt;33190&lt;/td&gt;&#xA;      &lt;td&gt;13124.0&lt;/td&gt;&#xA;      &lt;td&gt;20066.0&lt;/td&gt;&#xA;      &lt;td&gt;7421.0&lt;/td&gt;&#xA;      &lt;td&gt;18.515025&lt;/td&gt;&#xA;      &lt;td&gt;2703.948255&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;Arkansas&lt;/td&gt;&#xA;      &lt;td&gt;13068&lt;/td&gt;&#xA;      &lt;td&gt;4895.0&lt;/td&gt;&#xA;      &lt;td&gt;8173.0&lt;/td&gt;&#xA;      &lt;td&gt;3031.0&lt;/td&gt;&#xA;      &lt;td&gt;17.683933&lt;/td&gt;&#xA;      &lt;td&gt;2696.469812&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;California&lt;/td&gt;&#xA;      &lt;td&gt;104277&lt;/td&gt;&#xA;      &lt;td&gt;41284.0&lt;/td&gt;&#xA;      &lt;td&gt;62993.0&lt;/td&gt;&#xA;      &lt;td&gt;39368.0&lt;/td&gt;&#xA;      &lt;td&gt;15.179841&lt;/td&gt;&#xA;      &lt;td&gt;1600.106686&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;presidential-election-results&#34; class=&#34;content-heading&#34;&gt;Presidential election results&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Similar to the article we want to generate a variable &lt;code&gt;biden&lt;/code&gt; which indicates Joe Biden&amp;rsquo;s margin of victory over Donald Trump in the 2020 elections.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# load election results by state for 2020 presidential election&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;election_results&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;democratic_vs_republican_votes_by_usa_state_2020.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;drop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;usa_state_code&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;axis&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;election_results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;biden&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;election_results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;percent_democrat&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;election_results&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;state&lt;/th&gt;&#xA;      &lt;th&gt;DEM&lt;/th&gt;&#xA;      &lt;th&gt;REP&lt;/th&gt;&#xA;      &lt;th&gt;usa_state&lt;/th&gt;&#xA;      &lt;th&gt;percent_democrat&lt;/th&gt;&#xA;      &lt;th&gt;biden&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;Alabama&lt;/td&gt;&#xA;      &lt;td&gt;843473&lt;/td&gt;&#xA;      &lt;td&gt;1434159&lt;/td&gt;&#xA;      &lt;td&gt;Alabama&lt;/td&gt;&#xA;      &lt;td&gt;37.032892&lt;/td&gt;&#xA;      &lt;td&gt;-12.967108&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;Alaska&lt;/td&gt;&#xA;      &lt;td&gt;45758&lt;/td&gt;&#xA;      &lt;td&gt;80999&lt;/td&gt;&#xA;      &lt;td&gt;Alaska&lt;/td&gt;&#xA;      &lt;td&gt;36.098993&lt;/td&gt;&#xA;      &lt;td&gt;-13.901007&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;Arizona&lt;/td&gt;&#xA;      &lt;td&gt;1643664&lt;/td&gt;&#xA;      &lt;td&gt;1626679&lt;/td&gt;&#xA;      &lt;td&gt;Arizona&lt;/td&gt;&#xA;      &lt;td&gt;50.259682&lt;/td&gt;&#xA;      &lt;td&gt;0.259682&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;Arkansas&lt;/td&gt;&#xA;      &lt;td&gt;420985&lt;/td&gt;&#xA;      &lt;td&gt;761251&lt;/td&gt;&#xA;      &lt;td&gt;Arkansas&lt;/td&gt;&#xA;      &lt;td&gt;35.609218&lt;/td&gt;&#xA;      &lt;td&gt;-14.390782&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;California&lt;/td&gt;&#xA;      &lt;td&gt;9315259&lt;/td&gt;&#xA;      &lt;td&gt;4812735&lt;/td&gt;&#xA;      &lt;td&gt;California&lt;/td&gt;&#xA;      &lt;td&gt;65.934760&lt;/td&gt;&#xA;      &lt;td&gt;15.934760&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;5&lt;/th&gt;&#xA;      &lt;td&gt;Colorado&lt;/td&gt;&#xA;      &lt;td&gt;1753416&lt;/td&gt;&#xA;      &lt;td&gt;1335253&lt;/td&gt;&#xA;      &lt;td&gt;Colorado&lt;/td&gt;&#xA;      &lt;td&gt;56.769307&lt;/td&gt;&#xA;      &lt;td&gt;6.769307&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;6&lt;/th&gt;&#xA;      &lt;td&gt;Connecticut&lt;/td&gt;&#xA;      &lt;td&gt;1059252&lt;/td&gt;&#xA;      &lt;td&gt;699079&lt;/td&gt;&#xA;      &lt;td&gt;Connecticut&lt;/td&gt;&#xA;      &lt;td&gt;60.241900&lt;/td&gt;&#xA;      &lt;td&gt;10.241900&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;7&lt;/th&gt;&#xA;      &lt;td&gt;Delaware&lt;/td&gt;&#xA;      &lt;td&gt;295413&lt;/td&gt;&#xA;      &lt;td&gt;199857&lt;/td&gt;&#xA;      &lt;td&gt;Delaware&lt;/td&gt;&#xA;      &lt;td&gt;59.646859&lt;/td&gt;&#xA;      &lt;td&gt;9.646859&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;8&lt;/th&gt;&#xA;      &lt;td&gt;District of Columbia&lt;/td&gt;&#xA;      &lt;td&gt;258561&lt;/td&gt;&#xA;      &lt;td&gt;14449&lt;/td&gt;&#xA;      &lt;td&gt;District of Columbia&lt;/td&gt;&#xA;      &lt;td&gt;94.707520&lt;/td&gt;&#xA;      &lt;td&gt;44.707520&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;9&lt;/th&gt;&#xA;      &lt;td&gt;Florida&lt;/td&gt;&#xA;      &lt;td&gt;5294767&lt;/td&gt;&#xA;      &lt;td&gt;5667834&lt;/td&gt;&#xA;      &lt;td&gt;Florida&lt;/td&gt;&#xA;      &lt;td&gt;48.298456&lt;/td&gt;&#xA;      &lt;td&gt;-1.701544&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# merge to deaths dataframe&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;death_and_election&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deaths_and_states&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;merge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;election_results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;biden&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]],&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;how&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;left&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;on&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;state&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;vaccination-rates&#34; class=&#34;content-heading&#34;&gt;Vaccination rates&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Lastly, we add the vaccination rates per state after the pandemic was over. I use the vaccination rates from 10.5.2023 as this data was easily available.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;vaccinations_raw&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;us_state_vaccinations.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;columns&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;location&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;vaccinations_raw&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;New York State&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;New York&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inplace&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# chose date and relevant columns&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;vaccinations&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vaccinations_raw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vaccinations_raw&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;date&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;2023-05-10&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;people_vaccinated_per_hundred&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;p&gt;Next, we merge the vaccination rates with the dataframe to get our final dataset.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;death_and_election&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;merge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vaccinations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;how&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;left&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;on&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;state&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_per_million&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;biden&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;perc_over_65&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;people_vaccinated_per_hundred&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;div&gt;&#xA;&lt;style scoped&gt;&#xA;    .dataframe tbody tr th:only-of-type {&#xA;        vertical-align: middle;&#xA;    }&#xA;&lt;pre&gt;&lt;code&gt;.dataframe tbody tr th {&#xA;    vertical-align: top;&#xA;}&#xA;&#xA;.dataframe thead th {&#xA;    text-align: right;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;/style&gt;&lt;/p&gt;&#xA;&lt;table border=&#34;1&#34; class=&#34;dataframe&#34;&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr style=&#34;text-align: right;&#34;&gt;&#xA;      &lt;th&gt;&lt;/th&gt;&#xA;      &lt;th&gt;state&lt;/th&gt;&#xA;      &lt;th&gt;deaths_per_million&lt;/th&gt;&#xA;      &lt;th&gt;biden&lt;/th&gt;&#xA;      &lt;th&gt;perc_over_65&lt;/th&gt;&#xA;      &lt;th&gt;people_vaccinated_per_hundred&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;0&lt;/th&gt;&#xA;      &lt;td&gt;Alabama&lt;/td&gt;&#xA;      &lt;td&gt;2832.791548&lt;/td&gt;&#xA;      &lt;td&gt;-12.967108&lt;/td&gt;&#xA;      &lt;td&gt;17.757009&lt;/td&gt;&#xA;      &lt;td&gt;65.12&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;1&lt;/th&gt;&#xA;      &lt;td&gt;Alaska&lt;/td&gt;&#xA;      &lt;td&gt;1621.067031&lt;/td&gt;&#xA;      &lt;td&gt;-13.901007&lt;/td&gt;&#xA;      &lt;td&gt;13.132695&lt;/td&gt;&#xA;      &lt;td&gt;73.23&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;2&lt;/th&gt;&#xA;      &lt;td&gt;Arizona&lt;/td&gt;&#xA;      &lt;td&gt;2703.948255&lt;/td&gt;&#xA;      &lt;td&gt;0.259682&lt;/td&gt;&#xA;      &lt;td&gt;18.515025&lt;/td&gt;&#xA;      &lt;td&gt;78.37&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;3&lt;/th&gt;&#xA;      &lt;td&gt;Arkansas&lt;/td&gt;&#xA;      &lt;td&gt;2696.469812&lt;/td&gt;&#xA;      &lt;td&gt;-14.390782&lt;/td&gt;&#xA;      &lt;td&gt;17.683933&lt;/td&gt;&#xA;      &lt;td&gt;70.09&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;4&lt;/th&gt;&#xA;      &lt;td&gt;California&lt;/td&gt;&#xA;      &lt;td&gt;1600.106686&lt;/td&gt;&#xA;      &lt;td&gt;15.934760&lt;/td&gt;&#xA;      &lt;td&gt;15.179841&lt;/td&gt;&#xA;      &lt;td&gt;85.07&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;I am also storing the final dataset as a parquet file in case you want to play with it. To find it, follow the link at the bottom of the page.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_per_million&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;biden&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;perc_over_65&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;people_vaccinated_per_hundred&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_parquet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;death_partisanship_final_dataset.parquet&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;engine&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;pyarrow&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;h1 id=&#34;regressions&#34; class=&#34;content-heading&#34;&gt;Regressions&#xA;&lt;/h1&gt;&#xA;&lt;p&gt;With the assembled dataset we can now reproduce Nate Silver&amp;rsquo;s findings.&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-regression-state-partisanship-on-death-rates&#34; class=&#34;content-heading&#34;&gt;1. Regression: state partisanship on death rates&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Silver starts with a one-variable baseline model. And indeed &lt;code&gt;biden&lt;/code&gt;, Joe Biden&amp;rsquo;s winning margin, is a statistically significant predictor of COVID deaths. According to the model, a one-percentage-point increase in Biden&amp;rsquo;s margin reduced expected COVID deaths by ~30 covid deaths per million population.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;biden&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;deaths_per_million&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# add a constant term to the model&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_constant&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# run regression&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OLS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;print_model&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;print_model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;                            OLS Regression Results                            &#xA;==============================================================================&#xA;Dep. Variable:     deaths_per_million   R-squared:                       0.286&#xA;Model:                            OLS   Adj. R-squared:                  0.272&#xA;Method:                 Least Squares   F-statistic:                     19.27&#xA;Date:                Sun, 14 Jan 2024   Prob (F-statistic):           6.22e-05&#xA;Time:                        18:05:09   Log-Likelihood:                -381.14&#xA;No. Observations:                  50   AIC:                             766.3&#xA;Df Residuals:                      48   BIC:                             770.1&#xA;Df Model:                           1                                         &#xA;Covariance Type:            nonrobust                                         &#xA;==============================================================================&#xA;                 coef    std err          t      P&amp;gt;|t|      [0.025      0.975]&#xA;------------------------------------------------------------------------------&#xA;const       2031.3050     72.204     28.133      0.000    1886.129    2176.481&#xA;biden        -29.7773      6.784     -4.389      0.000     -43.418     -16.137&#xA;==============================================================================&#xA;Omnibus:                        0.718   Durbin-Watson:                   2.263&#xA;Prob(Omnibus):                  0.698   Jarque-Bera (JB):                0.732&#xA;Skew:                          -0.266   Prob(JB):                        0.694&#xA;Kurtosis:                       2.737   Cond. No.                         10.8&#xA;==============================================================================&#xA;&#xA;Notes:&#xA;[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;We can also plot the data set and the regression line to get a more intuitive overview of the result:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;fig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subplots&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;figsize&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scatter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;biden&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;deaths_per_million&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xlabel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Margin &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;% f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;or Biden (positive values mean Democrats won)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ylabel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Post vaccine (Feb 2021) deaths per 1M population&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xy1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;slope&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;red&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;plt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;figure&gt;&lt;img src=&#34;https://staticnotes.org/posts/covid_bipartisan_bayesian/output_30_0.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;h3 id=&#34;2-regression-state-partisanship-and-age-on-death-rates&#34; class=&#34;content-heading&#34;&gt;2. Regression: state partisanship and age on death rates&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Silver&amp;rsquo;s article is a response to criticism that the model above is not valuable because different states have different age structures and that may explain most of the variation in death rates. Silver remarks that the results hold even when controlling for age. We can add age &lt;code&gt;perc_over_65&lt;/code&gt; to the model and re-run the regression and indeed we get the same result. &lt;code&gt;biden&lt;/code&gt; is still significant with a similar coefficient.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;biden&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;perc_over_65&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;y2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;deaths_per_million&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_constant&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;model2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OLS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;print_model2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;print_model2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;                            OLS Regression Results                            &#xA;==============================================================================&#xA;Dep. Variable:     deaths_per_million   R-squared:                       0.397&#xA;Model:                            OLS   Adj. R-squared:                  0.371&#xA;Method:                 Least Squares   F-statistic:                     15.44&#xA;Date:                Sun, 14 Jan 2024   Prob (F-statistic):           6.99e-06&#xA;Time:                        18:05:12   Log-Likelihood:                -376.95&#xA;No. Observations:                  50   AIC:                             759.9&#xA;Df Residuals:                      47   BIC:                             765.6&#xA;Df Model:                           2                                         &#xA;Covariance Type:            nonrobust                                         &#xA;================================================================================&#xA;                   coef    std err          t      P&amp;gt;|t|      [0.025      0.975]&#xA;--------------------------------------------------------------------------------&#xA;const          256.0210    609.788      0.420      0.677    -970.714    1482.756&#xA;biden          -32.9481      6.397     -5.151      0.000     -45.817     -20.079&#xA;perc_over_65   101.6118     34.690      2.929      0.005      31.824     171.400&#xA;==============================================================================&#xA;Omnibus:                        1.194   Durbin-Watson:                   2.318&#xA;Prob(Omnibus):                  0.551   Jarque-Bera (JB):                1.061&#xA;Skew:                          -0.162   Prob(JB):                        0.588&#xA;Kurtosis:                       2.365   Cond. No.                         162.&#xA;==============================================================================&#xA;&#xA;Notes:&#xA;[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;3-regression-state-partisanship-age-and-vaccination-rates-on-death-rates&#34; class=&#34;content-heading&#34;&gt;3. Regression: state partisanship, age, and vaccination rates on death rates&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;Clearly your political leanings are not a predictor for your chance of dying from COVID. The assumption behind the model is that Republicans have been less likely to get vaccinated, and unvaccinated humans have a higher mortality w.r.t COVID. We can check what happens if we add the vaccination rates as a variable to the model.&lt;/p&gt;&#xA;&lt;p&gt;We can see below that vaccination rate is significant and explains away the effect of the &lt;code&gt;biden&lt;/code&gt; variable.&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;biden&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;perc_over_65&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;people_vaccinated_per_hundred&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;y3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;deaths_per_million&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_constant&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;model3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OLS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;print_model3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;print_model3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;                            OLS Regression Results                            &#xA;==============================================================================&#xA;Dep. Variable:     deaths_per_million   R-squared:                       0.450&#xA;Model:                            OLS   Adj. R-squared:                  0.414&#xA;Method:                 Least Squares   F-statistic:                     12.55&#xA;Date:                Sun, 14 Jan 2024   Prob (F-statistic):           4.01e-06&#xA;Time:                        18:05:13   Log-Likelihood:                -374.63&#xA;No. Observations:                  50   AIC:                             757.3&#xA;Df Residuals:                      46   BIC:                             764.9&#xA;Df Model:                           3                                         &#xA;Covariance Type:            nonrobust                                         &#xA;=================================================================================================&#xA;                                    coef    std err          t      P&amp;gt;|t|      [0.025      0.975]&#xA;-------------------------------------------------------------------------------------------------&#xA;const                          1528.3900    841.133      1.817      0.076    -164.723    3221.503&#xA;biden                           -15.9990     10.110     -1.583      0.120     -36.349       4.351&#xA;perc_over_65                    114.7298     34.042      3.370      0.002      46.207     183.253&#xA;people_vaccinated_per_hundred   -18.5072      8.743     -2.117      0.040     -36.106      -0.908&#xA;==============================================================================&#xA;Omnibus:                        0.262   Durbin-Watson:                   2.192&#xA;Prob(Omnibus):                  0.877   Jarque-Bera (JB):                0.454&#xA;Skew:                           0.027   Prob(JB):                        0.797&#xA;Kurtosis:                       2.537   Cond. No.                     1.08e+03&#xA;==============================================================================&#xA;&#xA;Notes:&#xA;[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.&#xA;[2] The condition number is large, 1.08e+03. This might indicate that there are&#xA;strong multicollinearity or other numerical problems.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;4-regression-age-and-vaccination-rates-on-death-rates&#34; class=&#34;content-heading&#34;&gt;4. Regression: age and vaccination rates on death rates&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;In a final step, we remove the correlated variable &lt;code&gt;biden&lt;/code&gt; from the model to demonstrate the impact of age and vaccination rate on death rate:&lt;/p&gt;&#xA;&lt;div class=&#34;code-block&#34; data-lang=&#34;python&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x4&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;perc_over_65&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;people_vaccinated_per_hundred&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;y4&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;deaths_per_million&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;x4&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add_constant&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;model4&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OLS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;print_model4&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model4&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;print_model4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code&gt;                            OLS Regression Results                            &#xA;==============================================================================&#xA;Dep. Variable:     deaths_per_million   R-squared:                       0.420&#xA;Model:                            OLS   Adj. R-squared:                  0.396&#xA;Method:                 Least Squares   F-statistic:                     17.03&#xA;Date:                Sun, 14 Jan 2024   Prob (F-statistic):           2.74e-06&#xA;Time:                        18:05:14   Log-Likelihood:                -375.95&#xA;No. Observations:                  50   AIC:                             757.9&#xA;Df Residuals:                      47   BIC:                             763.6&#xA;Df Model:                           2                                         &#xA;Covariance Type:            nonrobust                                         &#xA;=================================================================================================&#xA;                                    coef    std err          t      P&amp;gt;|t|      [0.025      0.975]&#xA;-------------------------------------------------------------------------------------------------&#xA;const                          2386.5532    653.203      3.654      0.001    1072.478    3700.629&#xA;perc_over_65                    117.0242     34.551      3.387      0.001      47.516     186.532&#xA;people_vaccinated_per_hundred   -29.4653      5.423     -5.434      0.000     -40.374     -18.556&#xA;==============================================================================&#xA;Omnibus:                        0.653   Durbin-Watson:                   2.211&#xA;Prob(Omnibus):                  0.722   Jarque-Bera (JB):                0.527&#xA;Skew:                           0.244   Prob(JB):                        0.768&#xA;Kurtosis:                       2.881   Cond. No.                         829.&#xA;==============================================================================&#xA;&#xA;Notes:&#xA;[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;jupyter-notebook&#34; class=&#34;content-heading&#34;&gt;Jupyter Notebook&#xA;&lt;/h3&gt;&#xA;&lt;p&gt;You can find the Jupyter notebook and the datasets for this post &lt;a href=&#34;https://gitlab.com/frankRi89/blog/-/tree/main/notebooks/covid_bipartisian&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;here&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;            style=&#34;height: 0.7em; width: 0.7em; padding-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;            class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;            viewBox=&#34;0 0 512 512&#34;&gt;&#xA;            &lt;path fill=&#34;currentColor&#34;&#xA;                d=&#34;M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z&#34;&gt;&#xA;            &lt;/path&gt;&#xA;        &lt;/svg&gt;&#xA;    &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>On Writing Well - 80/20 Checklist</title>
      <link>https://staticnotes.org/posts/writing-well-checklist/</link>
      <pubDate>Mon, 14 Aug 2023 00:00:00 +0100</pubDate>
      
      <guid>https://staticnotes.org/posts/writing-well-checklist/</guid>
      <description>&lt;p&gt;This is a checklist that I use at work to quickly sense check my drafts of strategy documents, tech proposals, PR reviews, project feedback, and other places where effective writing is helpful. It lists suggestions from the book &lt;a href=&#34;https://www.goodreads.com/en/book/show/53343&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;On Writing Well&#xA;    &#xA;&#xA;        &#xA;    &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;        style=&#34;height: 0.7em; width: 0.9em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;        class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;        viewBox=&#34;0 0 448 512&#34;&gt;&#xA;        &lt;path fill=&#34;currentColor&#34;&#xA;            d=&#34;M299.9 191.2c5.1 37.3-4.7 79-35.9 100.7-22.3 15.5-52.8 14.1-70.8 5.7-37.1-17.3-49.5-58.6-46.8-97.2 4.3-60.9 40.9-87.9 75.3-87.5 46.9-.2 71.8 31.8 78.2 78.3zM448 88v336c0 30.9-25.1 56-56 56H56c-30.9 0-56-25.1-56-56V88c0-30.9 25.1-56 56-56h336c30.9 0 56 25.1 56 56zM330 313.2s-.1-34-.1-217.3h-29v40.3c-.8 .3-1.2-.5-1.6-1.2-9.6-20.7-35.9-46.3-76-46-51.9 .4-87.2 31.2-100.6 77.8-4.3 14.9-5.8 30.1-5.5 45.6 1.7 77.9 45.1 117.8 112.4 115.2 28.9-1.1 54.5-17 69-45.2 .5-1 1.1-1.9 1.7-2.9 .2 .1 .4 .1 .6 .2 .3 3.8 .2 30.7 .1 34.5-.2 14.8-2 29.5-7.2 43.5-7.8 21-22.3 34.7-44.5 39.5-17.8 3.9-35.6 3.8-53.2-1.2-21.5-6.1-36.5-19-41.1-41.8-.3-1.6-1.3-1.3-2.3-1.3h-26.8c.8 10.6 3.2 20.3 8.5 29.2 24.2 40.5 82.7 48.5 128.2 37.4 49.9-12.3 67.3-54.9 67.4-106.3z&#34;&gt;&#xA;        &lt;/path&gt;&#xA;    &lt;/svg&gt;&#xA;&lt;/span&gt;&#xA;&#xA;&#xA;&#xA;    &#xA;&lt;/a&gt; that I covered in this &lt;a href=&#34;../posts/writing-well/&#34; &#xA;&gt;blog post&#xA;&lt;/a&gt;. As I mentioned in the blog post I am not striving for perfection. Instead I want to be able to identify the main parts of my first draft that I can improve within 5&amp;ndash;20 minutes of editing time.&lt;/p&gt;&#xA;&lt;h2 id=&#34;clear-thinking&#34; class=&#34;content-heading&#34;&gt;Clear Thinking&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I am clear about what the main point of the article is, who my audience is, and why they should care.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;structure&#34; class=&#34;content-heading&#34;&gt;Structure&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I have paid special attention to the first sentence and made it interesting.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The first paragraph hooks the reader by being fresh, novel, paradoxical, humorous, surprising, unusual or starting with an interesting fact or question.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The first paragraph tells the reader what the article is about and why they should care.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Every paragraph is kept reasonably short and captures one logical idea.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The last sentence of each paragraph entices the reader to keep reading.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The article is not longer than it needs to be. It does not attempt to cover every aspect of the topic.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I paid attention to the end. The end happens in a fitting, unexpected or surprising way that should keep the reader thinking about the text.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;unity&#34; class=&#34;content-heading&#34;&gt;Unity&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The text is mostly written in one tense.&lt;/li&gt;&#xA;&lt;li&gt;The reader is addressed with the same pronoun.&lt;/li&gt;&#xA;&lt;li&gt;The tone is not changed (casual vs. formal, neutral vs. involved).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;words&#34; class=&#34;content-heading&#34;&gt;Words&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Every word is essential for the sentence and doing new work.&lt;/li&gt;&#xA;&lt;li&gt;Unnecessary adverbs are avoided.&lt;/li&gt;&#xA;&lt;li&gt;Unnecessary adjectives are avoided, e.g. &amp;ldquo;diligent code review&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;Words that have shorter alternatives are replaced, e.g. “assistance” (help), “numerous” (many), “facilitate” (ease), “sufficient” (enough), “attempt” (try).&lt;/li&gt;&#xA;&lt;li&gt;Words that inflate importance are avoided, e.g. “with the possible exception of” (except), “due to the fact that” (because).&lt;/li&gt;&#xA;&lt;li&gt;Small qualifier words are removed: “a bit,” “a little,” “sort of,” “kind of,” “rather,” “quite,” “very,” “too,” “pretty much,” “in a sense”. Be confident in what you write.&lt;/li&gt;&#xA;&lt;li&gt;Active verbs are used over passive verbs, e.g. “Joe documented the architecture” over “The architecture was documented by Joe”.&lt;/li&gt;&#xA;&lt;li&gt;Concept nouns are replaced by active verbs. Instead of “The monitoring system is used to detect data drift.” use “We monitor our data to detect drift.”&lt;/li&gt;&#xA;&lt;li&gt;Verbs are precise: “The CEO resigned” instead of “The CEO left”.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;style&#34; class=&#34;content-heading&#34;&gt;Style&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Sentences are kept short.&lt;/li&gt;&#xA;&lt;li&gt;Sentences link logically to the next. If not, a link is explicitly provided.&lt;/li&gt;&#xA;&lt;li&gt;Avoid exclamation points unless for effect.&lt;/li&gt;&#xA;&lt;li&gt;Use contractions like &amp;ldquo;I&amp;rsquo;ll&amp;rdquo;, &amp;ldquo;I&amp;rsquo;ve&amp;rdquo;, but not &amp;ldquo;I&amp;rsquo;d&amp;rdquo; as this can mean both &amp;ldquo;I had&amp;rdquo; and &amp;ldquo;I would&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;Always use &amp;ldquo;that&amp;rdquo; over &amp;ldquo;which&amp;rdquo;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;tone&#34; class=&#34;content-heading&#34;&gt;Tone&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Avoid business lingo and concept nouns, e.g. &amp;ldquo;incident management procedures&amp;rdquo;. Replace them with active verbs and plain talk.&lt;/li&gt;&#xA;&lt;li&gt;Try to write in a human way. Make people do things using active verbs.&lt;/li&gt;&#xA;&lt;li&gt;Resist trying to sound smart in work documents.&lt;/li&gt;&#xA;&lt;li&gt;Avoid sexism in language: &amp;ldquo;Software Engineers can spend more time with their families.&amp;rdquo; instead of &amp;ldquo;Software Engineers can spend more time with their wives and children.&amp;rdquo;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    
    <item>
      <title>What I learned from On Writing Well</title>
      <link>https://staticnotes.org/posts/writing-well/</link>
      <pubDate>Sat, 12 Aug 2023 00:00:00 +0100</pubDate>
      
      <guid>https://staticnotes.org/posts/writing-well/</guid>
      <description>&lt;p&gt;Writing a good blog post that summarises William Zinsser&amp;rsquo;s classic book &lt;a href=&#34;https://www.goodreads.com/en/book/show/53343&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;On Writing Well&#xA;    &#xA;&#xA;        &#xA;    &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;        style=&#34;height: 0.7em; width: 0.9em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;        class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;        viewBox=&#34;0 0 448 512&#34;&gt;&#xA;        &lt;path fill=&#34;currentColor&#34;&#xA;            d=&#34;M299.9 191.2c5.1 37.3-4.7 79-35.9 100.7-22.3 15.5-52.8 14.1-70.8 5.7-37.1-17.3-49.5-58.6-46.8-97.2 4.3-60.9 40.9-87.9 75.3-87.5 46.9-.2 71.8 31.8 78.2 78.3zM448 88v336c0 30.9-25.1 56-56 56H56c-30.9 0-56-25.1-56-56V88c0-30.9 25.1-56 56-56h336c30.9 0 56 25.1 56 56zM330 313.2s-.1-34-.1-217.3h-29v40.3c-.8 .3-1.2-.5-1.6-1.2-9.6-20.7-35.9-46.3-76-46-51.9 .4-87.2 31.2-100.6 77.8-4.3 14.9-5.8 30.1-5.5 45.6 1.7 77.9 45.1 117.8 112.4 115.2 28.9-1.1 54.5-17 69-45.2 .5-1 1.1-1.9 1.7-2.9 .2 .1 .4 .1 .6 .2 .3 3.8 .2 30.7 .1 34.5-.2 14.8-2 29.5-7.2 43.5-7.8 21-22.3 34.7-44.5 39.5-17.8 3.9-35.6 3.8-53.2-1.2-21.5-6.1-36.5-19-41.1-41.8-.3-1.6-1.3-1.3-2.3-1.3h-26.8c.8 10.6 3.2 20.3 8.5 29.2 24.2 40.5 82.7 48.5 128.2 37.4 49.9-12.3 67.3-54.9 67.4-106.3z&#34;&gt;&#xA;        &lt;/path&gt;&#xA;    &lt;/svg&gt;&#xA;&lt;/span&gt;&#xA;&#xA;&#xA;&#xA;    &#xA;&lt;/a&gt; is stressful. I don&amp;rsquo;t want to break his rules while writing about them. I will attempt this anyway since I learned a lot from his book.&lt;/p&gt;&#xA;&lt;p&gt;Notes that I write for myself are pretty sloppy, unstructured, and stream-of-consciousness, but I care about my writing when others read it. Unfortunately, my most regular readers at the moment are probably my work colleagues. I often draft project or strategy documents that others need to understand and engage with. I am trying hard to keep the style non-corporate and maybe even a bit fun to read.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt;I probably use too many self-made memes.&lt;/small&gt;&lt;/span&gt;I don&amp;rsquo;t think William Zinsser considered tech guys writing data strategy documents part of his target audience, but his advice is universal.&lt;/p&gt;&#xA;&lt;p&gt;William Zinsser argues in his book that an average reader has an attention span of 30 seconds&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt;An estimate he made in the pre-social media year of 2006.&lt;/small&gt;&lt;/span&gt; and that their attention is competing with a dozen alternative activities. He argues that the key to good writing is &lt;strong&gt;clear and engaging structure&lt;/strong&gt;, &lt;strong&gt;simplicity&lt;/strong&gt;, and, in the context of business writing, &lt;strong&gt;humanity&lt;/strong&gt;. I will share my takeaways and a checklist that I use during my writing process.&lt;/p&gt;&#xA;&lt;h2 id=&#34;structure---clear-thinking-produces-clear-writing&#34; class=&#34;content-heading&#34;&gt;Structure - Clear thinking produces clear writing&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;When writing, you should think clearly about what you want to say. Illogical and bad writing is a result of being unsure about the purpose and structure of the text.&#xA;We all can relate. Writing is an iterative process. You often start an article with different ideas and arguments than when you reach the end. During the writing process you come up with better arguments that you want to include or that you can explain better. This is natural and you should enjoy the process of editing and deleting to ensure your first draft gets a coherent structure.&lt;/p&gt;&#xA;&lt;p&gt;Ask yourself: &amp;ldquo;Did I write what I wanted to say?&amp;rdquo; and &amp;ldquo;Can my reader easily follow my narrative from the first paragraph to the last?&amp;rdquo; The second question relates to the earlier idea of a lazy reader, who will stop reading if they are not hooked or need to spend brain power to follow your train of thought. How do you avoid that?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;The most important sentence of your writing is the first one.&lt;/strong&gt; It must induce the reader to read the second sentence. The second sentence must do the same for the third sentence and so on. &lt;strong&gt;The goal is to hook the reader in the first paragraph&lt;/strong&gt;. Zinsser calls this &amp;ldquo;the lead&amp;rdquo; and it should achieve two things:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;To be an effective hook it should be: fresh, novel, paradoxical, humorous, surprising, unusual or be an interesting fact or question. It needs to force the reader to keep reading.&lt;/li&gt;&#xA;&lt;li&gt;It needs to tell the reader what the article is about and why they should care.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Once the reader is hooked, ensure that the last sentence of each paragraph entices them to continue to the next. The end of a paragraph is often a natural stopping point. The paragraphs should be kept short and reflect one idea. Once you have said what you wanted to say, stop. Be comfortable dropping material. Decide which part of the subject you want to cover. Cover it well and then stop.&lt;/p&gt;&#xA;&lt;p&gt;How do you end your piece the right way? Try to encapsulate the main idea of the text and &lt;strong&gt;end in a fitting, unexpected or surprising way&lt;/strong&gt;. Like a good dessert, the last paragraph or sentence should be a joy in itself and linger for a moment after the end.&lt;/p&gt;&#xA;&lt;h2 id=&#34;simplicity---make-it-easy-for-your-readers&#34; class=&#34;content-heading&#34;&gt;Simplicity - Make it easy for your readers&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Like good structure, simplicity helps your reader stay engaged. Unfortunately, while you write you will accumulate clutter. This can be words that do not add value or sentences that are difficult to follow. You can achieve simplicity by ensuring that:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;every word in a sentence is doing new work&lt;/li&gt;&#xA;&lt;li&gt;sentences are short and logically linked together.&lt;/li&gt;&#xA;&lt;li&gt;you have unity in choice of tense, pronouns, and style&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Zinsser argues that &lt;strong&gt;writing improves proportionally to the number of things you can keep out of it that should not be there&lt;/strong&gt;. Be critical of the words you choose and avoid:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Words that do not do extra work, e.g. “a personal friend of mine” does not add more than &amp;ldquo;a friend&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;Unnecessary adverbs. &amp;ldquo;I wrote up the documentation&amp;rdquo;. &amp;ldquo;up&amp;rdquo; is not required. &amp;ldquo;My algorithm is decidedly better than brute-force&amp;rdquo;. &amp;ldquo;decidedly&amp;rdquo; does not add anything.&lt;/li&gt;&#xA;&lt;li&gt;Avoid adjectives unless absolutely necessary, e.g. do not write &amp;ldquo;diligent code review&amp;rdquo; unless your company does not care about code reviews.&lt;/li&gt;&#xA;&lt;li&gt;Words that have shorter alternatives, e.g. “assistance” (help), “numerous” (many), “facilitate” (ease), “sufficient” (enough), “attempt” (try).&lt;/li&gt;&#xA;&lt;li&gt;Words that inflate importance, e.g. “with the possible exception of” (except), “due to the fact that” (because), “he totally lacked the ability to” (he couldn’t), “for the purpose of” (for).&lt;/li&gt;&#xA;&lt;li&gt;Remove the small words that qualify how you feel and how you think and what you saw: “a bit,” “a little,” “sort of,” “kind of,” “rather,” “quite,” “very,” “too,” “pretty much,” “in a sense”.&lt;/li&gt;&#xA;&lt;li&gt;Prefer active verbs over passive, e.g. &amp;ldquo;Joe documented the architecture&amp;rdquo; over &amp;ldquo;The architecture was documented by Joe&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;Nouns that express a concept are commonly used in bad writing instead of verbs that tell what somebody did. Instead of &amp;ldquo;The monitoring system is used to detect data drift.&amp;rdquo; use &amp;ldquo;We monitor our data to detect drift.&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;Use precise verbs: &amp;ldquo;Start a company&amp;rdquo; instead of &amp;ldquo;Set up a company&amp;rdquo;. &amp;ldquo;The CEO resigned&amp;rdquo; or &amp;ldquo;The CEO was fired&amp;rdquo; instead of &amp;ldquo;The CEO stepped down&amp;rdquo;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;After applying these rules your sentences should be clear and stripped of clutter. Now your job is to ensure that sentence B follows logically from sentence A. Also ensure that sentence F does not repeat the same argument made in sentence A. If the connections are not clear, provide the missing link. My favourite quote in the book is on the question of sentence length. Zinsser advises: &lt;strong&gt;&amp;ldquo;If you want to write long sentences, be a genius.&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Aside from a careful choice of words and logical sentences, you should strive for unity in:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;tense. Stick to one tense.&lt;/li&gt;&#xA;&lt;li&gt;pronouns. Use the same pronoun to address your reader.&lt;/li&gt;&#xA;&lt;li&gt;tone. Are you writing casually or formally, involved or detached, ironic or amused?&lt;/li&gt;&#xA;&lt;li&gt;style. Are you writing a Wikipedia entry, a personal travel story, or a tech strategy?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Decide on these points at the beginning and do not change unless necessary.&lt;/p&gt;&#xA;&lt;h2 id=&#34;humanity---plain-talk-not-vanity&#34; class=&#34;content-heading&#34;&gt;Humanity - Plain talk, not vanity&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;After you have internalised the advice from the previous two sections you can start applying it at work. What could go wrong?&lt;/p&gt;&#xA;&lt;p&gt;People at work have a tendency to write in a pretentious style, e.g. &amp;ldquo;The company uses evaluative procedures for our objectives based on our KPIs.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;Instead of dead concept nouns like &amp;ldquo;evaluative procedures&amp;rdquo; use active verbs and plain talk, e.g. a better way is &amp;ldquo;We will evaluate our progress based on our KPIs.&amp;rdquo; You should aim to stay natural and write how you talk. A good test is to ensure your colleagues can visualise who is doing what when they read your sentence.&lt;/p&gt;&#xA;&lt;p&gt;To incorporate Zinsser&amp;rsquo;s advice in my own writing, I created &lt;a href=&#34;../posts/writing-well-checklist/&#34; &#xA;&gt;this checklist&#xA;&lt;/a&gt; that I refer to after completing a first draft. I am not striving for perfection. I don&amp;rsquo;t want to become an author for &lt;em&gt;The New Yorker&lt;/em&gt; magazine or win the Nobel Prize in Literature. Instead, I want to focus on the &lt;a href=&#34;https://en.wikipedia.org/wiki/Pareto_principle&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;~20%&#xA;    &#xA;        &lt;span style=&#34;white-space: nowrap&#34;&gt;&amp;thinsp;&lt;svg&#xA;                style=&#34;height: 0.7em; width: 0.7em; margin-left: -0.2em;&#34; focusable=&#34;false&#34; data-prefix=&#34;fas&#34; data-icon=&#34;external-link-alt&#34;&#xA;                class=&#34;svg-inline--fa fa-external-link-alt fa-w-16&#34; role=&#34;img&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&#xA;                viewBox=&#34;0 0 640 512&#34;&gt;&#xA;                &lt;path fill=&#34;currentColor&#34;&#xA;                    d=&#34;M640 51.2l-.3 12.2c-28.1 .8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3 .3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4 .2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5 .3v13.1c-19.4 .6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4 .3-3.6 0-10.3 .3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5 .8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1 .2 .5z&#34;&gt;&#xA;                &lt;/path&gt;&#xA;            &lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &#xA;    &#xA;&lt;/a&gt; of changes that lead to the largest quality improvement.&lt;/p&gt;&#xA;</description>
    </item>
    
  </channel>
</rss>
