<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Charles Landau</title>
    <description>The latest articles on DEV Community by Charles Landau (@charlesdlandau).</description>
    <link>https://dev.to/charlesdlandau</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F127580%2F382ebda2-b188-47ef-bde0-dea8428efcb5.jpg</url>
      <title>DEV Community: Charles Landau</title>
      <link>https://dev.to/charlesdlandau</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/charlesdlandau"/>
    <language>en</language>
    <item>
      <title>GitOps Superpowers</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Wed, 19 May 2021 21:23:16 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/gitops-superpowers-40p</link>
      <guid>https://dev.to/charlesdlandau/gitops-superpowers-40p</guid>
      <description>&lt;p&gt;I've been using GitOps for the past few years and I wanted to reflect briefly on what I've learned, how it helps, and how it breaks down.&lt;/p&gt;

&lt;p&gt;The term GitOps was developed by Weaveworks in 2017. It's a technique where you put the desired state of your system in a version controlled repository. When changes are made in the code, those changes get applied to your system automatically (they are "deployed"). There are lots of tools that implement this, including &lt;a href="https://fluxcd.io/"&gt;Weaveworks' own FluxCD tool&lt;/a&gt;, &lt;a href="https://www.terraform.io/cloud"&gt;Terraform Cloud&lt;/a&gt;, &lt;a href="https://vercel.com/"&gt;and Vercel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For a deeper dive on GitOps, &lt;a href="//gitops.tech"&gt;gitops.tech&lt;/a&gt; is a great place to start.&lt;/p&gt;

&lt;p&gt;Since I started using it, GitOps has made it considerably easier for me to build. Considerations like governance, tracking changes, and testing are much less daunting. Generally, what I like to do now is require changes to get a peer review before being accepted. For more sensitive environments some providers will &lt;a href="https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners"&gt;let you assign ownership to specific parts of the system&lt;/a&gt;, so that those owners must be the ones to approve changes. This is great for &lt;a href="https://www.openriskmanual.org/wiki/Four_Eyes_Principle"&gt;enforcing the "four eyes principle"&lt;/a&gt; - that changes can't get made by a single person. Sometimes it can be good to define the desired infrastructure alongside software, as with Vercel or many projects that use &lt;a href="https://helm.sh/"&gt;Helm&lt;/a&gt;. In other cases it's much better to avoid this, such as when you're using GitOps to manage a cloud account.&lt;/p&gt;

&lt;p&gt;All the benefits of defining systems with code roll up to the GitOps approach. Changes in the repository can be tested automatically, you can write reusable libraries, you can try your changes in test/QA environments before accepting them. The nice thing here is that you can accomplish this using git branches! Your CI tool probably has prebuilt jobs that can cover many of these use cases.&lt;/p&gt;

&lt;p&gt;Unfortunately, not everything can always be defined declaratively and deployed automatically and on time. There are a lot of factors that could drive you back to "ClickOps". The most obvious one is when the code doesn't support a resource you need (e.g. there is no Terraform implementation for what you're doing.) Two different problems arise when this happens. The first is that the steps you took manually all add up to a debt, and they need to be taken again if you ever need to redeploy. They need to be documented, and they need to be automated. Failing to document them is very bad, and the task of automating them has a way of languishing in the backlog. The other problem is that you have chipped away at one of the benefits of GitOps. We want the team to trust that the source repository describes the desired state very well. If we have enough manual workarounds tacked on to that desired state it becomes much harder to look at the source repository and understand what's going on.&lt;/p&gt;

&lt;p&gt;In addition to the problem of manual workarounds, there can be some other challenges with GitOps having to do with bootstrapping and kickstarting.&lt;/p&gt;

&lt;p&gt;Bootstrapping a GitOps-managed system can be the cause of a lot of navel-gazing and &lt;a href="https://en.wikipedia.org/wiki/Rube_Goldberg_machine"&gt;Rube Goldberginess&lt;/a&gt;. There is usually no practical reason to automate every aspect of the bootstrapping, and it's turtles all the way down so why bother? (I have a strong urge to automate all the things, so this is mostly advice to myself.) An illustrative example: You may want to make an AWS Account Factory, but you wouldn’t write a puppet to automate the root account provisioning.&lt;/p&gt;

&lt;p&gt;It can sometimes be necessary to "kickstart" resources as well, wherein we delete something that's in the desired state definition, like a container or storage volume, so that the automation pipeline can detect the missing resource and recreate it. There are a lot of different reasons this can end up being needed, often tied to implementation details that are at a lower level of abstraction than you're dealing with. (Immutable infrastructure methodologies seem to have a bunch of related problems here.)&lt;/p&gt;

&lt;p&gt;Despite the challenges, I don't think I'll be transitioning out of GitOps any time soon, and in fact I want to manage more things with GitOps. It feels faster to click through the AWS dashboard and make an S3 bucket, but it's fast in the same way writing code without tests feels like saving time. I think there's more opportunity for data and analytics resources to be managed by GitOps, and &lt;a href="https://twitter.com/kelseyhightower/status/1164194470436302848"&gt;treating configuration like data&lt;/a&gt; opens up all kinds of new possibilities.&lt;/p&gt;

&lt;p&gt;Cover Photo by Zach Reiner on Unsplash&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>kubernetes</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Things I Wish I Knew as a New Python User</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Fri, 26 Mar 2021 18:04:26 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/things-i-wish-i-knew-as-a-new-python-user-46c5</link>
      <guid>https://dev.to/charlesdlandau/things-i-wish-i-knew-as-a-new-python-user-46c5</guid>
      <description>&lt;p&gt;&lt;em&gt;This post originally appeared on the &lt;a href="https://theslipbox.substack.com/p/things-i-wish-i-knew-as-a-new-python"&gt;The Slip Box&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last week I responded to the weekly &lt;a href="https://twitter.com/hashtag/DevDiscuss?src=hashtag_click"&gt;#DevDiscuss&lt;/a&gt; with &lt;a href="https://twitter.com/landau_charles/status/1371991627468836864?s=20"&gt;a long thread&lt;/a&gt; about Python, and this post is the refinement, expansion, and all-around long-form expression of those same ideas. These are all the all the things I wish I knew when I was just starting to use Python, with the benefit of hindsight.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basics
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;There are a million and one tutorials out there to get you up and running with the syntax.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pick any tutorial written for Python 3.6+ and ignore anything written for Python 2. Python 2 is deprecated. They are not all the same, so sample some, and devour at least one deeply. Revisit a few times. FreeCodeCamp wasn't on my radar when I learned Python, but it comes highly recommended. They &lt;a href="https://www.freecodecamp.org/learn/scientific-computing-with-python/#python-for-everybody"&gt;seem to have a very robust Python course&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Do not&lt;/em&gt; expect of yourself to memorize every syntax rule. Many (most?) developers still have to look things up after many years of working with a language, including me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read PEP 8 and PEP 20.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.python.org/dev/peps/pep-0008/"&gt;PEP 8 is the style guide.&lt;/a&gt; Tools like &lt;a href="https://flake8.pycqa.org/en/latest/"&gt;Flake 8&lt;/a&gt; and &lt;a href="https://pypi.org/project/black/"&gt;Black&lt;/a&gt; will help you adhere to it easily. Don't follow it blindly!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A foolish consistency is the hobgoblin of little minds. — PEP 8&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.python.org/dev/peps/pep-0020/"&gt;PEP 20 is the Zen of Python&lt;/a&gt;, which you can refer to whenever somebody tells you something nonsensical with the word "pythonic" mixed in. (We can joke, but the truth is that Python has the power to be beautiful, and that matters to me.)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Beautiful is better than ugly.&lt;br&gt;
Explicit is better than implicit.&lt;br&gt;
Simple is better than complex.&lt;br&gt;
Complex is better than complicated.&lt;br&gt;
Flat is better than nested.&lt;br&gt;
Sparse is better than dense.&lt;br&gt;
Readability counts.&lt;br&gt;
Special cases aren't special enough to break the rules.&lt;br&gt;
Although practicality beats purity.&lt;br&gt;
Errors should never pass silently.&lt;br&gt;
Unless explicitly silenced.&lt;br&gt;
In the face of ambiguity, refuse the temptation to guess.&lt;br&gt;
There should be one-- and preferably only one --obvious way to do it.&lt;br&gt;
Although that way may not be obvious at first unless you're Dutch.&lt;br&gt;
Now is better than never.&lt;br&gt;
Although never is often better than &lt;em&gt;right&lt;/em&gt; now.&lt;br&gt;
If the implementation is hard to explain, it's a bad idea.&lt;br&gt;
If the implementation is easy to explain, it may be a good idea.&lt;br&gt;
Namespaces are one honking great idea -- let's do more of those!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It has been years, and I am still learning to write code that embodies these ideas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Spread your investment in your environment out&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I will never settle on a "perfect" IDE configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DO:&lt;/strong&gt; Install the basic Python extensions for your code editor, plus some productivity/workflow extensions like Git&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DO:&lt;/strong&gt; Try out package-specific extensions for packages you'll be using&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DO NOT:&lt;/strong&gt; Get stuck editing your IDE into a complex configuration that distracts from writing code&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use this excuse to learn git if you aren't already&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Eventually, you will want to share, collaborate, or reuse your code, and then you will want something like Git. I have never heard a developer say "Dang, I wish I had never learned git". In the past, I have been a partisan against anything but the &lt;code&gt;git&lt;/code&gt; CLI, but I was wrong. I still think it's hard to learn the concepts without going to the command line, but if you can do it in the IDE or a desktop client then go for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Standard Library, and Other Packages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;stdlib&lt;/code&gt; is a gold mine. &lt;code&gt;sys&lt;/code&gt;, &lt;code&gt;os&lt;/code&gt;, &lt;code&gt;json&lt;/code&gt;, &lt;code&gt;asyncio&lt;/code&gt;, &lt;code&gt;http&lt;/code&gt;, &lt;code&gt;uuid&lt;/code&gt;, &lt;code&gt;unittest&lt;/code&gt;,  and so many more! Find them all &lt;a href="https://docs.python.org/3/library/"&gt;here&lt;/a&gt;. These libraries are preinstalled with Python! &lt;/p&gt;

&lt;p&gt;Beyond &lt;code&gt;stdlib&lt;/code&gt; there's a whole universe of packages. Python has one of the most vibrant and awesome ecosystems around. &lt;a href="https://github.com/vinta/awesome-python"&gt;This awesome list&lt;/a&gt; organizes a bunch of those libraries into categories for you, and there are many more out there for you to find on &lt;a href="https://pypi.org/"&gt;PyPI&lt;/a&gt;. You can do it with &lt;code&gt;pip&lt;/code&gt;!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pip install mypackage1 mypackage2 mypackage3&lt;/code&gt; to download your packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pip freeze &amp;gt; requirements.txt&lt;/code&gt; to save your installed packages to a file (the file name is conventional)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pip install -r requirements.txt&lt;/code&gt; to install all the packages in &lt;code&gt;requirements.txt&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practices
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Use and dispose of virtual environments often&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python uses "&lt;a href="https://docs.python.org/3/library/venv.html"&gt;virtual environments&lt;/a&gt;" to isolate dependencies. You can use anything you want, and I like &lt;a href="https://python-poetry.org/"&gt;Poetry&lt;/a&gt; a lot, but on Linux I generally start a new project with a simple set of commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init my-py-project
&lt;span class="nb"&gt;cd &lt;/span&gt;my-py-project
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source&lt;/span&gt; ./venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a &lt;a href="https://github.com/github/gitignore"&gt;repo of starter .gitignore files maintained by GitHub&lt;/a&gt; including one for python. It already includes your venv file. Copy it into every project. Never look back. &lt;/p&gt;

&lt;p&gt;Last thing to note: you probably don't need &lt;code&gt;conda&lt;/code&gt;. It's a really great tool, but some folks start out going straight to &lt;code&gt;conda&lt;/code&gt; but I think Poetry or venv is enough for now. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static Type Checking&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://mypy.readthedocs.io/en/stable/getting_started.html#installing-and-running-mypy"&gt;mypy&lt;/a&gt;, you can add static typing to Python. Famously, Guido Van Rossum, the creator of Python, &lt;a href="https://blog.dropbox.com/topics/company/thank-you--guido"&gt;led a team at Dropbox to add mypy type checks to four million lines of code&lt;/a&gt;. New versions of Python have been &lt;a href="https://www.python.org/dev/peps/pep-0589/"&gt;adding language features&lt;/a&gt; that complement type checking.&lt;/p&gt;

&lt;p&gt;For quick, one-off projects, you might skip mypy. If you're going to be working with a project for a significant period of time, static type checking can eliminate entire categories of errors from your Python.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation is a Superpower&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PEP 257 and a few others define "docstrings". Leverage them to make full use of autodoc tools. &lt;code&gt;pdoc&lt;/code&gt; &lt;a href="https://pdoc.dev/"&gt;is a pretty fun tool&lt;/a&gt; that "just works". Build good habits from the start. Projects that have great documentation are &lt;em&gt;just more attractive to me&lt;/em&gt;. If I come across a project that seems to do what I need, but has crappy documentation, I keep looking.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any code of your own that you haven’t looked at for six or more months might as well have been written by someone else. — &lt;a href="https://www.ithistory.org/quotes/eagleson%E2%80%99s-law"&gt;Eagleson's Law&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Thank You Python
&lt;/h3&gt;

&lt;p&gt;Python has truly changed my life. No kidding. I love python, it has given me so much joy and I owe it so much. I hope more people learn and love python.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@pkprasad1996?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Prasad Panchakshari&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/snakes?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The Wrong Question About Docker and Kubernetes</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Mon, 18 May 2020 21:17:35 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/the-wrong-question-about-docker-and-kubernetes-15p6</link>
      <guid>https://dev.to/charlesdlandau/the-wrong-question-about-docker-and-kubernetes-15p6</guid>
      <description>&lt;p&gt;Not too long ago I discovered the work of a very smart and snarky cloud economist by the name of Corey Quinn. There’s a lot to admire in how Corey delivers content, his perspective on the industry, and his sense of humor. Having said that, I’ve been on the k8s learning curve for a little while now, and Corey’s pretty bearish on the topic. &lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--gEXrJZmK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1247254348498743300/vTTJS5wW_normal.jpg" alt="Corey Quinn profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Corey Quinn
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @quinnypig
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4t6ys1m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      If you run Kubernetes in production, you must be incredibly intelligent. &lt;br&gt;&lt;br&gt;That’s not a compliment; it’s a requirement.
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      17:13 PM - 25 Apr 2019
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1121462122741940226" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WwRENZp4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1121462122741940226" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PFD0MJBa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1121462122741940226" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6wx1BHu3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Corey is one of many cloud computing advocates taking this position, offered here as an example. He’s not the only one, and I even see Kelsey Hightower, one of the original evangelists for k8s, urging some caution. “Up and Running”, a book Kelsey co-authored, was my introduction to k8s, and I’ve tried to pay close attention to Kelsey ever since.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--RQUjub1G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1204077305271705606/j5XjhPAt_normal.jpg" alt="Kelsey Hightower profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Kelsey Hightower
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @kelseyhightower
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4t6ys1m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      So you want to roll your own application platform. All you need is:&lt;br&gt;&lt;br&gt;Linux&lt;br&gt;Docker&lt;br&gt;Kubernetes&lt;br&gt;Istio&lt;br&gt;Prometheus&lt;br&gt;Fluentd&lt;br&gt;Grafana&lt;br&gt;Jaeger&lt;br&gt;Harbor&lt;br&gt;Open Policy Agent&lt;br&gt;Vault&lt;br&gt;Spinnaker and Jenkins&lt;br&gt;&lt;br&gt;Oh, almost forgot, you're also going to need servers, people, and glue. Bring lots of glue.
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      01:32 AM - 03 Apr 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1245886920443363329" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WwRENZp4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1245886920443363329" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PFD0MJBa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1245886920443363329" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6wx1BHu3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;I think all of the above is fair, and I think the point about k8s complexity is hard to argue with. It’s easy for somebody to read expert opinions about this technology and get the wrong signal, because you might be starting with the wrong question. In this post, I’m going to urge you not to begin with the question “do I need docker or kubernetes?” Instead, begin with the question “could we get value from the technical and management practices required to express a Dockerfile? A k8s podspec?”&lt;/p&gt;

&lt;h2&gt;
  
  
  The iceberg of business value
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5mNhKnVh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://serve-md.charlesdlandau.net/img/tools_automation.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5mNhKnVh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://serve-md.charlesdlandau.net/img/tools_automation.PNG" alt="Highly Scientific Chart"&gt;&lt;/a&gt;&lt;/p&gt;
Very Scientific Chart



&lt;p&gt;As my question suggests, I have come to believe that the business process required to write a Dockerfile is more valuable than the tooling itself, and can require much more effort than the actual investment in Docker. Is there scripting in place to automate the build and run processes in a reproducible manner? Are all the dependencies fully documented? Have you followed the &lt;a href="https://12factor.net/"&gt;12 Factor App&lt;/a&gt; framework or similar? Addressing these questions is where most of the value comes from, and Docker happens to be a particularly successful technology that helps organizations deliver after they’ve done so.&lt;/p&gt;

&lt;p&gt;The same can be said about your services. The business and technical processes can go beyond expressing their build and run steps in a Dockerfile and can be extended to expressing their services as k8s podspecs.&lt;/p&gt;

&lt;p&gt;Lastly, don’t trivialize that this is a genuine question about value! Maybe it makes more sense for your team to go the way of the &lt;a href="https://m.signalvnoise.com/the-majestic-monolith/"&gt;Majestic Monolith&lt;/a&gt;. Go where the value is regardless of hype. If the technology you want to work with isn’t valuable to the shop you work in, perhaps that’s a signal for you to consider other employment, not a signal for the business to change value streams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;As I mentioned, I’m still on the learning curve for these technologies, so please take these words with a grain of salt. My hope is that this post has given you an alternative point of view on value creation in the container and container orchestration space. It’s hard to stay grounded when you’re learning about very hyped technologies, and refocusing on business value is how I’ve learned to cope.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>kubernetes</category>
      <category>career</category>
    </item>
    <item>
      <title>Greedy Learning and Rapid Adoption</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Wed, 25 Mar 2020 19:46:48 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/greedy-learning-and-rapid-adoption-5aon</link>
      <guid>https://dev.to/charlesdlandau/greedy-learning-and-rapid-adoption-5aon</guid>
      <description>&lt;p&gt;A long time ago I gave up on knowing anything about coding, tech, or development. Knowing things takes a long, long time.&lt;/p&gt;

&lt;p&gt;My memory is not great and even if it was, it's hard to justify technical decisions with "...well I remember the docs said xyz." So I gave up on remembering things too.&lt;/p&gt;

&lt;p&gt;Nonetheless, I want to explore and learn about new tools constantly. I want to be unconstrained in the solutions I compose. The only way I can live like this is to cheat a little bit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Greedy Part
&lt;/h2&gt;

&lt;p&gt;"Greedy learning" is a mental model for rapid adoption of new technologies. It essentially means that we start with the laziest, most intuitive search, and graph everything from that point on.&lt;/p&gt;

&lt;p&gt;The root node of the graph is you, because we're being greedy. The only intermediate node before we do a search is your intent. Let's say that we want to perform web requests in Python.&lt;/p&gt;

&lt;p&gt;Our initial knowledge graph is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;self -&amp;gt; intent:"web requests python" -&amp;gt; search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Most of the time, you will perform the &lt;code&gt;search&lt;/code&gt; on a public search engine, the intranet at your job, or a &lt;a href="http://repl.it"&gt;REPL&lt;/a&gt;. If you are very fortunate, you may have an "enterprise search" tool like &lt;a href="https://labs.spotify.com/2020/02/27/how-we-improved-data-discovery-for-data-scientists-at-spotify/"&gt;Spotify Lexikon&lt;/a&gt; that makes intent-based search trivial. Regardless, at this step you must become as lazy as you possibly can.&lt;/p&gt;

&lt;p&gt;For example, I have found that if I am interested in a topic, I can write &lt;code&gt;awesome&lt;/code&gt; at the beginning of a &lt;code&gt;search&lt;/code&gt; and I will often find an &lt;a href="https://github.com/sindresorhus/awesome"&gt;awesome list&lt;/a&gt; about it. Just like that, we have many subgraphs to explore.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;search results "awesome data engineering" -&amp;gt;
        intent:"explore_subgraph" -&amp;gt;
            root_graph_update:new_search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Likewise, if I think I can guess the answer, my search may begin at the REPL, where I test my guess, and the error messages I invariably generate become new searches.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;search results "print foo" -&amp;gt;
    errors -&amp;gt;
        intent:from_error -&amp;gt;
            root_graph_update:new_search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We want to do all of this fast and lazy. We're speed-reading in the &lt;a href="https://www.nngroup.com/articles/f-shaped-pattern-reading-web-content/"&gt;F-shape pattern&lt;/a&gt;. Everything should make intuitive sense. If it doesn't make intuitive sense, that indicates that we're missing something upstream in our knowledge graph.&lt;/p&gt;

&lt;p&gt;To extend our &lt;code&gt;intent:"web requests python"&lt;/code&gt; example, something about query parameters may come up which doesn't make intuitive sense. We don't abandon our scanning pattern and start deeply reading, but instead we generate a new intent to update our query parameters subgraph.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rapid Adoption
&lt;/h2&gt;

&lt;p&gt;At this point you may be thinking that I've created a long-winded manual for competitive Wikipedia surfing. Or a deep rationalization for my &lt;a href="https://randsinrepose.com/archives/nadd/"&gt;NADD&lt;/a&gt;. I hope I've done neither, and I think "rapid adoption" is the missing piece that sets this apart.&lt;/p&gt;

&lt;p&gt;In as few iterations of greedy learning as possible, we need to learn a schema to satisfy our root intent. Fundamentally, this schema defines an actionable subgraph of nodes. Ideally, each &lt;code&gt;root_graph_update&lt;/code&gt; modifies the schema, or we come to our problem with clear expectations. As quickly and as lazily as possible, we have a minimum actionable subgraph. Again, our "no memory or knowledge" assumption doesn't require us to start from scratch. It is perfectly valid to start with a schema that is &lt;em&gt;intuitive&lt;/em&gt; so long as you update it frequently based on search results and your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Complete Example
&lt;/h2&gt;

&lt;p&gt;(Full graph on &lt;a href="https://whimsical.com/N5UqTXUuAcUKKYPx62ZHwD#2Ux7TurymLpH6xFR6NcZ"&gt;Whimsical&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;We'll begin with a basic &lt;code&gt;root_graph&lt;/code&gt; as described above, for our example of a web request client in Python.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pAbqnOUV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4s48pylztqenc2dufwhq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pAbqnOUV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4s48pylztqenc2dufwhq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
The root graph when we look for "python web request" tools



&lt;p&gt;We have an intuition that a good tool for us will have some obvious qualities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It will have a strong community of support, such as lots of answers on Stack Overflow, or frequent releases on GitHub.&lt;/li&gt;
&lt;li&gt;It is written in, or has binding for, the language we care about.&lt;/li&gt;
&lt;li&gt;It has the required level of performance.&lt;/li&gt;
&lt;li&gt;It is &lt;em&gt;productive.&lt;/em&gt; I certainly struggle to measure the productivity of software libraries. The number of lines of code required to complete a basic task is, perhaps, a good proxy.&lt;/li&gt;
&lt;li&gt;The interface fits our use case. For web requests, we're looking for a way to make the request, and read the response.

&lt;ul&gt;
&lt;li&gt;We may also intuit that the response object should have methods like &lt;code&gt;.status_code&lt;/code&gt; or &lt;code&gt;.json&lt;/code&gt; but let's keep our example simple for now.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With our schema prepared, we proceed to search.&lt;/p&gt;

&lt;p&gt;For me, the simplest and most intuitive search for this intent is to just restate the intent and append the word "library", ensuring that I get more results that can be &lt;code&gt;import&lt;/code&gt;ed, rather than tutorials.&lt;/p&gt;

&lt;p&gt;The first thing that jumps out at us is &lt;code&gt;stdlib.http.client&lt;/code&gt; — given that we are exceedingly lazy and greedy, we have a strong bias for standard library tools which require no installation.&lt;/p&gt;

&lt;p&gt;Upon arriving at the &lt;a href="https://docs.python.org/3/library/http.client.html"&gt;docs&lt;/a&gt;, we discover the following callout:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;See also:&lt;/strong&gt; The &lt;a href="https://requests.readthedocs.io/en/master/"&gt;Requests package&lt;/a&gt; is recommended for a higher-level HTTP client interface.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We don't need to read any further. In the terms of &lt;a href="https://www.youtube.com/watch?v=YX2XR73LnRY"&gt;Kent Beck's 3X framework&lt;/a&gt;, we are firmly in the "explorers" camp. We leave the tab open so we can always come back to this page if the high-level interface doesn't meet our needs, and we move on to the &lt;code&gt;requests&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;requests&lt;/code&gt; docs immediately tell us a couple of things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The GitHub for this tool has more than 42,000 stars from developers and it's maintained by the Python Software Foundation, who also maintain Python itself. Strong community ✔️&lt;/li&gt;
&lt;li&gt;That this tool has a &lt;code&gt;Request&lt;/code&gt; object and &lt;code&gt;Response&lt;/code&gt; object ✔️&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, we go hunting for the interface &lt;a href="https://requests.readthedocs.io/en/master/api/"&gt;docs&lt;/a&gt;, and scanning through the quickstart. Reading a quickstart tells us which features the maintainers consider "core" to their user's experience. This matters because, as explorers, we have a strong preference for finding tools that support the features we care about as a core value, rather than kludges.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AnQKcjKM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wdag46oyidvxznvb6wi9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AnQKcjKM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wdag46oyidvxznvb6wi9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
From our search, multiple subgraphs



&lt;p&gt;With the complete documentation of our &lt;code&gt;Request&lt;/code&gt; and &lt;code&gt;Response&lt;/code&gt; objects in hand, we are ready get our hands slightly dirty. We can perform a simple validation that the core functions work in a REPL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--50IC5biE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/erapc7sreoqzaobxrad9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--50IC5biE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/erapc7sreoqzaobxrad9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
A smoke test of our search results



&lt;p&gt;At this point we are ready to check our subgraph against the schema. In the schema I outlined, we would do this by asking: Is it productive, performant, and Python? Does it have an interface to the features we need? Is it supported by a healthy community?&lt;/p&gt;

&lt;p&gt;In your schema, perhaps none of these questions will matter, and you'll care about something else.&lt;/p&gt;

&lt;p&gt;If our subgraph is valid, we can move to adoption. "Adoption" means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow way down. Up until now we've been trying to go as fast as possible. You could even write unit tests if you want.

&lt;ul&gt;
&lt;li&gt;You might even want to stand up and stretch for a while before starting this part. Get into a different mindset.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;With the tabs for each part of the interface open, write the interface calls into our real use case.&lt;/li&gt;
&lt;li&gt;Refer to the appropriate docs actively as you write.&lt;/li&gt;
&lt;li&gt;Run the solution and refer to the open tabs for errors.&lt;/li&gt;
&lt;li&gt;If the solution doesn't work, update the &lt;code&gt;root_graph&lt;/code&gt; accordingly and resume your search or generate a new search.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Arguments and Persuasion
&lt;/h2&gt;

&lt;p&gt;I should end by warning you that this method has never worked for me where &lt;em&gt;depth is the point.&lt;/em&gt; The way I think about this is as a distinction between arguments and persuasion.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arguments:&lt;/strong&gt; making strong logical connections in support of a thesis (as with a knowledge graph). "These are the reasons for this change, and how."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persuasion:&lt;/strong&gt; knowing the audience deeply and speaking to them from a place of radical empathy. "I know you, and what you want is this change."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there's anything that fits this mental model of arguments, it's interfaces. An API documents a clear argument: Given &lt;em&gt;xyz&lt;/em&gt; parameters and &lt;em&gt;abc&lt;/em&gt; state, an endpoint &lt;code&gt;/api/v2/users&lt;/code&gt; should return an instance of &lt;code&gt;Response/Users.schema&lt;/code&gt;. Another example is troubleshooting.&lt;/p&gt;

&lt;p&gt;Recording all of this has certainly been interesting for me as an exercise, and I hope you've found it useful. I'm always trying to learn more, so if you have feedback, let me know!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Data Engineering vs Data Science</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Mon, 27 Jan 2020 12:12:23 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/data-engineering-vs-data-science-50gn</link>
      <guid>https://dev.to/charlesdlandau/data-engineering-vs-data-science-50gn</guid>
      <description>&lt;p&gt;I was in a local technology Slack and saw the question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tell me, what is data engineering and how is it different than data science? What [Python] tools do you use?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's a good question and it's worth considering. Here's what I think:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/4WF7SSNIxQMRMflOAE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/4WF7SSNIxQMRMflOAE/giphy.gif" alt="https://media.giphy.com/media/4WF7SSNIxQMRMflOAE/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;
Ted Danson reading a slip of paper. Caption: "Okay, here we go"



&lt;p&gt;Data engineers are concerned with how data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lands in a system&lt;/li&gt;
&lt;li&gt;Moves through a system&lt;/li&gt;
&lt;li&gt;Interacts with business processes and application logic&lt;/li&gt;
&lt;li&gt;Is stored&lt;/li&gt;
&lt;li&gt;Is governed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Definitions differ, but I think that's a good starting place.&lt;/p&gt;

&lt;p&gt;There is a huge and diverse ecosystem of tools out there. I would highlight the following as tools with strong Python tooling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kafka (for pub/sub)&lt;/li&gt;
&lt;li&gt;Spark for data processing (including the Spark Streaming API for stream processing)&lt;/li&gt;
&lt;li&gt;Airflow for workflow management&lt;/li&gt;
&lt;li&gt;Pandas for data "wrangling"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you can find tons of tools on the &lt;a href="//github.com/igorbarinov/awesome-data-engineering"&gt;awesome list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, how do data scientists differ from data engineers? I would argue that they're both roles that are concerned with connecting data to business processes. They differ the same way their names differ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A data engineer is concerned with designing and building systems that make data available and actionable in a cost-effective manner.&lt;/li&gt;
&lt;li&gt;A data scientist performs experiments, the results of which are (sometimes) actionable insights or automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope that explanation helps you. If you see something I didn't explain very well, or got wrong, please chime in with that 👇&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>career</category>
    </item>
    <item>
      <title>What do you think about the "Shape Up" project management framework?</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Tue, 26 Nov 2019 23:05:37 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/what-do-you-think-about-the-shape-up-project-management-framework-ccm</link>
      <guid>https://dev.to/charlesdlandau/what-do-you-think-about-the-shape-up-project-management-framework-ccm</guid>
      <description>&lt;p&gt;And if you haven't checked it out, &lt;a href="https://basecamp.com/shapeup"&gt;here it is&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>discuss</category>
      <category>management</category>
    </item>
    <item>
      <title>How does open source impact your local community?</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Wed, 06 Nov 2019 14:40:16 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/how-does-open-source-impact-your-local-community-369e</link>
      <guid>https://dev.to/charlesdlandau/how-does-open-source-impact-your-local-community-369e</guid>
      <description>&lt;p&gt;For the past few months I've been participating with &lt;a href="https://codefordc.org/"&gt;Code for DC&lt;/a&gt;, a &lt;a href="https://brigade.codeforamerica.org/"&gt;Code for America brigade&lt;/a&gt;. As part of this work I even joined a civic tech podcast for a discussion about one of the projects we're working on (I'll post that in the comments).&lt;/p&gt;

&lt;p&gt;Like most volunteer organizations, I've seen how the leaders of the brigade struggle to understand the impact of their work. Anyway, all this led me to wonder how open source is impacting other communities. So, I thought it might be worth asking:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How has open source impacted your local community (if at all)?&lt;/li&gt;
&lt;li&gt;Has your journey as a developer given you new tools you can use to help your community?&lt;/li&gt;
&lt;li&gt;What are some ways that open source COULD help your local community, but currently doesn't?&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Python 3.8 Has Been Released 🚀🚀 Let's Take a Tour</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Wed, 16 Oct 2019 15:55:56 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/python-3-8-has-been-released-let-s-take-a-tour-bj3</link>
      <guid>https://dev.to/charlesdlandau/python-3-8-has-been-released-let-s-take-a-tour-bj3</guid>
      <description>Cover Image by Onur Ömer Yavuz from Pixabay



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Python 3.8.0rc1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.python.org/downloads/release/python-380/"&gt;Launch Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python 3.8 is a major release of Python. Here's a roundup of some new features.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;New Syntax Rules!&lt;/li&gt;
&lt;li&gt;Parallel Data Ops Improvements!&lt;/li&gt;
&lt;li&gt;Static Type Checking Features!&lt;/li&gt;
&lt;li&gt;CPython Stuff!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's start with a new syntax rule:&lt;/p&gt;
&lt;h2&gt;
  
  
  Assignment in Expressions (PEP 572)
&lt;/h2&gt;

&lt;p&gt;Python now allows you to create variables inside of expressions (e.g. the body of a list comprehension.)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="c1"&gt;# Reuse a value that's expensive to compute
&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Without reuse
&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.78 s ± 13.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
5.45 s ± 93.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Doing this in a "naked" expression is strongly discouraged in the PEP. See: &lt;a href="https://www.python.org/dev/peps/pep-0572/#exceptional-cases"&gt;Exceptional Cases&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.python.org/dev/peps/pep-0572/"&gt;PEP 572&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's one more new syntax rule:&lt;/p&gt;
&lt;h2&gt;
  
  
  Positional-Only Args (PEP 570)
&lt;/h2&gt;

&lt;p&gt;This one confused me until I scrolled down to the syntax section, so let's just see it in action:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;prelaunch_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Foo:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Bar:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Baz:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pep570_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Foo:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Bar:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Baz:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;/&lt;/code&gt; in the call signature of &lt;code&gt;pep570_func&lt;/code&gt; denotes where the positional-only args end. These functions will let us see the practical difference PEP 570 causes.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;prelaunch_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Foo:1
Bar:2
Baz:3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Violating positional-only
&lt;/span&gt;&lt;span class="n"&gt;pep570_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

&amp;lt;ipython-input-4-9e9851275486&amp;gt; in &amp;lt;module&amp;gt;
      1 # Violating positional-only
----&amp;gt; 2 pep570_func(foo=1, bar=2, baz=3)


TypeError: pep570_func() got some positional-only arguments passed as keyword arguments: 'foo'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This is fine, as bar is right of the "/" in the call signature
&lt;/span&gt;&lt;span class="n"&gt;pep570_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Foo:1
Bar:2
Baz:3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This was wrong before PEP-570 of course
&lt;/span&gt;&lt;span class="n"&gt;pep570_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  File "&amp;lt;ipython-input-6-adcd14865e94&amp;gt;", line 2
    pep570_func(foo=1, 2, baz=3)
                       ^
SyntaxError: positional argument follows keyword argument
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;What I like best about this PEP is that you can also have positional-only args with default values, as shown here:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pep570_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Foo:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Bar:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Baz:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;baz&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;pep570_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Foo:10
Bar:None
Baz:1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# But don't mistake them for kwargs
&lt;/span&gt;&lt;span class="n"&gt;pep570_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

&amp;lt;ipython-input-8-05c1c4b07ca6&amp;gt; in &amp;lt;module&amp;gt;
      1 # But don't mistake them for kwargs
----&amp;gt; 2 pep570_func(10, bar=1)


TypeError: pep570_func() got some positional-only arguments passed as keyword arguments: 'bar'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;For more details check out the PEP: &lt;a href="https://www.python.org/dev/peps/pep-0570/"&gt;PEP-570&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's move on to some parallel data processing stuff:&lt;/p&gt;
&lt;h2&gt;
  
  
  Shared Memory and New Pickles
&lt;/h2&gt;

&lt;p&gt;Two important improvements in 3.8 were inspired by libraries like &lt;a href="https://docs.dask.org/en/latest/"&gt;dask&lt;/a&gt; that try to solve the problem of passing data between processes. One is to create a new version of &lt;code&gt;pickle&lt;/code&gt; that can pass data objects between processeses using zero-copy buffers, for more memory efficient sharing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The common theme of these third-party serialization efforts is to generate a stream of object metadata (which contains pickle-like information about the objects being serialized) and a separate stream of zero-copy buffer objects for the payloads of large objects. Note that, in this scheme, small objects such as ints, etc. can be dumped together with the metadata stream. Refinements can include opportunistic compression of large data depending on its type and layout, like dask does.&lt;/p&gt;

&lt;p&gt;This PEP aims to make pickle usable in a way where large data is handled as a separate stream of zero-copy buffers, letting the application handle those buffers optimally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.python.org/dev/peps/pep-0574/#rationale"&gt;PEP-574&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The other biggie in this category is that processes have a new interface for sharing memory: &lt;code&gt;SharedMemory&lt;/code&gt; and &lt;code&gt;SharedMemoryManager&lt;/code&gt;. The docs feature a very exciting example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing.managers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SharedMemoryManager&lt;/span&gt;

&lt;span class="c1"&gt;# Arbitrary operations on a shared list
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_work&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shared_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;shared_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# Example from the docs
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;SharedMemoryManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;smm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;sl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;smm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShareableList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;# Divide the work among two processes, storing partial results in sl
&lt;/span&gt;    &lt;span class="n"&gt;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;do_work&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;p2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multiprocessing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;do_work&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# A multiprocessing.Pool might be more efficient
&lt;/span&gt;    &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="c1"&gt;# Wait for all work to complete in both processes
&lt;/span&gt;    &lt;span class="n"&gt;total_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Consolidate the partial results now in sl
&lt;/span&gt;
&lt;span class="c1"&gt;# `do_work` set all values to 1 in parallel
&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Total of values in shared list: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total_result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total of values in shared list: 2000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;It remains to be seen if these improvements create a happy path that parallel ops focused libraries will adopt. In any case, it's exciting. Check out &lt;code&gt;SharedMemory&lt;/code&gt; &lt;a href="https://docs.python.org/3.8/library/multiprocessing.shared_memory.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now let's look at some staic type checking stuff:&lt;/p&gt;
&lt;h2&gt;
  
  
  Typed Dictionaries (PEP 589)
&lt;/h2&gt;

&lt;p&gt;Type hints don't cover nested dicts and dataclasses don't parse to JSON well enough, so now Python will support some static type-checking for dictionaries with a known set of keys. Consider the script below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# scripts/valid_589.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

&lt;span class="c1"&gt;# Cannonical assignment of Movie
&lt;/span&gt;&lt;span class="n"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Wally 2: Rise of the Garbage Bots'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'year'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2055&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;mypy&lt;/code&gt; will pass this with no issues because the dictionary is a valid implementation of a type.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;mypy&lt;/span&gt; &lt;span class="n"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;valid_589&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1m[32mSuccess: no issues found in 1 source file[m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now consider the invalid script below -- it has values of the wrong types:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# scripts/invalid_values_589.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'year'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'year'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'wrong type'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;mypy&lt;/span&gt; &lt;span class="n"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;invalid_values_589&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scripts/invalid_values_589.py:10: [1m[31merror:[m Incompatible types (expression has type [m[1m"str"[m, TypedDict item [m[1m"year"[m has type [m[1m"int"[m)[m
scripts/invalid_values_589.py:10: [1m[31merror:[m Incompatible types (expression has type [m[1m"int"[m, TypedDict item [m[1m"name"[m has type [m[1m"str"[m)[m
[1m[31mFound 2 errors in 1 file (checked 1 source file)[m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;You can also check for missing values, invalid fields, or create &lt;code&gt;TypedDict&lt;/code&gt;s that will accept missing values by using the &lt;code&gt;total=False&lt;/code&gt; with the constructor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.python.org/dev/peps/pep-0589"&gt;PEP 589&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Finality (PEP 591)
&lt;/h2&gt;

&lt;p&gt;3.8 will also implement finality. We can prevent objects from being overriden or inherited. The &lt;code&gt;@final&lt;/code&gt; decorator can be used with a &lt;code&gt;class&lt;/code&gt; definition to prevent inheritence, and the &lt;code&gt;Final&lt;/code&gt; type will prevent overrides. Here's two examples from the PEP:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example 1, inheriting a @final class
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;final&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  &lt;span class="c1"&gt;# Error: Cannot inherit from final class "Base"
&lt;/span&gt;    &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;# Example 2, overriding an attribute
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Final&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;BORDER_WIDTH&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Final&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;BORDER_WIDTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;  &lt;span class="c1"&gt;# Error: can't override a final attribute
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finality can be applied to methods, attributes and inheritence. Check out all the features in &lt;a href="https://www.python.org/dev/peps/pep-0591/"&gt;PEP 591&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Literals (PEP 586)
&lt;/h2&gt;

&lt;p&gt;The type hinting call signature &lt;code&gt;def f(k: int):&lt;/code&gt; doesn't help us if the function expects &lt;code&gt;int&lt;/code&gt;s in a range. &lt;code&gt;open&lt;/code&gt; requires a &lt;code&gt;mode: str&lt;/code&gt; argument from a specific set of strings. &lt;code&gt;Literal&lt;/code&gt;s to the rescue!&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# scripts/problematic_586.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;problematic_586&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Gotta be less than 100'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;problematic_586&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;144&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;mypy&lt;/span&gt; &lt;span class="n"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;problematic_586&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1m[32mSuccess: no issues found in 1 source file[m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Instead, we can pass a &lt;code&gt;Literal&lt;/code&gt; to the type hinting for our argument &lt;code&gt;k&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# scripts/valid_586.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;valid_586&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;valid_586&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;43&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;mypy&lt;/span&gt; &lt;span class="n"&gt;scripts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;valid_586&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scripts/valid_586.py:8: [1m[31merror:[m Argument 1 to [m[1m"valid_586"[m has incompatible type [m[1m"Literal[43]"[m; expected [m[1m"Union[Literal[0], Literal[1], Literal[2], Literal[99]]"[m[m
[1m[31mFound 1 error in 1 file (checked 1 source file)[m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;There's a bit of nuance to using &lt;code&gt;Literal&lt;/code&gt; so if you decide to explore further start with &lt;a href="https://www.python.org/dev/peps/pep-0586"&gt;PEP-586&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And that's it! I'm going to hold off on writing about the CPython features because, frankly, I would prefer not to write about them until I have my arms more firmly around CPython generally and those features in particular.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;P.S. If you would like to play with any of the examples in this blog or test drive Python3.8 without installing it, I'm providing the source repository for this blog below. It includes a Dockerfile that spins up a Python 3.8 jupyterlab environment.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/CharlesDLandau"&gt;
        CharlesDLandau
      &lt;/a&gt; / &lt;a href="https://github.com/CharlesDLandau/python38_blog"&gt;
        python38_blog
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A repo with the source material for a blog
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Python38_Tour&lt;/h1&gt;
&lt;p&gt;This is the source repo for this blog, and it also includes a Dockerfile for simply launching python 3.8 without having to install it locally. So:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;//build
docker build -t &lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;img_tag&lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt; &lt;span class="pl-c1"&gt;.&lt;/span&gt;

//run on &lt;span class="pl-k"&gt;*&lt;/span&gt;nix
docker run -p 8888:8888 -it --rm -v &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;$(&lt;/span&gt;PWD&lt;span class="pl-pds"&gt;)&lt;/span&gt;&lt;/span&gt;:/code --name dev &lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;img_tag&lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt;

//run on windows
docker run -p 8888:8888 -it --rm -v %CD%:/code --name dev &lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;img_tag&lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If all goes well you'll be prompted to copy a URL into your browser, which will point to your local port 8888 with a token to authorize access to the Jupyter instance.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/CharlesDLandau/python38_blog"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>python</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Data Munging with Common Pandas Operations</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Wed, 09 Oct 2019 13:10:37 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/data-munging-with-common-pandas-operations-2il4</link>
      <guid>https://dev.to/charlesdlandau/data-munging-with-common-pandas-operations-2il4</guid>
      <description>&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;Why am I writing the billionth article on Pandas data munging? Aren't the other articles enough? Maybe! If you already read a few of those and you feel like you know a lot about Pandas maybe your time would be better spent moving on to some of these materials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/wesm/pydata-book"&gt;Python for Data Analysis by Pandas BDFL Wes McKinney&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/enhancingperf.html"&gt;Enhancing Performance by the Pandas dev team&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.dask.org/en/latest/"&gt;Introduction to Dask for parallel computing in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jakevdp.github.io/PythonDataScienceHandbook/"&gt;The Python Data Science Handbook by Jake VanderPlas&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Quick note: throughout this article I'm going to refer to features and observations. When you start working with multidimensional problems it's an important distinction, but in this article a feature is the same as a spreadsheet column, and an observation is the same as a spreadsheet row.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're going to work with some random data, which you can construct directly. Pandas &lt;code&gt;DataFrames&lt;/code&gt; are constructed from Pandas &lt;code&gt;Series&lt;/code&gt; objects, which in turn use &lt;code&gt;numpy&lt;/code&gt; objects and operations for many of their behaviors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a DataFrame with some randomized columns
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s"&gt;"str_feature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;"dog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"snake"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="s"&gt;"int_feature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.head&lt;/code&gt; method can grab the top &lt;code&gt;n&lt;/code&gt; rows, five by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Of course in some circumstances we don't want to take the first 5 or 10. We can take a pseudo-random sample of the data using &lt;code&gt;.sample&lt;/code&gt;. Note that &lt;code&gt;.sample&lt;/code&gt; defaults to 1 observation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2476&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;2476&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2793&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;2793&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3120&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;3120&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9338&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;9338&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3593&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;3593&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We can get the underlying types by accessing the &lt;code&gt;.dtypes&lt;/code&gt; attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtypes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;str_feature    object
int_feature     int32
dtype: object
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It should be stressed that &lt;code&gt;object&lt;/code&gt; features are less memory efficient than &lt;code&gt;int&lt;/code&gt; features. A discussion of the basic &lt;code&gt;dtypes&lt;/code&gt; is included in the &lt;a href="https://pandas.pydata.org/pandas-docs/stable/getting_started/basics.html#basics-dtypes"&gt;official getting started guide&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Descriptive statistics can be reported using &lt;code&gt;.describe&lt;/code&gt; -- note that only numerical features will be summarized.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;count&lt;/td&gt;
      &lt;td&gt;10000.00000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;mean&lt;/td&gt;
      &lt;td&gt;4999.50000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;std&lt;/td&gt;
      &lt;td&gt;2886.89568&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;min&lt;/td&gt;
      &lt;td&gt;0.00000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;25%&lt;/td&gt;
      &lt;td&gt;2499.75000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;50%&lt;/td&gt;
      &lt;td&gt;4999.50000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;75%&lt;/td&gt;
      &lt;td&gt;7499.25000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;max&lt;/td&gt;
      &lt;td&gt;9999.00000&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The descriptive statistics in this report have their own methods, for example here's &lt;code&gt;std&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int_feature    2886.89568
dtype: float64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;pandas-profiling&lt;/code&gt; is a new-ish package that creates much more detailed reports from a &lt;code&gt;DataFrame&lt;/code&gt;. You can check it out &lt;a href="https://github.com/pandas-profiling/pandas-profiling"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.size&lt;/code&gt; returns the number of observations multiplied by the number of features.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;20000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;.info&lt;/code&gt; returns metadata about the &lt;code&gt;DataFrame&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 10000 entries, 0 to 9999
Data columns (total 2 columns):
str_feature    10000 non-null object
int_feature    10000 non-null int32
dtypes: int32(1), object(1)
memory usage: 78.2+ KB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Selection and Assignment
&lt;/h2&gt;

&lt;p&gt;We tend to access data from the &lt;code&gt;DataFrame&lt;/code&gt; using the following patterns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;df[condition]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;df.iloc&lt;/code&gt; &amp;amp; &lt;code&gt;df.loc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;df.at&lt;/code&gt; &amp;amp; &lt;code&gt;df.iat&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# First pattern
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'str_feature'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'snake'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;14&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;14&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;18&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;18&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Second pattern
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="s"&gt;"int_feature"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0          0
1          1
2          2
3          3
4          4
        ... 
9995    9995
9996    9996
9997    9997
9998    9998
9999    9999
Name: int_feature, Length: 10000, dtype: int32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Note that here the lone &lt;code&gt;:&lt;/code&gt; means to access everything on that axis, the same way &lt;code&gt;my_list[:]&lt;/code&gt; tells a plain Python &lt;code&gt;list&lt;/code&gt; to access everything.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.iloc&lt;/code&gt; behaves similarly but works on axes only.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;.at&lt;/code&gt; and &lt;code&gt;.iat&lt;/code&gt; are used similarly to &lt;code&gt;.loc&lt;/code&gt; and &lt;code&gt;.iloc&lt;/code&gt; but they can't retrieve more than one observation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;df.at[0:5, 'str_feature']&lt;/code&gt; will give a &lt;code&gt;ValueError&lt;/code&gt; because of &lt;code&gt;0:5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;df.at[0]&lt;/code&gt; will give a &lt;code&gt;TypeError&lt;/code&gt; because there is no &lt;code&gt;col&lt;/code&gt; specified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'str_feature'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'snake'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There is a &lt;a href="https://stackoverflow.com/a/37216587/10553976"&gt;discussion&lt;/a&gt; on SO about how you can get some performance gains by accepting the limitations of &lt;code&gt;.at&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There's one more method I want to cover for accessing data from our &lt;code&gt;DataFrame&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;int_feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0    0
1    1
2    2
3    3
4    4
Name: int_feature, dtype: int32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This works fine until:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your feature is named &lt;code&gt;my super feature&lt;/code&gt; and you try to access &lt;code&gt;df.my super feature&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You forget that the reverse operation is illegal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's right, you cannot do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_feature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'int_feature'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c:\users\cdl\documents\personalproject\common_pandas_blog\.venv\lib\site-packages\ipykernel_launcher.py:1: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
  """Entry point for launching an IPython kernel.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Trying to will trigger a warning, at least in in newer versions of &lt;code&gt;Pandas&lt;/code&gt;. We can confirm that the feature was not added to the &lt;code&gt;DataFrame&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Instead, let's add a new feature like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'new_feature'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="s"&gt;'str_feature'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'snake'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can see that the new feature was added properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;new_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;True&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Manipulation
&lt;/h2&gt;

&lt;p&gt;Let's perform some common tasks to manipulate our data. Namely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Filter values&lt;/li&gt;
&lt;li&gt;Handle missing or invalid values&lt;/li&gt;
&lt;li&gt;SQL-like join two &lt;code&gt;DataFrame&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;SQL-like groupby&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Filtering values
&lt;/h3&gt;

&lt;p&gt;To filter values, we can simply overwrite our &lt;code&gt;df&lt;/code&gt; variable like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# We're cat people now.
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="s"&gt;'str_feature'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'cat'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;new_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;11&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;11&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Since we've just filtered our &lt;code&gt;DataFrame&lt;/code&gt; to use only use cat rows, our snakes-only &lt;code&gt;new_feature&lt;/code&gt; will be full of &lt;code&gt;False&lt;/code&gt; values and &lt;code&gt;str_feature&lt;/code&gt; will be all &lt;code&gt;cat&lt;/code&gt;s. Let's filter our columns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;"new_feature"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"str_feature"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;11&lt;/td&gt;
      &lt;td&gt;11&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As discussed &lt;a href="https://stackoverflow.com/a/18145399/10553976"&gt;here&lt;/a&gt;, the &lt;code&gt;axis&lt;/code&gt; argument tells &lt;code&gt;pandas&lt;/code&gt; to drop on the basis of the &lt;code&gt;features&lt;/code&gt; axis, and the &lt;code&gt;inplace&lt;/code&gt; argument makes this equivalent to &lt;code&gt;df = df.drop(...)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As a final note, don't make the mistake of assuming that any of these methods will automatically free up memory. Instead, use tools like Python &lt;code&gt;del&lt;/code&gt; and &lt;code&gt;pandas&lt;/code&gt; I/O features like &lt;code&gt;low_memory&lt;/code&gt; or &lt;code&gt;memory_map&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Handle missing or invalid values
&lt;/h3&gt;

&lt;p&gt;Another common data munging task is to handle cases where the data is invalid in some way. Let's make a new, messy &lt;code&gt;DataFrame&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a DataFrame with some randomized columns
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="s"&gt;"str_feature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;"dog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"snake"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="s"&gt;"int_feature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s"&gt;"messy_feature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simplest thing we could do is clean our data by filtering all observations with &lt;code&gt;np.nan&lt;/code&gt;, using &lt;code&gt;.isna&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Note the rarely used ~ negation operator below
&lt;/span&gt;&lt;span class="n"&gt;clean_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'messy_feature'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;isna&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;span class="n"&gt;clean_df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;messy_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;4134&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;4134&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2127&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;2127&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7014&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;7014&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;922&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;922&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5451&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;5451&lt;/td&gt;
      &lt;td&gt;True&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5059&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;5059&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1289&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;1289&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5016&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;5016&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9765&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;9765&lt;/td&gt;
      &lt;td&gt;True&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7094&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;7094&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As you can see, this method will clear just the &lt;code&gt;NaN&lt;/code&gt; values. That's great, but what if we only want values that are truthy in Python?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;df[df['messy_feature']]&lt;/code&gt; won't work, because it's a &lt;code&gt;ValueError&lt;/code&gt; to filter using a column with &lt;code&gt;NaN&lt;/code&gt; values. Instead, we have to filter the &lt;code&gt;NaN&lt;/code&gt;, then check for truthiness. Just like with a plain Python conditional &lt;code&gt;and&lt;/code&gt; statement, the conditions are checked left to right.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;clean_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'messy_feature'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;isna&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'messy_feature'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="n"&gt;clean_df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;messy_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1049&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;1049&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4769&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;4769&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4924&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;4924&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6907&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;6907&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5914&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;5914&lt;/td&gt;
      &lt;td&gt;True&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6291&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;6291&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5872&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;5872&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1794&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;1794&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8987&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;8987&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3848&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;3848&lt;/td&gt;
      &lt;td&gt;True&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Imputing values is easy too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;clean_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;clean_df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'messy_feature'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;fillna&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clean_df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'str_feature'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;clean_df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;messy_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;8063&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;8063&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3901&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;3901&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3702&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;3702&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;906&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;906&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8039&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;8039&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2433&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;2433&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4996&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;4996&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3015&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;3015&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8307&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;8307&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1904&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;1904&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And we can go beyond simple &lt;code&gt;.fillna&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;clean_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;clean_df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'messy_feature'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clean_df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'messy_feature'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'messy_feature'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'str_feature'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;clean_df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;messy_feature&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;9217&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;9217&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5018&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;5018&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6383&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;6383&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1297&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;1297&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9701&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;9701&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5192&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;5192&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4018&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;4018&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7619&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;7619&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9890&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;9890&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5102&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;5102&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Just be careful with &lt;code&gt;.apply&lt;/code&gt; as it has the potential to significantly degrade performance. See: &lt;a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/enhancingperf.html"&gt;enhancing performance&lt;/a&gt; in the Pandas docs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. SQL-like joins
&lt;/h3&gt;

&lt;p&gt;I would definitely recommend that you learn about SQL joins and then just map that knowledge to Pandas joins. The arguments like &lt;code&gt;on&lt;/code&gt;, &lt;code&gt;how&lt;/code&gt;, &lt;code&gt;left&lt;/code&gt;, and &lt;code&gt;right&lt;/code&gt; all make sense if you just keep in mind how the joins would work in SQL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;merged_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;how&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'left'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lsuffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_l"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rsuffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_r"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;merged_df&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature_l&lt;/th&gt;
      &lt;th&gt;int_feature_l&lt;/th&gt;
      &lt;th&gt;messy_feature_l&lt;/th&gt;
      &lt;th&gt;str_feature_r&lt;/th&gt;
      &lt;th&gt;int_feature_r&lt;/th&gt;
      &lt;th&gt;messy_feature_r&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;...&lt;/td&gt;
      &lt;td&gt;...&lt;/td&gt;
      &lt;td&gt;...&lt;/td&gt;
      &lt;td&gt;...&lt;/td&gt;
      &lt;td&gt;...&lt;/td&gt;
      &lt;td&gt;...&lt;/td&gt;
      &lt;td&gt;...&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9995&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;9995&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;9995&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9996&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;9996&lt;/td&gt;
      &lt;td&gt;True&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;9996&lt;/td&gt;
      &lt;td&gt;True&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9997&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;9997&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;9997&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9998&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;9998&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;9998&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9999&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;9999&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;9999&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;10000 rows × 6 columns&lt;/p&gt;

&lt;h3&gt;
  
  
  4. SQL-like groupby
&lt;/h3&gt;

&lt;p&gt;Like the SQL JOIN advice, I strongly recommend learning about SQL GROUP BY and letting that be the basis of your Pandas &lt;code&gt;.groupby&lt;/code&gt; knowledge. Here's a simple GROUP BY SUM in Pandas&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'str_feature'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;16476822&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;16729175&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;16789003&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note that &lt;code&gt;.groupby&lt;/code&gt; must be called by a method that aggregates the grouping. Let's see what happens if we neglect that part...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'str_feature'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;pandas.core.groupby.generic.DataFrameGroupBy object at 0x0A6F91D0&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;.groupby&lt;/code&gt; is particularly powerful when combined with the &lt;code&gt;.apply&lt;/code&gt; method...but my earlier warning about the performance of &lt;code&gt;.apply&lt;/code&gt; still holds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Simple sum/size calculation
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'str_feature'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nb"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;messy_feature&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;2485.191855&lt;/td&gt;
      &lt;td&gt;0.088688&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;2509.627213&lt;/td&gt;
      &lt;td&gt;0.086709&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;2504.326223&lt;/td&gt;
      &lt;td&gt;0.089499&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Moving Windows
&lt;/h2&gt;

&lt;p&gt;Often we want to calculate rolling values (like rolling sums):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'rolling'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rolling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;messy_feature&lt;/th&gt;
      &lt;th&gt;rolling&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;6.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt;9.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;12.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt;15.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;-1&lt;/td&gt;
      &lt;td&gt;18.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;21.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;24.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Indexing by Time
&lt;/h2&gt;

&lt;p&gt;A related task is to use datetime, which we accomplish using &lt;code&gt;pd.to_datetime&lt;/code&gt;. There are helper methods like &lt;code&gt;.astype&lt;/code&gt; for casting to datetime types, as well as &lt;code&gt;.set_index&lt;/code&gt; if we want to use a &lt;code&gt;datetime&lt;/code&gt; column as our index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'Datetime'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_datetime&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])],&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'s'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Round to nearest day
# see https://stackoverflow.com/a/13788301/10553976
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'Datetime'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'Datetime'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'datetime64[ns]'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Set as index
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Datetime'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  I/O
&lt;/h2&gt;

&lt;p&gt;One of the most attractive features of Pandas is the robust I/O capabilities. The whole list is &lt;a href="https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html"&gt;here&lt;/a&gt; but let's take a look at two important ones, CSV and SQL.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSV
&lt;/h3&gt;

&lt;p&gt;Writing a CSV in Pandas couldn't be easier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'./data.csv'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reading it back in is just as simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'./data.csv'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But wait: let's look at our &lt;code&gt;df&lt;/code&gt; now...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Datetime&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;messy_feature&lt;/th&gt;
      &lt;th&gt;rolling&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;2019-10-08 21:51:50&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;2019-10-07 21:51:50&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;2019-10-06 21:51:50&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;2019-10-05 21:51:50&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;6.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;2019-10-04 21:51:50&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;9.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We can't infer that any particular column is the index, so &lt;code&gt;.read_csv&lt;/code&gt; created a &lt;code&gt;DataFrame&lt;/code&gt; with a simple index instead of using the &lt;code&gt;DatetimeIndex&lt;/code&gt; we set before writing to a file. Of course we could always use &lt;code&gt;.set_index&lt;/code&gt; after the fact, but in resource constrained scenarios we want control of how large the created &lt;code&gt;DataFrame&lt;/code&gt; will be. Searching for a solution, we come to the &lt;code&gt;.read_csv&lt;/code&gt; &lt;a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html"&gt;documentation&lt;/a&gt; and the power of this tool immediately becomes apparent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read CSVs from URL (!!!!!), path, or file-like&lt;/li&gt;
&lt;li&gt;Specify the exact window in a CSV file to read from with kwargs like &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;index_col&lt;/code&gt;, &lt;code&gt;usecols&lt;/code&gt;, &lt;code&gt;nrows&lt;/code&gt;, &lt;code&gt;skiprows&lt;/code&gt;, and &lt;code&gt;skipfooter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Manage &lt;code&gt;NaN&lt;/code&gt; with kwargs like &lt;code&gt;na_filter&lt;/code&gt; and &lt;code&gt;na_values&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sep&lt;/code&gt; for handling &lt;code&gt;tsv&lt;/code&gt; and other delimiter situations&lt;/li&gt;
&lt;li&gt;Kwargs to help save memory like &lt;code&gt;low_memory&lt;/code&gt;, &lt;code&gt;memory_map&lt;/code&gt;, and &lt;code&gt;dtype&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Armed with tons of new knowledge about how to read csv files with Pandas, we can confidently read our &lt;code&gt;data.csv&lt;/code&gt; file with the &lt;code&gt;DatetimeIndex&lt;/code&gt; specified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'./data.csv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index_col&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'Datetime'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;messy_feature&lt;/th&gt;
      &lt;th&gt;rolling&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Datetime&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-08 21:51:50&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-07 21:51:50&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-06 21:51:50&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-05 21:51:50&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;6.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-04 21:51:50&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
      &lt;td&gt;9.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Just the way it originally was! Let's clean that file up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'./data.csv'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: if you aren't using Pandas features for data manipulation, consider using the stdlib &lt;code&gt;csv&lt;/code&gt; library for I/O instead of Pandas. Pandas objects create some overhead in memory, and Pandas itself is a nontrivial dependency.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SQL
&lt;/h3&gt;

&lt;p&gt;If you want to read and write data that lives in a SQL database, Pandas uses the &lt;code&gt;pd.read_sql&lt;/code&gt; and &lt;code&gt;.to_sql&lt;/code&gt; methods to interface with databases. In this example we'll use the stdlib &lt;code&gt;sqlite3&lt;/code&gt; dbAPI, but Pandas can integrate with any kind of DB that is supported by &lt;a href="https://www.sqlalchemy.org/"&gt;sqlalchemy&lt;/a&gt;. Also note that we're going to use a &lt;code&gt;try...finally&lt;/code&gt; block to enforce &lt;code&gt;.close&lt;/code&gt; always being called.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sqlite3&lt;/span&gt;

&lt;span class="c1"&gt;# DB operations
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Connect to db
&lt;/span&gt;    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'data.db'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Write dataframe to table 'df'
&lt;/span&gt;    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'df'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;if_exists&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'replace'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Read a SELECT * query of the same table, specifying index column
&lt;/span&gt;    &lt;span class="n"&gt;sqldf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'SELECT * FROM df'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index_col&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'Datetime'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Ensure the connection closes
&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Cleanup file
&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'data.db'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sqldf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table class="dataframe"&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;str_feature&lt;/th&gt;
      &lt;th&gt;int_feature&lt;/th&gt;
      &lt;th&gt;messy_feature&lt;/th&gt;
      &lt;th&gt;rolling&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Datetime&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-08 21:51:50&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-07 21:51:50&lt;/td&gt;
      &lt;td&gt;cat&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt;NaN&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-06 21:51:50&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;3.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-05 21:51:50&lt;/td&gt;
      &lt;td&gt;dog&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;False&lt;/td&gt;
      &lt;td&gt;6.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2019-10-04 21:51:50&lt;/td&gt;
      &lt;td&gt;snake&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt;9.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once again our data has made a round trip from memory to disk and back again. Well done Pandas and well done to you, dear reader!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;In this article you've learned how Pandas implements some basic data munging tasks, specifically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extracting metadata and descriptive statistics&lt;/li&gt;
&lt;li&gt;Filtering, imputing, joining and grouping data&lt;/li&gt;
&lt;li&gt;Windowed functions (like rolling sum)&lt;/li&gt;
&lt;li&gt;Using Datetime data and indexing by time&lt;/li&gt;
&lt;li&gt;Reading and writing data to files and databases&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Happy wrangling!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Image by &lt;a href="https://pixabay.com/photos/panda-panda-bear-sleep-rest-relax-1236875/"&gt;Cimberley&lt;/a&gt; on Pixabay&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>React useContext and Pre-Initialized Providers</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Thu, 03 Oct 2019 19:12:34 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/react-usecontext-and-pre-initialized-providers-2gn5</link>
      <guid>https://dev.to/charlesdlandau/react-usecontext-and-pre-initialized-providers-2gn5</guid>
      <description>&lt;p&gt;On a recent project I started using the &lt;a href="https://reactjs.org/docs/context.html"&gt;React Context API&lt;/a&gt; instead of Redux, and I like it. Here's how you can get started quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup a project
&lt;/h3&gt;

&lt;p&gt;I like Next for a variety of reasons, particularly the router. Let's create a new project like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init context_demo &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;context_demo
npx create-next-app
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;localhost:3000&lt;/code&gt; will now display the template app. Let's "clear the table":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/index.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/head&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The view should go blank now.&lt;/p&gt;

&lt;p&gt;With that out of the way, let's create a context in a new folder &lt;code&gt;contexts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// contexts/contextcontroller.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Dummy data&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ctxObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;lastUpdated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;nestings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;nest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;nest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;nest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;}}},&lt;/span&gt;
  &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;baz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ControlledContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

&lt;span class="c1"&gt;// A provider with all the methods and states set up for you&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;InitializedProvider&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pushFoo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="na"&gt;lastUpdated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;ctxObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;pushFoo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pushFoo&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ControlledContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ControlledContext.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ControlledContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InitializedProvider&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see all this does is pack a method into its state and pass the state to a context provider. Everything is all in one place, but we could be importing functions from all over the place if we wanted to.&lt;/p&gt;

&lt;p&gt;Let's build some consumers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/buttoneer.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ControlledContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../contexts/contextcontroller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Buttoneer&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ControlledContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pushFoo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Click&lt;/span&gt; &lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Buttoneer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one just consumes our &lt;code&gt;pushFoo&lt;/code&gt; method from the context. Now let's imitate significant nesting in the component tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/nestingdoll.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;NestingDoll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;20px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;NestingDoll&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this one just draws a box around its children. Now lets make a component that consumes the array from our context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/listview.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ControlledContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../contexts/contextcontroller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ControlledContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; 
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-listitem`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1px solid black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;20px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ListView&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these components let's edit our &lt;code&gt;index&lt;/code&gt; to render our &lt;code&gt;Buttoneer&lt;/code&gt; in one branch of the component tree, and then nest &lt;code&gt;Listview&lt;/code&gt; under several layers of &lt;code&gt;NestingDoll&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/index.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/head&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;InitializedProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../contexts/contextcontroller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Buttoneer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/buttoneer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;NestingDoll&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/nestingdoll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ListView&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/listview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Head&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InitializedProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Buttoneer&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NestingDoll&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NestingDoll&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NestingDoll&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListView&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/NestingDoll&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/NestingDoll&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/NestingDoll&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/InitializedProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result should look like it does in this demo: &lt;a href="https://controlled-context-demo.charlesdlandau.net/"&gt;controlled-context-demo.charlesdlandau.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you can see the repo &lt;a href="https://github.com/CharlesDLandau/controlled_context_demo_react"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think that this pattern improves the organization of projects because global app state is all in one place. I know that there are some drawbacks to the Contexts API (e.g. rerenders) but it works for me.&lt;/p&gt;

&lt;p&gt;Thanks for reading! I'd be interested to hear your thoughts. Is this an anti-pattern? Do you dislike the Context API and think I should just use Redux? &lt;/p&gt;

</description>
      <category>react</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>🤖➯🌩 (Machine Learning In the Cloud)</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Tue, 01 Oct 2019 14:17:14 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/machine-learning-in-the-cloud-3ni1</link>
      <guid>https://dev.to/charlesdlandau/machine-learning-in-the-cloud-3ni1</guid>
      <description>&lt;p&gt;I've been preparing a talk for my local ML user group and as a result I've had to synthesize a lot of ideas. In the talk I introduce a wide variety of "Machine Learning as a Service (MLaaS)" services and talk about how they fit in your toolkit. It's supposed to be a 45 minute talk, so the deck is pretty long... much longer than you would want for a blog post. In this post I'm going to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Summarize the heck outta this talk.&lt;/li&gt;
&lt;li&gt;Share the slides at the end.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Note: I am NOT affiliated with ANY product mentioned ANYWHERE in this post.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MLaaS...
&lt;/h2&gt;

&lt;p&gt;...because what the world really needs is another aaS right?&lt;/p&gt;

&lt;p&gt;Machine Learning as a Service is a tautology -- it's a label for any service that delivers machine learning. These services offer a variety of advantages to businesses and data scientists, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Near-State of the Art performance in some cases, without the up-front cost (e.g. training on many GPUs in parallel for many hours). Big Four firms (and their cloud plays) obviously have advantages when it comes to this space, especially in terms of their access to data. (See: &lt;a href="%5Bhttps://cloud.google.com/natural-language/%5D(https://cloud.google.com/natural-language/)"&gt;Google Natural Language&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;“No Data Science Knowledge Required” and “AutoML” services that enable rapid prototyping and other optimizations. (See: &lt;a href="https://www.h2o.ai/products/h2o-driverless-ai/%5D(https://www.h2o.ai/products/h2o-driverless-ai/)"&gt;H20 Driverless AI&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Platforms that enhance time-to-market, optimize cost, or offer simplified integrations with supporting services. (See: &lt;a href="%5Bhttps://studio.azureml.net/%5D(https://studio.azureml.net/)"&gt;Azure ML Studio&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt; APIs that map endpoints to ML behaviors like training or prediction. (See: &lt;a href="https://wit.ai"&gt;wit.ai&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Devices that embed ML capabilities (See: &lt;a href="https://gethover.com"&gt;Hover2&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Worth it?
&lt;/h2&gt;

&lt;p&gt;There are several considerations to take into account when you're evaluating MLaaS versus "rolling your own" solution:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; MLaaS can seem to offer a way to mitigate the cost of building a Data Science team. Data Scientists, Big Data Engineers, and ML Engineers attract great compensation and benefits, and building a competitive recruitment process for these teams can also be difficult.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Related note: you may avoid a lot of upfront costs with some MLaaS offerings, but per-call or per-use costs tend to bake that in.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ownership:&lt;/strong&gt; In many cases taking an MLaaS path means that you don’t fully own and control your models, or that you’re locked in to a platform. Rolling your own can mean having a greater degree of control. On the other hand, a proprietary model from a Big Four shop may be exactly what your organization wants.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rapid Prototyping:&lt;/strong&gt; MLaaS offerings can enable a low-cost rapid prototyping approach, especially for organizations that do not have a mature rapid prototyping practice (a skunkworks). In this way MLaaS can extend rather than displace data science capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Culture:&lt;/strong&gt; Many organizations seek to build not only a data science team but a "culture of innovation" of which their data science practice is a part. Having a data science team creates an in-house nexus that can advocate for itself and identify lines of business that may not be apparent to other teams.&lt;/p&gt;

&lt;p&gt;It's also worth noting that all the typical limitations of each delivery model apply:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical limitations of SaaS:&lt;/strong&gt; you only get their features when they are up (SLAs), supported (LTS), you are budgeted for them ($$$), et cetera&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical limitations of in-house production:&lt;/strong&gt; growing pains, recruitment costs, cruft...&lt;/p&gt;

&lt;h2&gt;
  
  
  Service Categories
&lt;/h2&gt;

&lt;p&gt;To give a better overview of the landscape I pulled out a few categories of services that are out there for you to use. These are &lt;strong&gt;non-exhaustive and overlapping&lt;/strong&gt; categories that map to common use cases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4jqtYEpZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://serve-md.charlesdlandau.net/img/ml_service_cats.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4jqtYEpZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://serve-md.charlesdlandau.net/img/ml_service_cats.png" alt="ml_service_cats"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. NLP Services
&lt;/h3&gt;

&lt;p&gt;NLP is an area where state of the art results are expensive, use cases may lend themselves to generic out-of-the-box solutions, and large enterprises often have better access to data than market entrants. Some services in this category include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="%5Bhttps://aws.amazon.com/comprehend/%5D(https://aws.amazon.com/comprehend/)"&gt;AWS Comprehend and Comprehend Medical&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="%5Bhttps://developers.google.com/actions/%5D(https://developers.google.com/actions/)"&gt;GCP Actions for Google Home, Web Content, and Android&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. AutoML
&lt;/h3&gt;

&lt;p&gt;AutoML and "No Data Science Required" services are developed using techniques like transfer learning, heuristics, Bayesian hyperparameter tuning, platform optimizations, and more. They're probably doing proprietary stuff that we may never even hear about. Services in this category include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="%5Bhttps://cloud.google.com/automl/%5D(https://cloud.google.com/automl/)"&gt;...AutoML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="%5Bhttps://www.ibm.com/watson%5D(https://www.ibm.com/watson)"&gt;Watson&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Services in the AutoML space also have begun trying to distinguish themselves using "explainable AI" features. These are accomplished with techniques like LIME, which perturb the inputs and use the perturbations to infer how much the model values that input towards the final prediction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UEImISmH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ansictanv2wj.cloudfront.net/figure4-99d9ea184dd35876e0dbae81f6fce038.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UEImISmH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ansictanv2wj.cloudfront.net/figure4-99d9ea184dd35876e0dbae81f6fce038.jpg" alt="frog_explanation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Image from &lt;a href="%5Bhttps://www.oreilly.com/learning/introduction-to-local-interpretable-model-agnostic-explanations-lime%5D(https://www.oreilly.com/learning/introduction-to-local-interpretable-model-agnostic-explanations-lime)"&gt;Marco Tulio Ribeiro&lt;/a&gt; and &lt;a href="https://pixabay.com/en/love-valentine-s-day-pose-heart-903178/"&gt;Pixabay&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. ML Data Services
&lt;/h3&gt;

&lt;p&gt;There's a wide world of "managed Apache" out there, for example Spark as a Service products are available at all major cloud providers. One place that's looking pretty interesting right now is data labeling, with services like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="%5Bhttps://scale.com/%5D(https://scale.com/)"&gt;Scale AI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="%5Bhttps://aws.amazon.com/sagemaker/groundtruth/%5D(https://aws.amazon.com/sagemaker/groundtruth/)"&gt;SageMaker Ground Truth&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea behind these services is to use human labelers frequently until a model can begin to infer the labels. As the model gets better at labeling the data, only the observations where the model has low confidence get referred to human labelers.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. ML as an API
&lt;/h3&gt;

&lt;p&gt;This might be the category with the greatest overlap to other categories, but it's the easiest to grasp. Any API that serves predictions or training endpoints fits in this category. Some notables include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="%5Bhttps://cloud.google.com/vision/%5D(https://cloud.google.com/vision/)"&gt;Google Vision&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="%5Bhttps://azure.microsoft.com/en-us/services/cognitive-services/personalizer/%5D(https://azure.microsoft.com/en-us/services/cognitive-services/personalizer/)"&gt;Azure Personalizer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Embedded AI
&lt;/h3&gt;

&lt;p&gt;I'm definitely stretching the definition of an "embedded system" when I use this category, but the basic idea is just devices that ship with built-in ML features, or that plug in to your devices to imbue them with ML magic. Such products include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="%5Bhttps://www.amazon.com/alexa-auto%5D(https://www.amazon.com/alexa-auto)"&gt;Alexa Auto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="%5Bhttps://store.google.com/product/google_pixel_buds%5D(https://store.google.com/product/google_pixel_buds)"&gt;Pixel Buds&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bonus: JaaS
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0tyxX_2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://serve-md.charlesdlandau.net/img/jaas_examples.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0tyxX_2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://serve-md.charlesdlandau.net/img/jaas_examples.png" alt="jaas_examples"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jupyter as a Service products like Google Colab and Datalore have been around for a long time now, so if you haven't checked them out yet, then now's the time. They're very mature web applications that act like a REPL on steriods. They don't replace an IDE, but have some great features and can be a great option for when you don't actually &lt;em&gt;need&lt;/em&gt; a full-fledged IDE. Tools like &lt;a href="%5Bhttps://jupyter.org/hub%5D(https://jupyter.org/hub)"&gt;JupyterHub&lt;/a&gt; that host and provide compute instances to Jupyter web clients can create a unified experience with reproducible experiments available alongside their documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slides
&lt;/h2&gt;

&lt;p&gt;If you'd like to see the whole deck, complete with notes, &lt;a href="https://docs.google.com/presentation/d/e/2PACX-1vSAasYe8juHia_Q1uWp_LelK0YXHwyuFhfVxZ_hEDzYIj6h2d6P8wFkLqgBIm-t_6KK6K8RgNaSwrzi/pub?start=false&amp;amp;loop=false&amp;amp;delayms=3000"&gt;here you go!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll be giving this talk for the first time in a couple weeks so I reserve the right to have errors in the slides. If you have any feedback I'd love it if you share that with me.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>🤖➡🌜 (Teach Bots to Land on the Moon)</title>
      <dc:creator>Charles Landau</dc:creator>
      <pubDate>Tue, 24 Sep 2019 02:30:51 +0000</pubDate>
      <link>https://dev.to/charlesdlandau/teach-bots-to-land-on-the-moon-27m9</link>
      <guid>https://dev.to/charlesdlandau/teach-bots-to-land-on-the-moon-27m9</guid>
      <description>&lt;p&gt;&lt;a href="https://colab.research.google.com/github/CharlesDLandau/rlNotebooks/blob/master/botsToTheMoon.ipynb" rel="noopener noreferrer"&gt;Tinker with this notebook in Google Colab&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/CharlesDLandau/rlNotebooks" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the past few episodes we've gone over design princples for reinforcement learning, introduced reinforcement learning with OpenAI Gym, and trained a deep learning model to navigate an OpenAI Gym environment. To accomplish this, we leveraged the agent-environment relationship:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The agent takes actions in the environment. These can be random, or guided by heuristics, or by a model, or some combination. It recieves data about the environment, like a picture of the environment or a string, and then it takes an action. Afterwards, it recieves a reward from the environment, which amount to positive or negative "reinforcement" of the selected behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The environment tracks the state, possible actions, rewards and &lt;strong&gt;reward function&lt;/strong&gt;, and optionally renders the environment to a display. It receives actions from the agent, and it can be configured to persist data (e.g. a video of the agent performing in the environment.)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Better Agents
&lt;/h4&gt;

&lt;p&gt;In previous episodes we also implemented some janky, simplistic reinforcement learning. Without convolutional layers or a policy engine the network could only learn simplistic strategies (like &lt;a href="https://dev.to/charlesdlandau/drive-a-tank-with-python-3caf"&gt;turn left&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;To solve this without reinventing the wheel we can use libraries like &lt;a href="https://github.com/tensorflow/agents" rel="noopener noreferrer"&gt;Tensorflow Agents&lt;/a&gt;, or &lt;a href="https://github.com/openai/baselines" rel="noopener noreferrer"&gt;OpenAI Baselines&lt;/a&gt; which have some battle-tested implementations of the most successful agents. I've worked with a few of these libraries and I mostly came to the same conclusions as this &lt;a href="https://medium.com/data-from-the-trenches/choosing-a-deep-reinforcement-learning-library-890fb0307092" rel="noopener noreferrer"&gt;excellent article&lt;/a&gt; by Thomas Simonini. Namely, I like &lt;a href="https://github.com/hill-a/stable-baselines" rel="noopener noreferrer"&gt;Stable Baselines&lt;/a&gt;, a fork of the OpenAI Baselines library.&lt;/p&gt;

&lt;h4&gt;
  
  
  Getting Ready
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthumbs.gfycat.com%2FGorgeousUnfortunateAndalusianhorse-size_restricted.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthumbs.gfycat.com%2FGorgeousUnfortunateAndalusianhorse-size_restricted.gif" alt="Getting Ready"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting up Google Colab with Stable Baselines and its dependencies, and figuring out how to get gifs working, took me longer than I would have liked. You do it with the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# see: colab.research.google.com/drive/1GLlB53gvZaUyqMYv8GmZQJmshRUzV_tg
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;qq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;libcusparse8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;libnvrtc8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;libnvtoolsext1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;
&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ln&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;snf&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x86_64&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gnu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;libnvrtc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;builtins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;x86_64&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gnu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;libnvrtc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;builtins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;so&lt;/span&gt;
&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;qq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;xvfb&lt;/span&gt; &lt;span class="n"&gt;freeglut3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="n"&gt;ffmpeg&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;

&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;stable&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;baselines&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;2.7&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="c1"&gt;# box2d fork until SWIG dependency is replaced
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;box2d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;

&lt;span class="c1"&gt;# pyglet later versions break gym apparently
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;pyglet&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;1.3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="c1"&gt;# Set up display; otherwise rendering will fail for
# classic control type envs, apparently
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Box2D&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pyglet&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Xvfb :1 -screen 0 1024x768x24 &amp;amp;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DISPLAY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;:1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;


&lt;span class="c1"&gt;# See https://github.com/ipython/ipython/issues/10045#issuecomment-522697219
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;IPython.core.interactiveshell&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;InteractiveShell&lt;/span&gt;
&lt;span class="n"&gt;InteractiveShell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ast_node_interactivity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;IPython&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that out of the way, you can implement a high-quality Advantage Actor Critic (A2C) model in just two lines. Simple Baselines is great because it has intuitive methods for training and predicting. Even better, it stores our enviornment as a &lt;code&gt;model.env&lt;/code&gt; member, so all we need for typical workflows is a &lt;code&gt;model&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;Let's train -- The following takes a fair bit of time to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;stable_baselines&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;A2C&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Train a multilayer perceptron in the lunar lander.
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;A2C&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MlpPolicy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LunarLander-v2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;learn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;900000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Mine finished in about 10 minutes.
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Finished in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  An actor and a critic walk into a bar.
&lt;/h3&gt;

&lt;p&gt;While that runs, let's talk about the Actor-Critic paradigm. The problem Actor-Critic solves involves none other than our reward function. In many cases the rewards only happen at the end of an "episode" AKA a "game." Consider a reward function for tic-tac-toe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return 0 during play&lt;/li&gt;
&lt;li&gt;Return 0 if game ends in a tie&lt;/li&gt;
&lt;li&gt;Return -1.0 if game ends in a loss for the agent&lt;/li&gt;
&lt;li&gt;Return 1.0 if game ends in a win for the agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, our agent is taking several steps each episode which recieve no feedback at all from the reward function, slowing training and making it difficult to give fine-grained feedback to our agent about specific actions. To solve this, Actor-Critic actually implements two models:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; A Critic model that tries to predict reward values that a given action will earn, given an observation about the environment. The table of predicted reward values for action-observation pairs is sometimes called a "Q table."&lt;/li&gt;
&lt;li&gt; An Actor model that takes observations from the environment, but not rewards. It learns a strategy for playing in the environment, AKA a "policy." Instead of optimizing on the environment's rewards directly, this model optimizes on &lt;em&gt;feedback from the critic model&lt;/em&gt;. When we do predictions, just the Actor model needs to be called.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can easily imagine our Actor model in the lunar lander module, while the Critic sits in the command center observing the lander's actions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthumbs.gfycat.com%2FFlawlessWhichAdamsstaghornedbeetle-size_restricted.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthumbs.gfycat.com%2FFlawlessWhichAdamsstaghornedbeetle-size_restricted.gif" alt="the critic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each time an action is taken the Critic consults a table of actions, angles, speeds, and so on. Seeing whether the action will contribute to a successful landing, the Critic radios over to the Actor with feedback about the action, and the Actor learns to be a better pilot from the feedback. Over the course of thousands of landings, the Critic updates the table frequently based on crashes, successes, and surprises. Some days, the Actor flies with the radio turned off, but it doesn't learn anything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Record a GIF of the landing
&lt;/h3&gt;

&lt;p&gt;By now your model might be done training. Per the docs, here's how we record a gif of our model in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;imageio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="c1"&gt;# Number of images to capture
&lt;/span&gt;&lt;span class="n"&gt;n_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;

&lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="c1"&gt;# init a new episode
&lt;/span&gt;&lt;span class="n"&gt;obs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# init the img var with the starting state of the env
&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rgb_array&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_images&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="c1"&gt;# At each step, append an image to list
&lt;/span&gt;  &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Advance a step and render a new image
&lt;/span&gt;  &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rgb_array&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;imageio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mimwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./lander.gif&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="n"&gt;fps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're successful then &lt;code&gt;lander.gif&lt;/code&gt; should look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fserve-md.charlesdlandau.net%2Fimg%2Flander.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fserve-md.charlesdlandau.net%2Fimg%2Flander.gif" alt="lander.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Displaying gifs in Jupyter is a little counterintuitive, here's how I do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="n"&gt;gifPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lander.gif&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Display GIF in Jupyter, CoLab, IPython
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gifPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrapping Up...
&lt;/h3&gt;

&lt;p&gt;In this episode you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learned about Actor-Critic&lt;/li&gt;
&lt;li&gt;Learned about Simple Baselines&lt;/li&gt;
&lt;li&gt;Saw how to setup giffing the environments in a notebook&lt;/li&gt;
&lt;li&gt;Landed on the moon!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthumbs.gfycat.com%2FPerfumedBelatedBlowfish-size_restricted.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthumbs.gfycat.com%2FPerfumedBelatedBlowfish-size_restricted.gif" alt="goodjob.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Way to go!&lt;/p&gt;

&lt;p&gt;In future episodes we'll take a closer look at how RL can create value for users, businesses, and robot overlords. Stay tuned and thanks for reading.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>tutorial</category>
      <category>python</category>
      <category>datascience</category>
    </item>
  </channel>
</rss>
