<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>staticnotes.org</title>
    <link>/</link>
    <description>All recent content posts from Rob on staticnotes.org</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-US</language>
    <lastBuildDate>Sun, 18 Jan 2026 20:00:00 +0000</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml" /><image>
      <url>https://staticnotes.org/favicon.ico</url>
      <title>staticnotes.org</title>
    </image>
   
    
    <item>
      <title>UK house price changes in real terms</title>
      <link>/posts/uk-house-prices/</link>
      <pubDate>Sun, 11 Jan 2026 00:00:00 +0000</pubDate>
      
      <guid>/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 difference 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 visualize 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;&gt;&#xA;  &lt;a href=&#34;#querying-the-housing-price-data&#34; class=&#34;header-link&#34;&gt;&#xA;    Querying the housing price data&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;I am using the UK House Price Index of the Land Registry API:&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&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 succesful 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 how the housing market performs close to me or areas that I am interested 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 &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#inspecting-the-data&#34; class=&#34;header-link&#34;&gt;&#xA;    Inspecting the data&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#computing-real-house-prices&#34; class=&#34;header-link&#34;&gt;&#xA;    Computing real house prices&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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 transation per quarter and region in real terms. Now we can visualize the data to finally see what happened.&lt;/p&gt;&#xA; &lt;h2 id=&#34;visualizing-nominal-and-real-house-prices-over-time&#34;&gt;&#xA;  &lt;a href=&#34;#visualizing-nominal-and-real-house-prices-over-time&#34; class=&#34;header-link&#34;&gt;&#xA;    Visualizing nominal and real house prices over time&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;detached-houses-in-south-england-counties&#34;&gt;&#xA;  &lt;a href=&#34;#detached-houses-in-south-england-counties&#34; class=&#34;header-link&#34;&gt;&#xA;    Detached Houses in South England Counties&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#flats-in-london-boroughs&#34; class=&#34;header-link&#34;&gt;&#xA;    Flats in London Boroughs&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#terraced-houses-in-london-boroughs&#34; class=&#34;header-link&#34;&gt;&#xA;    Terraced houses in London Boroughs&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&#xA;&#xA;&lt;img src=&#34;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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#winners-and-losers-in-real-terms-last-3-years&#34; class=&#34;header-link&#34;&gt;&#xA;    Winners and Losers in real terms (last 3 years)&#xA;  &lt;/a&gt;&#xA;&lt;/h1&gt;&lt;p&gt;Lastly I want to see how the housing market in the different London boroughs compare 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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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 did 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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#conclusion&#34; class=&#34;header-link&#34;&gt;&#xA;    Conclusion&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;&gt;&#xA;  &lt;a href=&#34;#appendix&#34; class=&#34;header-link&#34;&gt;&#xA;    Appendix&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;Since someone asked, here are the real price changes compare to 3 years ago for all London boroughs:&lt;/p&gt;&#xA;&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#jupyter-notebook&#34; class=&#34;header-link&#34;&gt;&#xA;    Jupyter Notebook&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;You can find the jupyter notebook for this post &#xA;&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>TIL how to set up multiple SSH keys (for multiple Github accounts)</title>
      <link>/til/2025/11/how-to-set-up-multiple-ssh-keys/</link>
      <pubDate>Fri, 28 Nov 2025 16:20:00 +0000</pubDate>
      
      <guid>/til/2025/11/how-to-set-up-multiple-ssh-keys/</guid>
    <description>&lt;p&gt;Setting up SSH keys is one of these things I need to do every couple of months. Inevitably, I don&amp;rsquo;t remember how to do it and then follow some tutorial, e.g. the &#xA;&lt;a href=&#34;https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Github Docs&#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 kind of always works but I haven&amp;rsquo;t fully internalized how to properly manage those different SSH keys.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Disclaimer&lt;/em&gt;: This learning was provoked by setting up multiple SSH keys for different Github accounts (I know how to do that) and then being able to &lt;code&gt;git clone {private-repository}&lt;/code&gt; a private repository with the correct ssh key (I didn&amp;rsquo;t know how to do that). An example use case could be a personal and professional Github account that don&amp;rsquo;t have access to the same private repositories. So ideally when we git clone we want to automatically pick the right ssh key.&lt;/p&gt;&#xA; &lt;h3 id=&#34;1-generate-the-ssh-keys-for-each-account&#34;&gt;&#xA;  &lt;a href=&#34;#1-generate-the-ssh-keys-for-each-account&#34; class=&#34;header-link&#34;&gt;&#xA;    1. Generate the SSH keys for each account&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;Let&amp;rsquo;s assume we want to generate new separate ssh keys for each account. I like to have them all in my &lt;code&gt;~/.ssh&lt;/code&gt; folder.&#xA;We can use the key generation command&lt;/p&gt;&#xA;&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; ~/.ssh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ssh-keygen -t ed25519 -C &lt;span class=&#34;s2&#34;&gt;&amp;#34;your_email or your_name&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;where we specify the encryption type (&lt;code&gt;-t&lt;/code&gt;) as &lt;code&gt;ed25519&lt;/code&gt; which is &#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/EdDSA#Ed25519&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Edwards-curve Digital Signature Algorithm&#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 generally &#xA;&lt;a href=&#34;https://www.latacora.com/blog/cryptographic-right-answers/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;recommended over RSA-based keys&#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 comment (&lt;code&gt;-C&lt;/code&gt;) argument allows us to optionally add a comment that is added at the back of the key so that you remember who it created. People often use their email address. However, this is not used anywhere to select the key.&lt;/p&gt;&#xA;&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;$ Generating public/private ed25519 key pair.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ Enter file in which to save the key &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;/Users/youruser/.ssh/id_ed25519&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;: /Users/youruser/.ssh/github_personal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;$ Enter passphrase &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;github_personal&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;empty &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; no passphrase&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;: &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This generates both the private and public key &lt;code&gt;github_personal&lt;/code&gt; (private) and &lt;code&gt;github_personal.pub&lt;/code&gt; (public) in the specified path. If we entered a passphrase the private key will be encrypted as well using &#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Triple_DES&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;3DES&#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;. We can check out what the keys look like:&lt;/p&gt;&#xA;&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;$ cat github_personal.pub&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDycaSFXnekEe32AZFhhDp3Q14JRXF7bu8CNfGf7Z6hN your_email &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cat github_personal&#xA;&#xA;-----BEGIN OPENSSH PRIVATE KEY-----&#xA;somegibberylongkeyperhapsfurtherencryptedusingpassphrase&#xA;-----END OPENSSH PRIVATE KEY-----&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s also use the same method to create a keypair for work (&lt;code&gt;github_work&lt;/code&gt;, &lt;code&gt;github_work.pub&lt;/code&gt;). Once we have these keys, we can add them to our two Github accounts.&lt;/p&gt;&#xA; &lt;h3 id=&#34;2-associate-the-public-keys-with-the-github-accounts&#34;&gt;&#xA;  &lt;a href=&#34;#2-associate-the-public-keys-with-the-github-accounts&#34; class=&#34;header-link&#34;&gt;&#xA;    2. Associate the public keys with the Github accounts&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;In both Github accounts, navigate to &lt;code&gt;Access:SSH and GPG Keys&lt;/code&gt; -&amp;gt; &lt;code&gt;New SSH key&lt;/code&gt; and add the &lt;strong&gt;public key&lt;/strong&gt; as an &lt;em&gt;Authentication Key&lt;/em&gt; to the account. Github now has the ability to verify messages that were signed by the corresponding private key of the pair.&lt;/p&gt;&#xA; &lt;h3 id=&#34;3-set-up-openssh-client-config-file&#34;&gt;&#xA;  &lt;a href=&#34;#3-set-up-openssh-client-config-file&#34; class=&#34;header-link&#34;&gt;&#xA;    3. Set up OpenSSH client config file&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;The file &lt;code&gt;~/.ssh/config&lt;/code&gt; allows us to configure &amp;ldquo;Host&amp;rdquo; specifications that we can refer to when using SSH (e.g. when git clone uses the SSH protocol for data transfer). The file looks like this:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Host hostname1&#xA;    SSH_OPTION value&#xA;    SSH_OPTION value&#xA;&#xA;Host hostname2&#xA;    SSH_OPTION value&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In our case, we define the two different github identities that we want to be able to select:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Host github-personal&#xA;    User git&#xA;    PreferredAuthentications publickey&#xA;    Hostname github.com&#xA;    IdentityFile ~/.ssh/github_personal&#xA;&#xA;Host github-work&#xA;    User git&#xA;    PreferredAuthentications publickey&#xA;    Hostname github.com&#xA;    IdentityFile ~/.ssh/github_work&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This defines which keys to use when we connect using SSH via &lt;code&gt;user@host&lt;/code&gt;. So when we the test the config by running &lt;code&gt;ssh -T git@github-personal&lt;/code&gt; SSH will use the SSH key &lt;code&gt;~/.ssh/github_personal&lt;/code&gt; as specified in the file. (Note: We can name the host and user whatever we want.)&lt;/p&gt;&#xA; &lt;h3 id=&#34;4-use-the-right-hostname-when-cloning-repositories&#34;&gt;&#xA;  &lt;a href=&#34;#4-use-the-right-hostname-when-cloning-repositories&#34; class=&#34;header-link&#34;&gt;&#xA;    4. Use the right hostname when cloning repositories&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;Let&amp;rsquo;s say we want to git clone a repository that only our work account has access to, then I can use the git clone command &lt;code&gt;git clone {user}/{host}:{repo_path}.git&lt;/code&gt;:&lt;/p&gt;&#xA;&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;$ git clone git@github-work:/org1/project1.git&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or more explicitely:&lt;/p&gt;&#xA;&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;$ git clone ssh://git@github-work/org1/project.git&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;git/ssh will look into the &lt;code&gt;config&lt;/code&gt; file and select the configured private key for the provided host.&lt;/p&gt;&#xA;&lt;p&gt;GitHub will send a challenge (message) to our machine for authentication. The private key will be used to sign this challenge and our machine then sends the signed message back to the Github server. The Github server will use the stored public key (from step 2) to verify the signature and allow a connection.&lt;/p&gt;&#xA;&lt;p&gt;Note: If in step 1) we decided to encrypt the private key with a passphrase we will be prompted to provide it. Normally, at that point MacOS will offer us to add this passphrase to our &#xA;&lt;a href=&#34;https://support.apple.com/en-gb/guide/keychain-access/welcome/mac&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Keychain&#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>TIL how to re-run only failed tests</title>
      <link>/til/2025/11/pytest-rerun-failed/</link>
      <pubDate>Fri, 21 Nov 2025 13:00:00 +0000</pubDate>
      
      <guid>/til/2025/11/pytest-rerun-failed/</guid>
    <description>&lt;p&gt;This is a super small thing I stumbled over.&#xA;When I implement a new feature, there is inevitably a step where I go through the failing pytest tests and fix or clarify them.&lt;/p&gt;&#xA;&lt;p&gt;Unless I use an IDE, my work loop is like this:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Make code change&lt;/li&gt;&#xA;&lt;li&gt;Run &lt;code&gt;python -m pytest&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Check which tests are failing.&lt;/li&gt;&#xA;&lt;li&gt;Go back to 1.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Now, 2. runs all tests which can take quite some time. There is always the option to run a specific test only, but multiple failing tests can be scattered across different files.&lt;/p&gt;&#xA;&lt;p&gt;So instead, what you can do is to only run the tests that failed at your last test run. Simply use:&lt;/p&gt;&#xA;&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 pytest --last-failed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once you have fixed those tests, it&amp;rsquo;s worth running all tests one more time to check that nothing else was broken by the new changes.&lt;/p&gt;&#xA;&lt;p&gt;Another option is to use the test view of your IDE, if you have access to one in that environment.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>TIL how to investigate missing data easily with DuckDB</title>
      <link>/til/2025/05/duckdb-glob_utility_function/</link>
      <pubDate>Fri, 16 May 2025 14:00:00 +0000</pubDate>
      
      <guid>/til/2025/05/duckdb-glob_utility_function/</guid>
    <description>&lt;p&gt;In data engineering pipelines we commonly store output data in S3 buckets at various stages.&#xA;In this particular case we stored the input data received from customers as csv files in the S3 bucket &lt;code&gt;s3://customer-ingested/customerA.csv&lt;/code&gt; and after some transformations we stored the transformed data as csv files in another S3 bucket &lt;code&gt;s3://customer-transformed/customerA.csv&lt;/code&gt;.&lt;/p&gt;&#xA; &lt;h3 id=&#34;problem&#34;&gt;&#xA;  &lt;a href=&#34;#problem&#34; class=&#34;header-link&#34;&gt;&#xA;    Problem&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;For some of the customers the csv file was missing in the first bucket &lt;code&gt;customer-ingested&lt;/code&gt; while we were sure that all customers had a file in &lt;code&gt;customer-transformed&lt;/code&gt;. However, there was a legit reason why the file could be missing which was that in the application the customer had a state of &lt;code&gt;is_deactivated = True&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The goal of this investigation was to find all the active customers for which we were missing data in the bucket &lt;code&gt;customer-ingested&lt;/code&gt;.&lt;/p&gt;&#xA; &lt;h3 id=&#34;solution&#34;&gt;&#xA;  &lt;a href=&#34;#solution&#34; class=&#34;header-link&#34;&gt;&#xA;    Solution&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;The nice thing about DuckDB in this scenario is that I can combine filesystem data with information from an application table and work in (familiar) SQL land.&lt;/p&gt;&#xA;&lt;p&gt;Here is the query:&lt;/p&gt;&#xA;&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;transformed&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;&#x9;&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;regexp_extract&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;file&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;/([^/]+)\.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;mi&#34;&gt;1&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;filenames_transformed&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;glob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://customer-transformed/*.csv&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;&#x9;&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;ingested&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;&#x9;&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;regexp_extract&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;file&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;/([^/]+)\.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;mi&#34;&gt;1&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;filenames_ingested&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;glob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://customer-ingested/*.csv&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;&#x9;&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;customer_status&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;&#x9;&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;customer_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;n&#34;&gt;is_deactivated&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://application_table_snapshot/customers.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;&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;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;transformed&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;left&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ingested&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;transformed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filenames_transformed&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;ingested&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filenames_ingested&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;left&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_status&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;cs&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;transformed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filenames_transformed&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;cs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;customer_name&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;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_deactivated&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;False&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;and&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filenames_ingested&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;is&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;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;┌───────────────────────┬────────────────────┬────────────────────┬────────────────┐&#xA;│ filenames_transformed │ filenames_ingested │   customer_name    │ is_deactivated │&#xA;│        varchar        │      varchar       │      varchar       │    varchar     │&#xA;├───────────────────────┼────────────────────┼────────────────────┼────────────────┤&#xA;│ customerT             │ NULL               │ customerT          │ False          │&#xA;│ customerW             │ NULL               │ customerW          │ False          │&#xA;│ customerZ             │ NULL               │ customerZ          │ False          │&#xA;└───────────────────────┴────────────────────┴────────────────────┴────────────────┘&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the CTE, I am creating a table &lt;code&gt;transformed&lt;/code&gt; with all the filenames in the S3 bucket &lt;code&gt;customer-transformed&lt;/code&gt;. I am using DuckDB&amp;rsquo;s utility function &lt;code&gt;glob(search_path)&lt;/code&gt; to retrieve the filenames. I do the same for the bucket &lt;code&gt;customer-ingested&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;To get the customer status I read from a recent replication snapshot of the application database to get &lt;code&gt;customer_status&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Finally, I join the three expressions to identify missing files (missing values) in the column &lt;code&gt;filenames_ingested&lt;/code&gt; for active customers.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>TIL that DuckDB now supports Avro files</title>
      <link>/til/2025/03/duckdb-avro-support/</link>
      <pubDate>Wed, 12 Mar 2025 16:00:00 +0000</pubDate>
      
      <guid>/til/2025/03/duckdb-avro-support/</guid>
    <description>&lt;p&gt;In the data engineering pipelines of my current company we use two main file formats:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Parquet files for analytical workloads (columnar-storage)&lt;/li&gt;&#xA;&lt;li&gt;Avro files for transactional / event-based messages (row-storage)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In &#xA;&lt;a href=&#34;./posts/duckdb-for-data-scientists/&#34; &#xA;&gt;Querying remote S3 files&#xA;&lt;/a&gt; I wrote about how I use DuckDB to query parquet files stored in S3. Recently, I noticed that DuckDB &#xA;&lt;a href=&#34;https://duckdb.org/2024/12/09/duckdb-avro-extension.html&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;started supporting&#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; reading of &#xA;&lt;a href=&#34;https://avro.apache.org/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Avro&#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; files in the same way.&lt;/p&gt;&#xA; &lt;h3 id=&#34;install-extension&#34;&gt;&#xA;  &lt;a href=&#34;#install-extension&#34; class=&#34;header-link&#34;&gt;&#xA;    Install extension&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;To install the extension open DuckDB and run:&lt;/p&gt;&#xA;&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;avro&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;community&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;avro&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;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;read-local-files&#34;&gt;&#xA;  &lt;a href=&#34;#read-local-files&#34; class=&#34;header-link&#34;&gt;&#xA;    Read local files&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;Local files can be queried with the &lt;code&gt;read_avro&lt;/code&gt; function:&lt;/p&gt;&#xA;&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;read_avro&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;my_dataset.avro&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;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;read-files-stored-in-s3&#34;&gt;&#xA;  &lt;a href=&#34;#read-files-stored-in-s3&#34; class=&#34;header-link&#34;&gt;&#xA;    Read files stored in S3&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;Remote files can be queried by providing the S3 URI (after &#xA;&lt;a href=&#34;./posts/duckdb-for-data-scientists/#authentication-with-aws&#34; &#xA;&gt;logging into the AWS account&#xA;&lt;/a&gt;):&lt;/p&gt;&#xA;&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;read_avro&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://my_bucket/my_remote_dataset.avro&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A few limitations of the extension are listed &#xA;&lt;a href=&#34;https://duckdb.org/2024/12/09/duckdb-avro-extension.html#limitations--next-steps&#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>/posts/duckdb-dbt-superset/</link>
      <pubDate>Sun, 09 Mar 2025 15:00:00 +0000</pubDate>
      
      <guid>/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: &#xA;&lt;a href=&#34;./posts/duckdb-for-data-scientists/&#34; &#xA;&gt;Querying remote parquet files&#xA;&lt;/a&gt; and &#xA;&lt;a href=&#34;./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;Figure1 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;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 visualization problem to demonstrate the setup. My goal is to load the race time dataset that I used in &#xA;&lt;a href=&#34;./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 visualize the data.&lt;/p&gt;&#xA; &lt;h2 id=&#34;loading-the-raw-data-into-duckdb&#34;&gt;&#xA;  &lt;a href=&#34;#loading-the-raw-data-into-duckdb&#34; class=&#34;header-link&#34;&gt;&#xA;    Loading the raw data into DuckDB&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then create a persistent database (a file on my machine):&lt;/p&gt;&#xA;&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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To verify that everything works, I run:&lt;/p&gt;&#xA;&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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h2 id=&#34;setting-up-dbt-for-data-transformations&#34;&gt;&#xA;  &lt;a href=&#34;#setting-up-dbt-for-data-transformations&#34; class=&#34;header-link&#34;&gt;&#xA;    Setting up dbt for data transformations&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I initialize the dbt project &lt;code&gt;local_warehouse&lt;/code&gt; with&lt;/p&gt;&#xA;&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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;highlight&#34; title=&#34;profiles.yml&#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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;dbt-models&#34;&gt;&#xA;  &lt;a href=&#34;#dbt-models&#34; class=&#34;header-link&#34;&gt;&#xA;    dbt models&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This tells dbt how to materialize the dbt models in DuckDB. So let&amp;rsquo;s run dbt to build the models:&lt;/p&gt;&#xA;&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;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;check-tables-were-created&#34;&gt;&#xA;  &lt;a href=&#34;#check-tables-were-created&#34; class=&#34;header-link&#34;&gt;&#xA;    Check tables were created&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;followed by:&lt;/p&gt;&#xA;&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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which should now show:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;database.main_staging.stg_vatternrundan&#xA;database.main_refined.average_speed_by_country&#xA;&lt;/code&gt;&lt;/pre&gt; &lt;h2 id=&#34;superset-for-data-analytics-dashboards&#34;&gt;&#xA;  &lt;a href=&#34;#superset-for-data-analytics-dashboards&#34; class=&#34;header-link&#34;&gt;&#xA;    Superset for data analytics dashboards&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;After modelling my data, I want to create a dashboard and visualize 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;&gt;&#xA;  &lt;a href=&#34;#install-superset-with-duckdb-support&#34; class=&#34;header-link&#34;&gt;&#xA;    Install Superset with DuckDB support&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;I follow the &#xA;&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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then build the container with&lt;/p&gt;&#xA;&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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and start Superset with&lt;/p&gt;&#xA;&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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, I can access Superset with my browser under &lt;code&gt;http://localhost:8088&lt;/code&gt; and login 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;&gt;&#xA;  &lt;a href=&#34;#configure-superset&#34; class=&#34;header-link&#34;&gt;&#xA;    Configure Superset&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;duckdb:////app/duckdb/database.duckdb?access_mode=READ_ONLY&#xA;&lt;/code&gt;&lt;/pre&gt;&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;&gt;&#xA;  &lt;a href=&#34;#add-datasets-in-superset&#34; class=&#34;header-link&#34;&gt;&#xA;    Add datasets in Superset&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;&gt;&#xA;  &lt;a href=&#34;#create-dashboard-in-superset&#34; class=&#34;header-link&#34;&gt;&#xA;    Create dashboard in Superset&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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;&gt;&#xA;  &lt;a href=&#34;#conclusion&#34; class=&#34;header-link&#34;&gt;&#xA;    Conclusion&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 visualizations.&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;&gt;&#xA;  &lt;a href=&#34;#troubleshooting&#34; class=&#34;header-link&#34;&gt;&#xA;    Troubleshooting&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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>/posts/poor-charlies-almanack-notes/</link>
      <pubDate>Fri, 21 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>/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;&gt;&#xA;  &lt;a href=&#34;#advocating-interdisciplinary-collaboration-between-university-departments&#34; class=&#34;header-link&#34;&gt;&#xA;    Advocating interdisciplinary collaboration between university departments&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 science should try to incorporate findings / models from the hard sciences (physics, chemistry, etc.) and attribute properly.&lt;/p&gt;&#xA; &lt;h2 id=&#34;fraud-and-advice-for-endowment-funds&#34;&gt;&#xA;  &lt;a href=&#34;#fraud-and-advice-for-endowment-funds&#34; class=&#34;header-link&#34;&gt;&#xA;    Fraud and advice for endowment funds&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 criticizes the trend of university endowment funds to employ layers of analysts and consultants to use fund 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 criticizes 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;&gt;&#xA;  &lt;a href=&#34;#inverted-advice-for-graduates&#34; class=&#34;header-link&#34;&gt;&#xA;    (Inverted) Advice for Graduates&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 other&amp;rsquo;s 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;&gt;&#xA;  &lt;a href=&#34;#mental-checklist-to-analyse-problems&#34; class=&#34;header-link&#34;&gt;&#xA;    Mental checklist to analyse problems&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 &#xA;&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: &#xA;&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 to 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 &#xA;&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;, &#xA;&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/Jealously 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 stronger 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 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 fades. 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 to learn 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: &#xA;&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 and follow the experts.&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;&gt;&#xA;  &lt;a href=&#34;#conclusion&#34; class=&#34;header-link&#34;&gt;&#xA;    Conclusion&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 &#xA;&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 &#xA;&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 criticizes 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>TIL how to fix a broken Joplin sync</title>
      <link>/til/broken-joplin-sync/</link>
      <pubDate>Mon, 17 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>/til/broken-joplin-sync/</guid>
    <description>&lt;p&gt;I use &#xA;&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; for all my note-taking as it&amp;rsquo;s open-source, markdown-based, and has decent Desktop and Android apps. I use note encryption and sync my notes via WebDAV with my remote Nextcloud instance.&lt;/p&gt;&#xA; &lt;h3 id=&#34;problem&#34;&gt;&#xA;  &lt;a href=&#34;#problem&#34; class=&#34;header-link&#34;&gt;&#xA;    Problem&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;After not syncing my notes for several weeks, I encountered a couple of errors both on my Desktop app and on my Android app. I don&amp;rsquo;t have access to the error message anymore, but the errors referred to files and file IDs that caused inconsistencies on the remote server, e.g. broken references:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;f1231gdffgasd1asd2.md TypeError: Cannot read property &amp;#39;type_ of null.&#xA;&lt;/code&gt;&lt;/pre&gt; &lt;h3 id=&#34;solution&#34;&gt;&#xA;  &lt;a href=&#34;#solution&#34; class=&#34;header-link&#34;&gt;&#xA;    Solution&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;To solve the issue, I had to delete the offending file on the remote server. However, to not lose it, it&amp;rsquo;s best to make a local copy of the file&amp;rsquo;s content if it is present on one of your local devices.&lt;/p&gt;&#xA;&lt;p&gt;First, I had to determine which file caused the issue, which is a bit harder here as filenames are encrypted. The easiest way to identify the note from the filename is to paste a local markdown reference into a new Joplin note like this:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[Note I am looking for](:/f1231gdffgasd1asd2)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and then click the link in the rendered note. This took me to the offending note.&lt;/p&gt;&#xA;&lt;p&gt;Second, copy the content into a new note.&lt;/p&gt;&#xA;&lt;p&gt;Third, I had to delete the file on the remote. I connected on my Mac to the remote WebDAV server via Finder. In Finder, Click on &lt;code&gt;Go&lt;/code&gt; -&amp;gt; &lt;code&gt;Connect to Server&lt;/code&gt; -&amp;gt; Add address: &lt;code&gt;https://yourserveraddress.org/remote.php/webdav/joplin&lt;/code&gt; (look up the link in your Joplin settings), and authenticated with my Nextcloud credentials. Then I was able to search for the file &lt;code&gt;f1231gdffgasd1asd2&lt;/code&gt; and delete it.&lt;/p&gt;&#xA;&lt;p&gt;The sync now succeeds.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>TIL how to debug a broken nextcloud login (again)</title>
      <link>/til/nextcloud-login-debugging-2/</link>
      <pubDate>Sun, 16 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>/til/nextcloud-login-debugging-2/</guid>
    <description>&lt;p&gt;The symptoms of this problem were the same as the ones I described in &#xA;&lt;a href=&#34;./til/nextcloud-login-debugging/&#34; &#xA;&gt;TIL how to debug a broken nextcloud login&#xA;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;!-- /til/nextcloud-login-debugging/) --&gt;&#xA; &lt;h3 id=&#34;problem&#34;&gt;&#xA;  &lt;a href=&#34;#problem&#34; class=&#34;header-link&#34;&gt;&#xA;    Problem&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;Phone and Mac apps stopped syncing data with the Nextcloud instance. In my browser I could access the login page, but after entering the details I was being sent back to the same login page without any error message.&lt;/p&gt;&#xA; &lt;h3 id=&#34;investigation&#34;&gt;&#xA;  &lt;a href=&#34;#investigation&#34; class=&#34;header-link&#34;&gt;&#xA;    Investigation&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;Last time the issue was caused by excessive logging. However, I reduced the &lt;code&gt;loglevel&lt;/code&gt; in the nextcloud config, so this was not the issue here. I am no expert in web admin, PHP, or nextcloud, so I used Claude 3.5 to &lt;em&gt;pair&lt;/em&gt; on debugging:&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;        I am self-hosting a nextcloud instance on a Hetzner VPC. I currently have the following problem. I can&amp;rsquo;t log in to nextcloud via my account. The screen just reloads and shows me the login page again. It is not a login detail issue. They are correct. Moreover, other nextcloud related syncs (files, calendar) stopped working. Walk me through how I can debug this issue and get nextcloud up and running again.      &lt;/div&gt; &#xA;&lt;/div&gt;&#xA;&lt;p&gt;I can&amp;rsquo;t say that the suggestions worked right away, but they put me on the right path and helped me with some useful debugging commands.&lt;/p&gt;&#xA;&lt;p&gt;The command&lt;/p&gt;&#xA;&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;df -h&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;showed me that I didn&amp;rsquo;t have &lt;em&gt;any&lt;/em&gt; free space. While the command&lt;/p&gt;&#xA;&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;du -sh /var/www/nextcloud/data/*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;indicated that in nextcloud a lot of space was occupied by old file versions and deleted files from the nextcloud file sync.&lt;/p&gt;&#xA; &lt;h3 id=&#34;solution&#34;&gt;&#xA;  &lt;a href=&#34;#solution&#34; class=&#34;header-link&#34;&gt;&#xA;    Solution&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;You can use the nextcloud console &lt;code&gt;occ&lt;/code&gt; (ownCloud Console) tool to run maintenance tasks on the nextcloud instance.&lt;/p&gt;&#xA;&lt;p&gt;The command&lt;/p&gt;&#xA;&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;sudo -u www-data php /var/www/nextcloud/occ list&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;lists all available commands.&lt;/p&gt;&#xA;&lt;p&gt;A couple of clean up commands to remove old file versions and files in the trashbin worked for me:&lt;/p&gt;&#xA;&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;c1&#34;&gt;# Check Nextcloud trashbin size&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo -u www-data php /var/www/nextcloud/occ trashbin:cleanup --all-users&#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;# Clean up file versions&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo -u www-data php /var/www/nextcloud/occ versions:cleanup&#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;# Clear Nextcloud cache:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo -u www-data php /var/www/nextcloud/occ cache:clear&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This freed up enough space for nextcloud to work again.&lt;/p&gt;&#xA;&lt;p&gt;Unfortunately, the &lt;code&gt;occ&lt;/code&gt; commands didn&amp;rsquo;t work right away because there was apparently not enough space to run any of them. Each one returned the same error message:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fwrite(): write of 4963 bytes failed with errno=28 No space left on device &#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So I first had to free up a few hundred megabytes:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Clear local repository of retrieved package files:&lt;/p&gt;&#xA;&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;sudo apt-get clean&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Remove old log files:&lt;/p&gt;&#xA;&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;sudo find /var/log -type f -name &lt;span class=&#34;s2&#34;&gt;&amp;#34;*.gz&amp;#34;&lt;/span&gt; -delete&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo find /var/log -type f -name &lt;span class=&#34;s2&#34;&gt;&amp;#34;*.1&amp;#34;&lt;/span&gt; -delete&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo truncate -s &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; /var/log/*.log&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Remove temporary files:&lt;/p&gt;&#xA;&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;sudo rm -rf /tmp/*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This cleared enough space to run the &lt;code&gt;occ&lt;/code&gt; commands.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>How related posts are computed</title>
      <link>/posts/how-recommendations-work/</link>
      <pubDate>Sun, 09 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>/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;Summarize every post and TIL using local Llama 3.1 (&lt;code&gt;llama3.1:8b-instruct-q5_0&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 ChromaDB&amp;rsquo;s default embedding model &lt;code&gt;all-MiniLM-L6-v2&lt;/code&gt; and store the embedding and metadata about the post in a persistent &#xA;&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 &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#noteworthy&#34; class=&#34;header-link&#34;&gt;&#xA;    Noteworthy&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Maybe not surprising, but Llama 3.1 8b performed much better than Llama 3.2 3b. The latter would hallucinate quite a few parts of the summary.&lt;/li&gt;&#xA;&lt;li&gt;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 which I had to work 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 token. There is the option to use another embedding model that has a higher maximum sequence length. A good embedding model leaderboard to help make a choice is available &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#example&#34; class=&#34;header-link&#34;&gt;&#xA;    Example&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;For the blog post &#xA;&lt;a href=&#34;./posts/4000-weeks/&#34; &#xA;&gt;Book notes: Four Thousand Weeks by Oliver Burkeman&#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-llama&#34;&gt;&#xA;    &lt;summary class=&#34;llmbox-title&#34;&gt;&#xA;        Model: llama3.1:8b-instruct-q5_0 - response &#xA;    &lt;/summary&gt;&#xA;    &lt;div class=&#34;llmbox-content&#34;&gt;&#xA;&lt;p&gt;&amp;ldquo;The blog post discusses the book &amp;ldquo;Four Thousand Weeks&amp;rdquo; by Oliver Burkeman, which explores the concept of time and how to make the most of our limited lives. The author argues that modern society&amp;rsquo;s focus on productivity and efficiency is flawed, as it leads to a never-ending cycle of work and stress. Instead, he advocates for embracing our finitude and focusing on the present moment. Key concepts include &amp;ldquo;atelic activities&amp;rdquo; (enjoying leisure time for its own sake), &amp;ldquo;radical incrementalism&amp;rdquo; (making small progress towards goals), and &amp;ldquo;cosmic insignificance therapy&amp;rdquo; (putting life&amp;rsquo;s problems into perspective by considering the vastness of the universe). The author also suggests tools for embracing finitude, such as keeping a done list to focus on completed tasks. Overall, the book encourages readers to reevaluate their priorities and find meaning in the present moment.&amp;rdquo;&#xA;&lt;/div&gt;&lt;/p&gt;&#xA;&lt;/details&gt;&#xA; &lt;h3 id=&#34;embeddings&#34;&gt;&#xA;  &lt;a href=&#34;#embeddings&#34; class=&#34;header-link&#34;&gt;&#xA;    Embeddings&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;I can visualize the embeddings in two dimensions using &#xA;&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;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;&gt;&#xA;  &lt;a href=&#34;#code&#34; class=&#34;header-link&#34;&gt;&#xA;    Code&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;I am using &#xA;&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;</description>
    </item>
    
    <item>
      <title>Book notes: How Big Things Get Done by Bent Flyvbjerg and Dan Gardner</title>
      <link>/posts/how-big-things-get-done/</link>
      <pubDate>Sun, 02 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>/posts/how-big-things-get-done/</guid>
    <description>&lt;p&gt;&#xA;&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 realized 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 &#xA;&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 realized. Examples are easy to find, e.g. the delayed &#xA;&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 &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#planning-is-cheap-building-is-expensive&#34; class=&#34;header-link&#34;&gt;&#xA;    Planning is cheap, building is expensive&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 scrutinize 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;&gt;&#xA;  &lt;a href=&#34;#understand-the-why&#34; class=&#34;header-link&#34;&gt;&#xA;    Understand the why&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;&gt;&#xA;  &lt;a href=&#34;#reduce-uncertainty-via-experimentation&#34; class=&#34;header-link&#34;&gt;&#xA;    Reduce uncertainty via experimentation&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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 scrutinized 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;&gt;&#xA;  &lt;a href=&#34;#experience-in-people-and-technology&#34; class=&#34;header-link&#34;&gt;&#xA;    Experience in people and technology&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;To maximize the chance of a successful project we should maximize &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 McKinkley&amp;rsquo;s advice to &#xA;&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 to only use 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;&gt;&#xA;  &lt;a href=&#34;#reference-class-forecasting&#34; class=&#34;header-link&#34;&gt;&#xA;    Reference-class forecasting&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;After the project is planned we need to forecast the project duration and its cost. Unfortunately, planners often forecast too optimistic. Instead of deriving it from the project alone, the authors suggest to use &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 can not 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;&gt;&#xA;  &lt;a href=&#34;#after-the-planning-is-done-build-quickly&#34; class=&#34;header-link&#34;&gt;&#xA;    After the planning is done, build quickly&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;The project duration is in itself is 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;&gt;&#xA;  &lt;a href=&#34;#build-with-an-experienced-team&#34; class=&#34;header-link&#34;&gt;&#xA;    Build with an experienced team&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;&gt;&#xA;  &lt;a href=&#34;#whats-our-lego&#34; class=&#34;header-link&#34;&gt;&#xA;    What&amp;rsquo;s our Lego?&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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, standardized 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;&gt;&#xA;  &lt;a href=&#34;#additional-thoughts-about-the-book&#34; class=&#34;header-link&#34;&gt;&#xA;    Additional thoughts about the book&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt; &lt;h3 id=&#34;incentives-and-identity&#34;&gt;&#xA;  &lt;a href=&#34;#incentives-and-identity&#34; class=&#34;header-link&#34;&gt;&#xA;    Incentives and identity&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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 relationship. Workers were treated well, their feedback was actively encouraged, and they felt like they are 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;&gt;&#xA;  &lt;a href=&#34;#cost-overruns-by-project-type&#34; class=&#34;header-link&#34;&gt;&#xA;    Cost overruns by project type&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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 fat-ness of the distribution (% projects in the upper tail), and the (base rate) cost overrun for projects in the upper 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. Organizing 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 type.&lt;/p&gt;&#xA; &lt;h3 id=&#34;learnings-for-software-projects&#34;&gt;&#xA;  &lt;a href=&#34;#learnings-for-software-projects&#34; class=&#34;header-link&#34;&gt;&#xA;    Learnings for software projects&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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>/posts/prompt-heuristics/</link>
      <pubDate>Fri, 11 Oct 2024 14:56:00 +0000</pubDate>
      
      <guid>/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 &#xA;&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 go 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;&gt;&#xA;  &lt;a href=&#34;#prompt-specificity&#34; class=&#34;header-link&#34;&gt;&#xA;    Prompt specificity&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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. A good advice given in &#xA;&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 part of 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;pre tabindex=&#34;0&#34;&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 knowledgble about the city, its roads, and its sights. &#xA;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#xA;&lt;li&gt;If the model is used inside a product, tell it about it:&#xA;&lt;pre tabindex=&#34;0&#34;&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.&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA; &lt;h3 id=&#34;order-of-prompt-components&#34;&gt;&#xA;  &lt;a href=&#34;#order-of-prompt-components&#34; class=&#34;header-link&#34;&gt;&#xA;    Order of prompt components&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;&gt;&#xA;  &lt;a href=&#34;#use-xml-tags-for-prompt-components&#34; class=&#34;header-link&#34;&gt;&#xA;    Use XML tags for prompt components&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;Use XML tags to separate different components of a prompt.&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&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; &#xA;&lt;/code&gt;&lt;/pre&gt; &lt;h3 id=&#34;using-examples-few-shot-prompting&#34;&gt;&#xA;  &lt;a href=&#34;#using-examples-few-shot-prompting&#34; class=&#34;header-link&#34;&gt;&#xA;    Using examples (few shot prompting)&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;&gt;&#xA;  &lt;a href=&#34;#instructions&#34; class=&#34;header-link&#34;&gt;&#xA;    Instructions&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;pre tabindex=&#34;0&#34;&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.&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA; &lt;h3 id=&#34;grammar-and-style&#34;&gt;&#xA;  &lt;a href=&#34;#grammar-and-style&#34; class=&#34;header-link&#34;&gt;&#xA;    Grammar and style&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;&gt;&#xA;  &lt;a href=&#34;#parse-able-output&#34; class=&#34;header-link&#34;&gt;&#xA;    Parse-able output&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;&gt;&#xA;  &lt;a href=&#34;#other-tricks&#34; class=&#34;header-link&#34;&gt;&#xA;    Other tricks&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;pre tabindex=&#34;0&#34;&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.&#xA;&lt;/code&gt;&lt;/pre&gt;&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;pre tabindex=&#34;0&#34;&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;.&#xA;&lt;/code&gt;&lt;/pre&gt;&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;&gt;&#xA;  &lt;a href=&#34;#iterative-prompt-design&#34; class=&#34;header-link&#34;&gt;&#xA;    Iterative prompt design&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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>TIL (from Claude) how to create separate RSS feeds for my hugo blog </title>
      <link>/til/hugo-with-separate-rss-feeds/</link>
      <pubDate>Thu, 03 Oct 2024 00:00:00 +0000</pubDate>
      
      <guid>/til/hugo-with-separate-rss-feeds/</guid>
    <description>&lt;p&gt;I really like the idea of providing different content types of my blog in separate RSS feeds. For example a blog could have:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;essays&lt;/li&gt;&#xA;&lt;li&gt;today-I-learned posts&lt;/li&gt;&#xA;&lt;li&gt;link-list or bloglink posts&lt;/li&gt;&#xA;&lt;li&gt;short social media style posts&lt;/li&gt;&#xA;&lt;li&gt;etc.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Providing different RSS feeds for them allows my readers to subscribe to all or a subset of these, depending on their interest. I am using hugo, as the static site generator for this website. Setting up these different feeds for a framework that I am only partially familar with is a great use-case to work with an LLM.&lt;/p&gt;&#xA;&lt;p&gt;I knew that I would need to:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Distinguish different content types with a flag&lt;/li&gt;&#xA;&lt;li&gt;Specify different RSS templates that filter on these flags&lt;/li&gt;&#xA;&lt;li&gt;Tell hugo to generate separate xml files for each content type and use the right templates.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;I just didn&amp;rsquo;t know how to piece these parts together. I first tried googling the answer and read the typical mix of&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;stackoverflow posts that were not solving the exact same problem&lt;/li&gt;&#xA;&lt;li&gt;hugo forum discussions that did not have a clear solution or where the solution wasn&amp;rsquo;t transferable to my unique setup.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I think with those first pointers, spending some time on the hugo documentation, and trial-and-erroring, I could have worked out how to do it.&#xA;I think that these shallow but unknown problems are the ideal use case for an LLM.&lt;/p&gt;&#xA;&lt;p&gt;I think of using LLMs as an interface for search + context, where I don&amp;rsquo;t have to take the laborious work of pre-filtering and connecting the sources. Instead, it helps me get a quick overview and a potential draft of a solution. I can then go deeper and understand the problem better by asking about parts of the solution that I don&amp;rsquo;t understand. I can then mix this with more googling and get to a solution.&lt;/p&gt;&#xA; &lt;h2 id=&#34;my-goal&#34;&gt;&#xA;  &lt;a href=&#34;#my-goal&#34; class=&#34;header-link&#34;&gt;&#xA;    My Goal:&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;I have a hugo blog with the following folder structure:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/content/posts/post1.md&#xA;/content/posts/post2.md&#xA;/content/posts/_index.md&#xA;/content/til/_index.md&#xA;/content/til/til1.md&#xA;/content/til/til2.md&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Markdown pages written in the posts subfolder have type: post in the frontmatter and pages written in the til subfolder have type: til in the submatter.&lt;/p&gt;&#xA;&lt;p&gt;Explain to me step by step how I can create three separate rss feeds on my website.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Only showing content coming from the til subfolder on til.xml&lt;/li&gt;&#xA;&lt;li&gt;Only showing content coming from the post subfolder posts.xml&lt;/li&gt;&#xA;&lt;li&gt;One showing everything on index.xml&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;      &lt;/div&gt; &#xA;&lt;/div&gt;&#xA; &lt;h2 id=&#34;solution&#34;&gt;&#xA;  &lt;a href=&#34;#solution&#34; class=&#34;header-link&#34;&gt;&#xA;    Solution&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;details class=&#34;llmbox llm-anthropic&#34;&gt;&#xA;    &lt;summary class=&#34;llmbox-title&#34;&gt;&#xA;        Model: claude-3-5-sonnet-20241022 - response &#xA;    &lt;/summary&gt;&#xA;    &lt;div class=&#34;llmbox-content&#34;&gt;&#xA;&lt;p&gt;I&amp;rsquo;d be happy to explain how you can create three separate RSS feeds for your Hugo blog with the structure you&amp;rsquo;ve described. Let&amp;rsquo;s go through this step-by-step:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Create RSS template files:&#xA;First, you&amp;rsquo;ll need to create three separate RSS template files in your Hugo project&amp;rsquo;s layouts folder.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Now, let me explain each step in more detail:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We create three separate RSS template files in the &lt;code&gt;layouts/_default/&lt;/code&gt; directory. Each file corresponds to one of the RSS feeds you want to create.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;In each RSS template, we use Hugo&amp;rsquo;s templating language to generate the RSS feed. The main difference between the templates is in the range statement:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For &lt;code&gt;til.xml&lt;/code&gt;, we use &lt;code&gt;{{ range where .Site.RegularPages &amp;quot;Type&amp;quot; &amp;quot;til&amp;quot; }}&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;For &lt;code&gt;posts.xml&lt;/code&gt;, we use &lt;code&gt;{{ range where .Site.RegularPages &amp;quot;Type&amp;quot; &amp;quot;post&amp;quot; }}&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;For &lt;code&gt;index.xml&lt;/code&gt;, we use &lt;code&gt;{{ range .Site.RegularPages }}&lt;/code&gt; to include all content&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We update the Hugo configuration file to define new output formats for TIL and Posts, and to include these new formats in the home page outputs.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;We add links to the new RSS feeds in the site&amp;rsquo;s HTML, typically in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section or footer.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Finally, we build the site to generate the new RSS feed files.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;After following these steps, your Hugo site will generate three separate RSS feeds:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;til.xml&lt;/code&gt; will only include content from the &lt;code&gt;til&lt;/code&gt; subfolder&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;posts.xml&lt;/code&gt; will only include content from the &lt;code&gt;posts&lt;/code&gt; subfolder&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;index.xml&lt;/code&gt; will include all content&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Would you like me to explain any part of this process in more detail?&#xA;&lt;/div&gt;&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;&lt;p&gt;I followed these steps, except for using my already existing xml template for &lt;code&gt;til.xml&lt;/code&gt;, &lt;code&gt;posts.xml&lt;/code&gt;, &lt;code&gt;index.xml&lt;/code&gt;. I already read in some hugo discussions that I need to add &lt;code&gt;[outputs]&lt;/code&gt; and &lt;code&gt;[outputFormats]&lt;/code&gt; to my hugo &lt;code&gt;config.toml&lt;/code&gt; file. However, I didn&amp;rsquo;t really understand the difference between home, page, section and what exactly &lt;code&gt;home = [&amp;quot;HTML&amp;quot;, &amp;quot;RSS&amp;quot;, &amp;quot;JSON&amp;quot;, &amp;quot;TIL&amp;quot;, &amp;quot;POSTS&amp;quot;]&lt;/code&gt; does.&#xA;So I asked for clarification:&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;        Can you explain to me the config [outputs] and its purpose as well as [outputFormats]?      &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-3-5-sonnet-20241022 - response &#xA;    &lt;/summary&gt;&#xA;    &lt;div class=&#34;llmbox-content&#34;&gt;&#xA;&lt;p&gt;Certainly! I&amp;rsquo;d be happy to explain the &lt;code&gt;[outputs]&lt;/code&gt; and &lt;code&gt;[outputFormats]&lt;/code&gt; configurations in Hugo and their purposes.&lt;/p&gt;&#xA;&lt;p&gt;Now, let me provide a more detailed explanation of these configurations:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;[outputs]&lt;/code&gt;: This configuration section determines what types of files Hugo will generate for different types of pages on your site. In our case, we&amp;rsquo;re telling Hugo to generate additional output formats for the home page. The line &lt;code&gt;home = [&amp;quot;HTML&amp;quot;, &amp;quot;RSS&amp;quot;, &amp;quot;TIL&amp;quot;, &amp;quot;POSTS&amp;quot;]&lt;/code&gt; means:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For the home page, generate the standard HTML and RSS outputs&lt;/li&gt;&#xA;&lt;li&gt;Also generate our custom TIL and POSTS outputs&#xA;This is crucial for creating our multiple RSS feeds, as it instructs Hugo to actually generate these files when building the site.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;&lt;code&gt;[outputFormats]&lt;/code&gt;: This section allows you to define new output formats or modify existing ones. In our case, we&amp;rsquo;re defining two new output formats: TIL and POSTS. For each new format, we specify:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;mediaType&lt;/code&gt;: This tells Hugo what kind of content this is. We&amp;rsquo;re using &amp;ldquo;application/rss+xml&amp;rdquo; because we&amp;rsquo;re creating RSS feeds.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;baseName&lt;/code&gt;: This determines the filename of the output file. For example, &lt;code&gt;baseName = &amp;quot;til&amp;quot;&lt;/code&gt; will result in a file named &lt;code&gt;til.xml&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;By defining these custom output formats, we&amp;rsquo;re giving Hugo the information it needs to generate our specialized RSS feeds.&lt;/p&gt;&#xA;&lt;p&gt;The interaction between these two configuration sections is key:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;[outputFormats]&lt;/code&gt; defines what the TIL and POSTS formats are&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;[outputs]&lt;/code&gt; tells Hugo to actually generate these formats for the home page&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This setup allows you to have fine-grained control over what files Hugo generates and how they&amp;rsquo;re named, which is exactly what we need to create multiple, specialized RSS feeds.&#xA;Is there any part of this you&amp;rsquo;d like me to elaborate on further?&#xA;&lt;/div&gt;&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;&lt;p&gt;This helped but I still didn&amp;rsquo;t really get why I would have to add this to &lt;code&gt;home&lt;/code&gt; and not &lt;code&gt;page&lt;/code&gt; because I thought that I want to generate rss for page-types.&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;        What&amp;rsquo;s the difference between adding TIL and POSTS to home instead of page?      &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-3-5-sonnet-20241022 - response &#xA;    &lt;/summary&gt;&#xA;    &lt;div class=&#34;llmbox-content&#34;&gt;&#xA;&lt;p&gt;That&amp;rsquo;s an excellent question! The difference between adding output formats to &lt;code&gt;home&lt;/code&gt; versus &lt;code&gt;page&lt;/code&gt; in Hugo&amp;rsquo;s configuration is quite significant and affects how and where these outputs are generated. Let me explain:&lt;/p&gt;&#xA;&lt;p&gt;Now, let me elaborate on the key points:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Scope and Purpose:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Adding TIL and POSTS to &lt;code&gt;home&lt;/code&gt; creates site-wide RSS feeds that include all relevant content from across your site. This is ideal for your use case of creating separate feeds for TIL entries and blog posts.&lt;/li&gt;&#xA;&lt;li&gt;If you added these to &lt;code&gt;page&lt;/code&gt;, it would create individual RSS feeds for each content page, which is not what you&amp;rsquo;re aiming for.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Number of Files Generated:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;With &lt;code&gt;home&lt;/code&gt;, you get one &lt;code&gt;til.xml&lt;/code&gt; and one &lt;code&gt;posts.xml&lt;/code&gt; file for your entire site.&lt;/li&gt;&#xA;&lt;li&gt;If you used &lt;code&gt;page&lt;/code&gt;, you&amp;rsquo;d get a &lt;code&gt;til.xml&lt;/code&gt; and &lt;code&gt;posts.xml&lt;/code&gt; for every single page on your site, which would be unnecessary and potentially confusing.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Content Aggregation:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The &lt;code&gt;home&lt;/code&gt; outputs can access and aggregate content from across your entire site, which is perfect for creating comprehensive RSS feeds.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;page&lt;/code&gt; outputs typically only contain information from that specific page.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Location of Generated Files:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;home&lt;/code&gt; outputs are usually placed at the root of your site, making them easy to find and link to (e.g., &lt;code&gt;https://yoursite.com/til.xml&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;page&lt;/code&gt; outputs would be scattered throughout your site structure, mirroring your content organization.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Practical Implementation:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For your RSS feeds, using &lt;code&gt;home&lt;/code&gt; allows you to create the three distinct feeds you want (TIL, posts, and everything) in a clean, organized manner.&lt;/li&gt;&#xA;&lt;li&gt;Using &lt;code&gt;page&lt;/code&gt; for this purpose would be impractical and wouldn&amp;rsquo;t achieve your goal of separate, comprehensive feeds.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;In summary, for your specific need of creating site-wide RSS feeds for different content types, adding TIL and POSTS to the &lt;code&gt;home&lt;/code&gt; outputs is the correct approach. It generates the feeds at the site level, includes all relevant content, and produces a single file for each feed type, which is exactly what you&amp;rsquo;re looking to achieve.&#xA;&lt;/div&gt;&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;&lt;p&gt;I followed the suggested approach and added to my &lt;code&gt;config.toml&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# I want to top-level output html, rss, and my two custom outputs&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;nx&#34;&gt;outputs&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;nx&#34;&gt;home&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;s2&#34;&gt;&amp;#34;html&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;rss&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;til&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;post&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;&#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;c&#34;&gt;# Here I define how to process these custom feeds&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;nx&#34;&gt;outputFormats&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;til&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;nx&#34;&gt;mediaType&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;application/rss+xml&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;nx&#34;&gt;baseName&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;til&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;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;outputFormats&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;post&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;nx&#34;&gt;mediaType&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;application/rss+xml&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;nx&#34;&gt;baseName&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I built the page and hugo would build three different xml files:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;public/index.xml&#xA;public/posts.xml&#xA;public/til.xml&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However, the files all had the same content as if they were built from the same template instead of the individual templates that filter by page type.&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;        This generates the three xml files but they all seem to use the same template file      &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-3-5-sonnet-20241022 - response &#xA;    &lt;/summary&gt;&#xA;    &lt;div class=&#34;llmbox-content&#34;&gt;&#xA;&lt;p&gt;I apologize for the confusion in my previous explanation. You&amp;rsquo;re right to point out that issue. Let&amp;rsquo;s correct this and explain how to properly set up distinct templates for each RSS feed.&lt;/p&gt;&#xA;&lt;p&gt;Now, let me explain the key changes and why they solve the problem:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Template File Naming:&#xA;The crucial change is in how we name and place the template files. Instead of putting them in &lt;code&gt;layouts/_default/&lt;/code&gt;, we&amp;rsquo;re now creating:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;layouts/index.til.xml&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;layouts/index.posts.xml&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;layouts/index.xml&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This naming convention is important because Hugo uses it to match the output formats we defined in the configuration.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Template Content:&#xA;The content of each template remains largely the same, but we&amp;rsquo;ve made sure that each one is filtering for the correct content type:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;index.til.xml&lt;/code&gt; uses &lt;code&gt;{{ range where .Site.RegularPages &amp;quot;Type&amp;quot; &amp;quot;til&amp;quot; }}&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;index.posts.xml&lt;/code&gt; uses &lt;code&gt;{{ range where .Site.RegularPages &amp;quot;Type&amp;quot; &amp;quot;post&amp;quot; }}&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;index.xml&lt;/code&gt; continues to use &lt;code&gt;{{ range .Site.RegularPages }}&lt;/code&gt; for all content&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Configuration:&#xA;The configuration in &lt;code&gt;config.toml&lt;/code&gt; remains the same as before. The &lt;code&gt;[outputFormats]&lt;/code&gt; and &lt;code&gt;[outputs]&lt;/code&gt; sections are correctly set up to generate these files.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;How It Works:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When Hugo sees &lt;code&gt;TIL&lt;/code&gt; in the &lt;code&gt;[outputs]&lt;/code&gt; section, it looks for a template named &lt;code&gt;index.til.xml&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Similarly, for &lt;code&gt;POSTS&lt;/code&gt;, it looks for &lt;code&gt;index.posts.xml&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;The default RSS output uses &lt;code&gt;index.xml&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;This setup ensures that each RSS feed uses its own template, allowing you to customize the content for each feed independently.&lt;/p&gt;&#xA;&lt;p&gt;The reason your previous attempt generated three XML files with the same content was likely because Hugo was falling back to a default RSS template when it couldn&amp;rsquo;t find specific templates for TIL and POSTS.&lt;/p&gt;&#xA;&lt;p&gt;With these changes, you should now have three distinct RSS feeds, each with its appropriate content. Does this explanation help clarify the issue? Would you like me to elaborate on any part of this solution?&#xA;&lt;/div&gt;&lt;/p&gt;&#xA;&lt;/details&gt;&#xA;&lt;p&gt;So I moved the template layout files as suggested to:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;layouts/index.til.xml&#xA;layouts/index.posts.xml&#xA;layouts/index.xml&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and they were correctly selected.&#xA;You can find the correct feeds here:&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;a href=&#34;https://staticnotes.org/index.xml&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;https://staticnotes.org/index.xml&#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;&lt;a href=&#34;https://staticnotes.org/posts.xml&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;https://staticnotes.org/posts.xml&#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;&lt;a href=&#34;https://staticnotes.org/til.xml&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;https://staticnotes.org/til.xml&#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;conclusion&#34;&gt;&#xA;  &lt;a href=&#34;#conclusion&#34; class=&#34;header-link&#34;&gt;&#xA;    Conclusion&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;A common criticism is that LLMs will confidently hallucinate incorrect information. I think this will likely be true for the next couple of years. However, when I use the old-school google + stackoverflow + documentation + online discussion workflow I also might generate an incorrect approach. This can happen because I misunderstand the content or because I can&amp;rsquo;t piece the information from different sources correctly together for my use case.&lt;/p&gt;&#xA;&lt;p&gt;I think viewing an LLM as an interactive interface to search and combine information and context is the right mental model to use them productively.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Processing 112M rows of steam reviews locally with DuckDB</title>
      <link>/posts/duckdb-large-datasets/</link>
      <pubDate>Sat, 28 Sep 2024 13:43:40 +0000</pubDate>
      
      <guid>/posts/duckdb-large-datasets/</guid>
    <description>&lt;p&gt;In &#xA;&lt;a href=&#34;./posts/duckdb-for-data-scientists/&#34; &#xA;&gt;DuckDB use cases for data scientists: Querying remote S3 files&#xA;&lt;/a&gt; I wrote 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 processing 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 &#xA;&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 &#xA;&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 &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#useful-commands-and-settings&#34; class=&#34;header-link&#34;&gt;&#xA;    Useful commands and settings&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;&gt;&#xA;  &lt;a href=&#34;#steam-review-dataset&#34; class=&#34;header-link&#34;&gt;&#xA;    Steam review dataset&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;First, I want to familiarize 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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&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 = &#xA;&lt;/code&gt;&lt;/pre&gt;&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;&gt;&#xA;  &lt;a href=&#34;#processing-the-file-directly&#34; class=&#34;header-link&#34;&gt;&#xA;    Processing the file directly&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 materializing 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;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&#xA;&lt;/code&gt;&lt;/pre&gt;&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 &#xA;&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;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&#xA;&lt;/code&gt;&lt;/pre&gt;&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 &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#working-in-a-jupyter-notebook&#34; class=&#34;header-link&#34;&gt;&#xA;    Working in a Jupyter notebook&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt; &lt;h3 id=&#34;duckdb-python-client&#34;&gt;&#xA;  &lt;a href=&#34;#duckdb-python-client&#34; class=&#34;header-link&#34;&gt;&#xA;    DuckDB Python client&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;polars&#34;&gt;&#xA;  &lt;a href=&#34;#polars&#34; class=&#34;header-link&#34;&gt;&#xA;    Polars&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#conclusion&#34; class=&#34;header-link&#34;&gt;&#xA;    Conclusion&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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>TIL about the QUALIFY statement in SQL</title>
      <link>/til/sql-qualify/</link>
      <pubDate>Mon, 16 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>/til/sql-qualify/</guid>
    <description>&lt;p&gt;Today I came across the &lt;code&gt;QUALIFY&lt;/code&gt; clause which is supported in some SQL dialects.&lt;span class=&#34;sidenote-number&#34;&gt;&lt;small class=&#34;sidenote&#34;&gt; It&amp;rsquo;s not part of the SQL standard but supported by main analytical databases like BigQuery, Snowflake, Oracle, Databricks, DuckDB, etc.&lt;/small&gt;&lt;/span&gt; It&amp;rsquo;s part of &#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Snowflake_Inc.&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;Snowflake&amp;rsquo;s&#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; dialect which is the data warehouse that I use at work.&#xA;The &lt;code&gt;QUALIFY&lt;/code&gt; statement lets me filter the result of a query based on the result of a window function.&lt;/p&gt;&#xA;&lt;p&gt;The order of execution is the following:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-- SELECT &amp;lt;columns&amp;gt;&#xA;--   FROM &amp;lt;table&amp;gt;&#xA;--   [GROUP BY ...]&#xA;--   [HAVING ...]&#xA;--   QUALIFY &amp;lt;window function predicate&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;QUALIFY&lt;/code&gt; is for window functions what &lt;code&gt;HAVING&lt;/code&gt; is for group-by statements. It allows to filter based on the outputs of these operations without having to use a subquery or CTE. Therefore I can write more concise SQL.&lt;/p&gt;&#xA;&lt;p&gt;I often deduplicate data using the &lt;code&gt;row_number()&lt;/code&gt; window function. Sometimes I just want the latest event for a particular user in a dataset.&lt;/p&gt;&#xA;&lt;p&gt;An example would be:&lt;/p&gt;&#xA;&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;-- logs with some user events and timestamps&#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;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;logs_annotated&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;&#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;logs&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;&#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;row_number&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;over&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;partition&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;event_timestamp&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 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;row_number&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;logs&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;&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;logs_annotated&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;row_number&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;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With &lt;code&gt;QUALIFY&lt;/code&gt; I can write one statement instead:&lt;/p&gt;&#xA;&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;logs&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;qualify&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row_number&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;over&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;partition&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;event_timestamp&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 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;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works because the &lt;code&gt;QUALIFY&lt;/code&gt; statement is evaluated after the window function result has been computed and can therefore be used in filtering.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Interest rate expectations</title>
      <link>/posts/interest-rate-expecations/</link>
      <pubDate>Sat, 14 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>/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 glanced 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;&gt;&#xA;  &lt;a href=&#34;#the-federal-funds-rate&#34; class=&#34;header-link&#34;&gt;&#xA;    The Federal Funds Rate&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 depositor&amp;rsquo;s 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 undercapitalized. Banks do that a lot and negotiate an interest rate for this overnight loan. The weighted average of all these deals for 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;&gt;&#xA;  &lt;a href=&#34;#federal-funds-futures&#34; class=&#34;header-link&#34;&gt;&#xA;    Federal Funds Futures&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;We can infer the expectations to 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 &#xA;&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 &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#what-do-the-federal-funds-futures-hold&#34; class=&#34;header-link&#34;&gt;&#xA;    What do the Federal Funds Future(s) hold?&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 &#xA;&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;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;/code&gt;&lt;/pre&gt;&lt;/div&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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 realized 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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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 realized EFFR up until today. If today was 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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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 0.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 realized EFFR will decrease more than 0.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 points change 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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 commitee announces a 25bps rate cut.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;This implies a probability of 53.33% that the commitee announces a 25bps rate cut.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&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 commitee announces a 50bps rate cut.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;This implies a probability of 46.67% that the commitee 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 &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#what-about-europe&#34; class=&#34;header-link&#34;&gt;&#xA;    What about Europe?&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;If you are interested in the expectations for the interest rates set by the Bank of England, you can use &#xA;&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 &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#jupyter-notebook&#34; class=&#34;header-link&#34;&gt;&#xA;    Jupyter Notebook&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;You can find the jupyter notebook for this post &#xA;&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>TIL about just and justfiles</title>
      <link>/til/just-command-runner/</link>
      <pubDate>Fri, 13 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>/til/just-command-runner/</guid>
    <description>&lt;p&gt;&#xA;&lt;a href=&#34;https://github.com/casey/just&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;just&#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 &lt;em&gt;just&lt;/em&gt; a command runner that I recently started using to define aliases for commands in my projects, e.g. build, test, or deploy commands.&lt;/p&gt;&#xA; &lt;h3 id=&#34;installation&#34;&gt;&#xA;  &lt;a href=&#34;#installation&#34; class=&#34;header-link&#34;&gt;&#xA;    Installation&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;just&lt;/code&gt; can be installed via homebrew:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install just&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;example&#34;&gt;&#xA;  &lt;a href=&#34;#example&#34; class=&#34;header-link&#34;&gt;&#xA;    Example&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;I want to create alias commands for my &#xA;&lt;a href=&#34;https://www.getdbt.com/&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;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; project to build my dbt models in production vs. development environments. At the moment, I need to run the commands:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# prod warehouse&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry run dbt run --target prod&#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;# dev warehouse&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry run dbt run --target dev&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To define shorter just commands for this project I add a &lt;code&gt;justfile&lt;/code&gt; into the project folder.&lt;/p&gt;&#xA;&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;# justfile&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;run-prod *ARGS:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    poetry run dbt run --target prod {{ARGS}}&#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;run-dev *ARGS:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    poetry run dbt run --target dev {{ARGS}}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If I am inside the project folder I can now run &lt;code&gt;just run-prod&lt;/code&gt; and &lt;code&gt;just run-dev&lt;/code&gt;. Moreover, I can pass in any dbt keyword arguments, e.g.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;just run-dev --select mymodel&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;will resolve to&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;poetry run dbt run --target dev --select mymodel&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;is-this-not-just-make&#34;&gt;&#xA;  &lt;a href=&#34;#is-this-not-just-make&#34; class=&#34;header-link&#34;&gt;&#xA;    Is this not just &lt;code&gt;make&lt;/code&gt;?&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;just&lt;/code&gt; is inspired by the Unix build tool &#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Make_%28software%29&#34; &#xA;&#xA;    target=&#34;_blank&#34;&#xA;    &gt;make&#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; from 1978. However, &lt;code&gt;just&lt;/code&gt; is not a build system and focuses solely on command running. This avoids having to deal with things like &lt;code&gt;.PHONY&lt;/code&gt; that can can catch you out in &lt;code&gt;make&lt;/code&gt; recipes. I also like two additional features of &lt;code&gt;just&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I can run my &lt;code&gt;just&lt;/code&gt; commands from any subfolder of the project folder that contains the &lt;code&gt;justfile&lt;/code&gt;. This is useful when I work on this blog. I have to run &lt;code&gt;hugo serve&lt;/code&gt; from the top-level project folder and jupyter-to-markdown converter &lt;code&gt;nb2hugo&lt;/code&gt; from the &lt;code&gt;notebooks/project_x/&lt;/code&gt; subfolder. With &lt;code&gt;just&lt;/code&gt; command aliases it doesn&amp;rsquo;t matter from which folder I run the command.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;just&lt;/code&gt; allows you to load environmental variables from an &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;&#xA;&lt;p&gt;Example &lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;DATABASE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;localhost:1111&#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;USERACCOUNT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;rob1234&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add &lt;code&gt;set load-dotenv&lt;/code&gt; to your &lt;code&gt;justfile&lt;/code&gt; and the environment variables will be available in your shell:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; dotenv-load&#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;check-vars:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    @echo &lt;span class=&#34;s2&#34;&gt;&amp;#34;Env vars are DATABASE:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$DATABASE&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; and USER:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$USERACCOUNT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;                                                                &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running &lt;code&gt;just check-vars&lt;/code&gt; will output:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Env vars are DATABASE:localhost:1111 and USER:rob1234&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Clearing up confusion around IPython, ipykernel, and Jupyter notebooks</title>
      <link>/posts/jupyter-confusion/</link>
      <pubDate>Mon, 26 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>/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 then running the Jupyter web UI.&lt;/li&gt;&#xA;&lt;li&gt;I lacked a clear understanding of the differences of &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 &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#the-different-components&#34; class=&#34;header-link&#34;&gt;&#xA;    The different components&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;&gt;&#xA;  &lt;a href=&#34;#jupyter-kernels-vs-shell-environment&#34; class=&#34;header-link&#34;&gt;&#xA;    Jupyter kernels vs. shell environment&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;One source of confusion is that 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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;List all available jupyter kernels:&lt;/strong&gt;&#xA;&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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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 to 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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;or in a notebook cell:&#xA;&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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h2 id=&#34;dependency-management&#34;&gt;&#xA;  &lt;a href=&#34;#dependency-management&#34; class=&#34;header-link&#34;&gt;&#xA;    Dependency management&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 &#xA;&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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;Create new virtual environment in the folder, then activate it&#xA;&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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;Create a new notebook&#xA;&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;nv&#34;&gt;$touch&lt;/span&gt; mynotebook.ipynb&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;Open notebook in VSCode 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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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 &#xA;&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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and install packages via:&lt;/p&gt;&#xA;&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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&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;&#xA;&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;&#xA;&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>TIL to create continuously numbered lists with content between items</title>
      <link>/til/markdown-lists/</link>
      <pubDate>Wed, 21 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>/til/markdown-lists/</guid>
    <description>&lt;p&gt;When writing notes in markdown I commonly encounter the problem that I want to create an automatically numbered list with content between the items. However, this messes up the numbering as it creates two separate numbered lists, e.g.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;My first point&lt;/li&gt;&#xA;&lt;li&gt;My second point&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;code&gt;code block or image&lt;/code&gt;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;My third point&lt;/li&gt;&#xA;&lt;li&gt;My fourth point&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;The solution to this is &lt;em&gt;embarrassingly obvious&lt;/em&gt; once you know it. Just move the image or code block one level down by indenting it with four spaces. This keeps the list intact.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;My first point&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;My second point&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;code block or image&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;My third point&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;My fourth point&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
    </item>
    
    <item>
      <title>TIL how to set a lower threshold on a column in SQL</title>
      <link>/til/greatest-sql/</link>
      <pubDate>Wed, 07 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>/til/greatest-sql/</guid>
    <description>&lt;p&gt;For the last couple of months I came across multiple instances where I wanted to write an SQL query to lower threshold all the values in a particular column in one of our Snowflake tables.&lt;/p&gt;&#xA;&lt;p&gt;I used quite clunky workarounds to do that. It turns out you can use the SQL functions &lt;code&gt;GREATEST&lt;/code&gt; or &lt;code&gt;LEAST&lt;/code&gt; for it.&lt;/p&gt;&#xA; &lt;h3 id=&#34;example&#34;&gt;&#xA;  &lt;a href=&#34;#example&#34; class=&#34;header-link&#34;&gt;&#xA;    Example&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;I am creating a temporary table in the first CTE with a column &lt;code&gt;DATA_COLUMN&lt;/code&gt; that has positive and negative numbers.&lt;/p&gt;&#xA;&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;example_table&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;o&#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;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;VALUES&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;mi&#34;&gt;1&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;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;423&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;mi&#34;&gt;2&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;mi&#34;&gt;5&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;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;mi&#34;&gt;3&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;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;001&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;mi&#34;&gt;4&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;mi&#34;&gt;100&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;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;mi&#34;&gt;5&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;mi&#34;&gt;12&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;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; &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;t&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;row_nr&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;data_column&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;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;GREATEST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DATA_COLUMN&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;mi&#34;&gt;0&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;thresholded&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;example_table&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Output:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;0.000&#xA;5.000&#xA;0.000&#xA;100.000&#xA;12.000&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The function&amp;rsquo;s primary purpose is to take the greatest value among a number of referenced columns, e.g. &lt;code&gt;GREATEST(column1, column2, column3)&lt;/code&gt;.&lt;/p&gt;&#xA;</description>
    </item>
    
    <item>
      <title>Data analysis: Vätternrundan 2024 results</title>
      <link>/posts/vatternrundan-results/</link>
      <pubDate>Sat, 03 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>/posts/vatternrundan-results/</guid>
    <description>&lt;p&gt;In 2024, I was foolish enough to participate in the &#xA;&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;p&gt;Since this event is a &#xA;&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;, not a race, the organizers only publish finishing times via a bib number search on &#xA;&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;I can use this data to find out:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;information 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;&gt;&#xA;  &lt;a href=&#34;#scraping-the-dataset&#34; class=&#34;header-link&#34;&gt;&#xA;    Scraping the dataset&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;Since getting the timing information from the results page involves several clicks for each start number, I use &#xA;&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; to automate the browser actions. 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 parquet file that is used in the next section. I had to do some light data cleaning, e.g. converting scraped strings to timedelta, removing data for unused startnumbers, etc.&lt;/p&gt;&#xA; &lt;h2 id=&#34;loading-the-dataset&#34;&gt;&#xA;  &lt;a href=&#34;#loading-the-dataset&#34; class=&#34;header-link&#34;&gt;&#xA;    Loading the dataset&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;I load the data from the parquet file into a pandas dataframe. I perform a few additional data cleaning steps, so it is easier to work with the dataset.&lt;/p&gt;&#xA;&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;/code&gt;&lt;/pre&gt;&lt;/div&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#analysing-the-dataset&#34; class=&#34;header-link&#34;&gt;&#xA;    Analysing the dataset&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#the-riders&#34; class=&#34;header-link&#34;&gt;&#xA;    The riders&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#number-of-finishers&#34; class=&#34;header-link&#34;&gt;&#xA;    Number of finishers&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#the-podium-and-top-10&#34; class=&#34;header-link&#34;&gt;&#xA;    The podium and top 10&#xA;  &lt;/a&gt;&#xA;&lt;/h3&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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 teams were:&lt;/p&gt;&#xA;&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#lanterne-rouge&#34; class=&#34;header-link&#34;&gt;&#xA;    Lanterne rouge&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;The slowest finisher took almost 28h.&lt;/p&gt;&#xA;&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;&gt;&#xA;  &lt;a href=&#34;#finishing-times-excluding-sub-9-groups&#34; class=&#34;header-link&#34;&gt;&#xA;    Finishing times (excluding sub-9 groups)&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;figure&gt;&lt;img src=&#34;output_31_0.png&#34;&gt;&#xA;&lt;/figure&gt;&#xA;&#xA;&lt;p&gt;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;&gt;&#xA;  &lt;a href=&#34;#jupyter-notebook&#34; class=&#34;header-link&#34;&gt;&#xA;    Jupyter Notebook&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;You can find the jupyter notebook and the datasets for this post &#xA;&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>/posts/reading-and-note-taking/</link>
      <pubDate>Sun, 26 May 2024 00:00:00 +0000</pubDate>
      
      <guid>/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 enforced 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 of 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-familiarize 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;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 summarize 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;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 finished the book, I transfer the chapter notes into a markdown file (in &#xA;&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. 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 &#xA;&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 &#xA;&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 for 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>DuckDB use cases for data scientists: Querying remote S3 files</title>
      <link>/posts/duckdb-for-data-scientists/</link>
      <pubDate>Sun, 25 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>/posts/duckdb-for-data-scientists/</guid>
    <description>&lt;p&gt;&#xA;&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 analysis 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 &#xA;&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. Since a few months I use 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;&gt;&#xA;  &lt;a href=&#34;#installing-duckdb&#34; class=&#34;header-link&#34;&gt;&#xA;    Installing DuckDB&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h2 id=&#34;authentication-with-aws&#34;&gt;&#xA;  &lt;a href=&#34;#authentication-with-aws&#34; class=&#34;header-link&#34;&gt;&#xA;    Authentication with AWS&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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 work 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;&gt;&#xA;  &lt;a href=&#34;#1-set-aws-credentials-in-the-session&#34; class=&#34;header-link&#34;&gt;&#xA;    1. Set AWS credentials in the session:&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;I can set AWS credentials inside a duck db session like this:&lt;/p&gt;&#xA;&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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;2-let-aws-vault-handle-credentials&#34;&gt;&#xA;  &lt;a href=&#34;#2-let-aws-vault-handle-credentials&#34; class=&#34;header-link&#34;&gt;&#xA;    2. Let aws vault handle credentials&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;I use the AWS credentials management tool &lt;code&gt;aws vault&lt;/code&gt; (see &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#querying-parquet-files&#34; class=&#34;header-link&#34;&gt;&#xA;    Querying parquet files&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&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;pre tabindex=&#34;0&#34;&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&#xA;&lt;/code&gt;&lt;/pre&gt;&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;&gt;&#xA;  &lt;a href=&#34;#inspect-schema-of-parquet-file&#34; class=&#34;header-link&#34;&gt;&#xA;    Inspect schema of parquet file&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;To familiarize myself with the schema I run &lt;code&gt;parquet_schema&lt;/code&gt;&lt;/p&gt;&#xA;&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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which will return:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;clicked_at::timestamp&#xA;user_id::int&#xA;event_type::string&#xA;&lt;/code&gt;&lt;/pre&gt; &lt;h3 id=&#34;query-a-parquet-file&#34;&gt;&#xA;  &lt;a href=&#34;#query-a-parquet-file&#34; class=&#34;header-link&#34;&gt;&#xA;    Query a parquet file&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;query-multiple-parquet-files&#34;&gt;&#xA;  &lt;a href=&#34;#query-multiple-parquet-files&#34; class=&#34;header-link&#34;&gt;&#xA;    Query multiple parquet files&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;Say I want to find the users with the highest number of events across all files. I can use &#xA;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;create-table-from-files&#34;&gt;&#xA;  &lt;a href=&#34;#create-table-from-files&#34; class=&#34;header-link&#34;&gt;&#xA;    Create table from files&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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;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; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h3 id=&#34;query-column-statistics&#34;&gt;&#xA;  &lt;a href=&#34;#query-column-statistics&#34; class=&#34;header-link&#34;&gt;&#xA;    Query column statistics&#xA;  &lt;/a&gt;&#xA;&lt;/h3&gt;&lt;p&gt;A nice feature of the parquet file format is that it stores &#xA;&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;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 class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&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 &#xA;&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>A great weekend</title>
      <link>/posts/great-weekend/</link>
      <pubDate>Sun, 25 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>/posts/great-weekend/</guid>
    <description>&lt;p&gt;After a stressful work week I sometimes fall into the trap of trying to maximize how I use my days off. This makes me restless. I sometimes need to remind myself that the weekend is not about squeezing as many productively used hours into the day, but rather about just living, relaxing, and embracing a little bit of boredom and randomness in your life.&lt;/p&gt;&#xA;&lt;p&gt;So here is a list of activities that make a weekend great:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;walking 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 neighborhood in your city without a particular goal in mind&lt;/li&gt;&#xA;&lt;li&gt;cooking a meal for your partner 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;small talk with someone in your local community, e.g. one of your neighbors&lt;/li&gt;&#xA;&lt;li&gt;messaging or calling a friend who moved far away&lt;/li&gt;&#xA;&lt;li&gt;taking time for an activity (running, cycling, swimming, gym, local club meetup)&lt;/li&gt;&#xA;&lt;li&gt;playing a board game&lt;/li&gt;&#xA;&lt;li&gt;learning a new board game (e.g. Hive, Robinson Crusoe, Wingspan)&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. your bicycle&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 (try a section of the paper you would normally skip)&lt;/li&gt;&#xA;&lt;li&gt;reading or deleting interesting blog posts that you have saved on your phone for later&lt;/li&gt;&#xA;&lt;li&gt;listening to a music genre that you would not normally listen to&lt;/li&gt;&#xA;&lt;li&gt;following a yoga / stretching / meditation routine on youtube&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 your work or career&lt;/li&gt;&#xA;&lt;li&gt;practicing a different language&lt;/li&gt;&#xA;&lt;li&gt;talking to your 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>How to display jupyter notebooks on your hugo blog</title>
      <link>/posts/hugo-and-jupyter/</link>
      <pubDate>Sat, 20 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>/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 my setup how to convert a Jupyter notebook into a blog post for this website, such as &#xA;&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;&gt;&#xA;  &lt;a href=&#34;#writing-the-notebook&#34; class=&#34;header-link&#34;&gt;&#xA;    Writing the notebook&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;The source code for this blog is available in this &#xA;&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;pre tabindex=&#34;0&#34;&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;&#xA;&lt;/code&gt;&lt;/pre&gt;&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;&gt;&#xA;  &lt;a href=&#34;#converting-to-markdown&#34; class=&#34;header-link&#34;&gt;&#xA;    Converting to markdown&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;To align with the markdown-based workflow of Hugo we need to convert the notebook to markdown. The script  &#xA;&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;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;nb2hugo covid_bipartisan_bayesian.ipynb --site-dir /Users/rob/hugoblog/ --section posts&#xA;&lt;/code&gt;&lt;/pre&gt;&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;&gt;&#xA;  &lt;a href=&#34;#adjusting-the-website-css&#34; class=&#34;header-link&#34;&gt;&#xA;    Adjusting the website CSS&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&lt;p&gt;I made two more adjustment 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>
    
  </channel>
</rss>