From 3b85406fe0a94b1e80266a863cd87df41c313f59 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Thu, 15 Oct 2026 23:05:21 -0700 Subject: [PATCH 01/17] Ch.6 to polars - .rename requires a dictionary, will we be teaching this? - POLARS_CHANGE for the PercentFormatter --- chapters/06/Tables.ipynb | 1407 +++++++++++++++++--------------------- 1 file changed, 623 insertions(+), 784 deletions(-) diff --git a/chapters/06/Tables.ipynb b/chapters/06/Tables.ipynb index cdb0b9f24..cb0fcc359 100644 --- a/chapters/06/Tables.ipynb +++ b/chapters/06/Tables.ipynb @@ -4,13 +4,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Tables\n", + "# DataFrames\n", "\n", - "Tables are a fundamental object type for representing data sets. A table can be viewed in two ways:\n", + "DataFrames are a fundamental object type for representing data sets. A DataFrame can be viewed in two ways:\n", "* a sequence of named columns that each describe a single aspect of all entries in a data set, or\n", "* a sequence of rows that each contain all information about a single entry in a data set.\n", "\n", - "In order to use tables, import all of the module called `datascience`, a module created for this text." + "In order to use DataFrames, import the module called `polars`." ] }, { @@ -23,215 +23,199 @@ }, "outputs": [], "source": [ - "import numpy as np\n", - "np.set_printoptions(threshold=50)\n", + "import polars as pl\n", "path_data = '../../assets/data/'" ] }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from datascience import *" - ] - }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Empty tables can be created using the `Table` function. An empty table is useful because it can be extended to contain new rows and columns." + "Empty DataFrames can be created using `pl.DataFrame`. An empty DataFrame is useful because it can be extended to contain new rows and columns." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 2, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
" + "text/plain": [ + "shape: (0, 0)\n", + "┌┐\n", + "╞╡\n", + "└┘" ], - "text/plain": [] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" + "text/html": [ + "
\n", + "shape: (0, 0)
" + ] + } } ], "source": [ - "Table()" + "pl.DataFrame()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The `with_columns` method on a table constructs a new table with additional labeled columns. Each column of a table is an array. To add one new column to a table, call `with_columns` with a label and an array. (The `with_column` method can be used with the same effect.)\n", + "A DataFrame is built from named columns. Each column is a Polars Series. To create a DataFrame with one column, pass a Series to `pl.DataFrame`.\n", "\n", - "Below, we begin each example with an empty table that has no columns. " + "Below, we begin each example with a DataFrame that has one column." ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 3, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Number of petals
8
34
5
" - ], "text/plain": [ - "Number of petals\n", - "8\n", - "34\n", - "5" + "shape: (3, 1)\n", + "┌──────────────────┐\n", + "│ Number of petals │\n", + "│ --- │\n", + "│ i64 │\n", + "╞══════════════════╡\n", + "│ 8 │\n", + "│ 34 │\n", + "│ 5 │\n", + "└──────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (3, 1)
Number of petals
i64
8
34
5
" ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "Table().with_columns('Number of petals', make_array(8, 34, 5))" + "pl.DataFrame([\n", + " pl.Series(\"Number of petals\", [8, 34, 5])\n", + "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "To add two (or more) new columns, provide the label and array for each column. All columns must have the same length, or an error will occur." + "To add two (or more) new columns, pass a Polars Series for each column. All columns must have the same length, or an error will occur." ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 4, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Number of petals Name
8 lotus
34 sunflower
5 rose
" - ], "text/plain": [ - "Number of petals | Name\n", - "8 | lotus\n", - "34 | sunflower\n", - "5 | rose" + "shape: (3, 2)\n", + "┌──────────────────┬───────────┐\n", + "│ Number of petals ┆ Name │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ str │\n", + "╞══════════════════╪═══════════╡\n", + "│ 8 ┆ lotus │\n", + "│ 34 ┆ sunflower │\n", + "│ 5 ┆ rose │\n", + "└──────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (3, 2)
Number of petalsName
i64str
8"lotus"
34"sunflower"
5"rose"
" ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "Table().with_columns(\n", - " 'Number of petals', make_array(8, 34, 5),\n", - " 'Name', make_array('lotus', 'sunflower', 'rose')\n", - ")" + "pl.DataFrame([\n", + " pl.Series(\"Number of petals\", [8, 34, 5]),\n", + " pl.Series(\"Name\", [\"lotus\", \"sunflower\", \"rose\"]),\n", + "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We can give this table a name, and then extend the table with another column." + "We can give this DataFrame a name, and then extend the DataFrame with another column." ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 5, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Number of petals Name Color
8 lotus pink
34 sunflower yellow
5 rose red
" - ], "text/plain": [ - "Number of petals | Name | Color\n", - "8 | lotus | pink\n", - "34 | sunflower | yellow\n", - "5 | rose | red" + "shape: (3, 3)\n", + "┌──────────────────┬───────────┬────────┐\n", + "│ Number of petals ┆ Name ┆ Color │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ str ┆ str │\n", + "╞══════════════════╪═══════════╪════════╡\n", + "│ 8 ┆ lotus ┆ pink │\n", + "│ 34 ┆ sunflower ┆ yellow │\n", + "│ 5 ┆ rose ┆ red │\n", + "└──────────────────┴───────────┴────────┘" + ], + "text/html": [ + "
\n", + "shape: (3, 3)
Number of petalsNameColor
i64strstr
8"lotus""pink"
34"sunflower""yellow"
5"rose""red"
" ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "flowers = Table().with_columns(\n", - " 'Number of petals', make_array(8, 34, 5),\n", - " 'Name', make_array('lotus', 'sunflower', 'rose')\n", - ")\n", + "flowers = pl.DataFrame([\n", + " pl.Series(\"Number of petals\", [8, 34, 5]),\n", + " pl.Series(\"Name\", [\"lotus\", \"sunflower\", \"rose\"]),\n", + "])\n", "\n", "flowers.with_columns(\n", - " 'Color', make_array('pink', 'yellow', 'red')\n", + " pl.Series(\"Color\", [\"pink\", \"yellow\", \"red\"])\n", ")" ] }, @@ -239,46 +223,42 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The `with_columns` method creates a new table each time it is called, so the original table is not affected. For example, the table `flowers` still has only the two columns that it had when it was created." + "The `with_columns` method creates a new DataFrame each time it is called, so the original DataFrame is not affected. For example, the DataFrame `flowers` still has only the two columns that it had when it was created." ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 6, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Number of petals Name
8 lotus
34 sunflower
5 rose
" - ], "text/plain": [ - "Number of petals | Name\n", - "8 | lotus\n", - "34 | sunflower\n", - "5 | rose" + "shape: (3, 2)\n", + "┌──────────────────┬───────────┐\n", + "│ Number of petals ┆ Name │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ str │\n", + "╞══════════════════╪═══════════╡\n", + "│ 8 ┆ lotus │\n", + "│ 34 ┆ sunflower │\n", + "│ 5 ┆ rose │\n", + "└──────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (3, 2)
Number of petalsName
i64str
8"lotus"
34"sunflower"
5"rose"
" ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -289,74 +269,57 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Creating tables in this way involves a lot of typing. If the data have already been entered somewhere, it is usually possible to use Python to read it into a table, instead of typing it all in cell by cell.\n", + "Creating DataFrames in this way involves a lot of typing. If the data have already been entered somewhere, it is usually possible to use Python to read it into a DataFrame, instead of typing it all in cell by cell.\n", + "\n", + "Often, DataFrames are created from files that contain comma-separated values. Such files are called CSV files.\n", "\n", - "Often, tables are created from files that contain comma-separated values. Such files are called CSV files.\n", + "Below, we use `pl.read_csv` to read a CSV file that contains some of the data used by Minard in his graphic about Napoleon's Russian campaign. The data are placed in a DataFrame named `minard`.\n", "\n", - "Below, we use the Table method `read_table` to read a CSV file that contains some of the data used by Minard in his graphic about Napoleon's Russian campaign. The data are placed in a table named `minard`." + "POLARS_CHANGE: This file separates rows with carriage returns, so `read_csv` is given `eol_char=\"\\r\"`." ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 7, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Longitude Latitude City Direction Survivors
32 54.8 Smolensk Advance 145000
33.2 54.9 Dorogobouge Advance 140000
34.4 55.5 Chjat Advance 127100
37.6 55.8 Moscou Advance 100000
34.3 55.2 Wixma Retreat 55000
32 54.6 Smolensk Retreat 24000
30.4 54.4 Orscha Retreat 20000
26.8 54.3 Moiodexno Retreat 12000
" - ], "text/plain": [ - "Longitude | Latitude | City | Direction | Survivors\n", - "32 | 54.8 | Smolensk | Advance | 145000\n", - "33.2 | 54.9 | Dorogobouge | Advance | 140000\n", - "34.4 | 55.5 | Chjat | Advance | 127100\n", - "37.6 | 55.8 | Moscou | Advance | 100000\n", - "34.3 | 55.2 | Wixma | Retreat | 55000\n", - "32 | 54.6 | Smolensk | Retreat | 24000\n", - "30.4 | 54.4 | Orscha | Retreat | 20000\n", - "26.8 | 54.3 | Moiodexno | Retreat | 12000" + "shape: (8, 5)\n", + "┌───────────┬──────────┬─────────────┬───────────┬───────────┐\n", + "│ Longitude ┆ Latitude ┆ City ┆ Direction ┆ Survivors │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ f64 ┆ f64 ┆ str ┆ str ┆ i64 │\n", + "╞═══════════╪══════════╪═════════════╪═══════════╪═══════════╡\n", + "│ 32.0 ┆ 54.8 ┆ Smolensk ┆ Advance ┆ 145000 │\n", + "│ 33.2 ┆ 54.9 ┆ Dorogobouge ┆ Advance ┆ 140000 │\n", + "│ 34.4 ┆ 55.5 ┆ Chjat ┆ Advance ┆ 127100 │\n", + "│ 37.6 ┆ 55.8 ┆ Moscou ┆ Advance ┆ 100000 │\n", + "│ 34.3 ┆ 55.2 ┆ Wixma ┆ Retreat ┆ 55000 │\n", + "│ 32.0 ┆ 54.6 ┆ Smolensk ┆ Retreat ┆ 24000 │\n", + "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 │\n", + "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 │\n", + "└───────────┴──────────┴─────────────┴───────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 5)
LongitudeLatitudeCityDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard = Table.read_table(path_data + 'minard.csv')\n", + "minard = pl.read_csv(path_data + 'minard.csv', eol_char='\\r')\n", "minard" ] }, @@ -364,56 +327,56 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We will use this small table to demonstrate some useful Table methods. We will then use those same methods, and develop other methods, on much larger tables of data." + "We will use this small DataFrame to demonstrate some useful DataFrame methods. We will then use those same methods, and develop other methods, on much larger DataFrames of data." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "**The Size of the Table**\n", + "**The Size of the DataFrame**\n", "\n", - "The method `num_columns` gives the number of columns in the table, and `num_rows` the number of rows." + "The attribute `width` gives the number of columns in the DataFrame, and `height` the number of rows." ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 8, + "metadata": {}, "data": { "text/plain": [ "5" ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.num_columns" + "minard.width" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 9, + "metadata": {}, "data": { "text/plain": [ "8" ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.num_rows" + "minard.height" ] }, { @@ -422,163 +385,125 @@ "source": [ "**Column Labels**\n", "\n", - "The method `labels` can be used to list the labels of all the columns. With `minard` we don't gain much by this, but it can be very useful for tables that are so large that not all columns are visible on the screen." + "The attribute `columns` lists the names of all the columns. With `minard` we don't gain much by this, but it can be very useful for DataFrames that are so large that not all columns are visible on the screen." ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 10, + "metadata": {}, "data": { "text/plain": [ - "('Longitude', 'Latitude', 'City', 'Direction', 'Survivors')" + "['Longitude', 'Latitude', 'City', 'Direction', 'Survivors']" ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.labels" + "minard.columns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We can change column labels using the `relabeled` method. This creates a new table and leaves `minard` unchanged." + "We can change column labels using the `rename` method. This creates a new DataFrame and leaves `minard` unchanged." ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 11, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Longitude Latitude City Name Direction Survivors
32 54.8 Smolensk Advance 145000
33.2 54.9 Dorogobouge Advance 140000
34.4 55.5 Chjat Advance 127100
37.6 55.8 Moscou Advance 100000
34.3 55.2 Wixma Retreat 55000
32 54.6 Smolensk Retreat 24000
30.4 54.4 Orscha Retreat 20000
26.8 54.3 Moiodexno Retreat 12000
" - ], "text/plain": [ - "Longitude | Latitude | City Name | Direction | Survivors\n", - "32 | 54.8 | Smolensk | Advance | 145000\n", - "33.2 | 54.9 | Dorogobouge | Advance | 140000\n", - "34.4 | 55.5 | Chjat | Advance | 127100\n", - "37.6 | 55.8 | Moscou | Advance | 100000\n", - "34.3 | 55.2 | Wixma | Retreat | 55000\n", - "32 | 54.6 | Smolensk | Retreat | 24000\n", - "30.4 | 54.4 | Orscha | Retreat | 20000\n", - "26.8 | 54.3 | Moiodexno | Retreat | 12000" + "shape: (8, 5)\n", + "┌───────────┬──────────┬─────────────┬───────────┬───────────┐\n", + "│ Longitude ┆ Latitude ┆ City Name ┆ Direction ┆ Survivors │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ f64 ┆ f64 ┆ str ┆ str ┆ i64 │\n", + "╞═══════════╪══════════╪═════════════╪═══════════╪═══════════╡\n", + "│ 32.0 ┆ 54.8 ┆ Smolensk ┆ Advance ┆ 145000 │\n", + "│ 33.2 ┆ 54.9 ┆ Dorogobouge ┆ Advance ┆ 140000 │\n", + "│ 34.4 ┆ 55.5 ┆ Chjat ┆ Advance ┆ 127100 │\n", + "│ 37.6 ┆ 55.8 ┆ Moscou ┆ Advance ┆ 100000 │\n", + "│ 34.3 ┆ 55.2 ┆ Wixma ┆ Retreat ┆ 55000 │\n", + "│ 32.0 ┆ 54.6 ┆ Smolensk ┆ Retreat ┆ 24000 │\n", + "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 │\n", + "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 │\n", + "└───────────┴──────────┴─────────────┴───────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 5)
LongitudeLatitudeCity NameDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.relabeled('City', 'City Name')" + "minard.rename({\"City\": \"City Name\"})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "However, this method does not change the original table. " + "However, this method does not change the original DataFrame." ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 12, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Longitude Latitude City Direction Survivors
32 54.8 Smolensk Advance 145000
33.2 54.9 Dorogobouge Advance 140000
34.4 55.5 Chjat Advance 127100
37.6 55.8 Moscou Advance 100000
34.3 55.2 Wixma Retreat 55000
32 54.6 Smolensk Retreat 24000
30.4 54.4 Orscha Retreat 20000
26.8 54.3 Moiodexno Retreat 12000
" - ], "text/plain": [ - "Longitude | Latitude | City | Direction | Survivors\n", - "32 | 54.8 | Smolensk | Advance | 145000\n", - "33.2 | 54.9 | Dorogobouge | Advance | 140000\n", - "34.4 | 55.5 | Chjat | Advance | 127100\n", - "37.6 | 55.8 | Moscou | Advance | 100000\n", - "34.3 | 55.2 | Wixma | Retreat | 55000\n", - "32 | 54.6 | Smolensk | Retreat | 24000\n", - "30.4 | 54.4 | Orscha | Retreat | 20000\n", - "26.8 | 54.3 | Moiodexno | Retreat | 12000" + "shape: (8, 5)\n", + "┌───────────┬──────────┬─────────────┬───────────┬───────────┐\n", + "│ Longitude ┆ Latitude ┆ City ┆ Direction ┆ Survivors │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ f64 ┆ f64 ┆ str ┆ str ┆ i64 │\n", + "╞═══════════╪══════════╪═════════════╪═══════════╪═══════════╡\n", + "│ 32.0 ┆ 54.8 ┆ Smolensk ┆ Advance ┆ 145000 │\n", + "│ 33.2 ┆ 54.9 ┆ Dorogobouge ┆ Advance ┆ 140000 │\n", + "│ 34.4 ┆ 55.5 ┆ Chjat ┆ Advance ┆ 127100 │\n", + "│ 37.6 ┆ 55.8 ┆ Moscou ┆ Advance ┆ 100000 │\n", + "│ 34.3 ┆ 55.2 ┆ Wixma ┆ Retreat ┆ 55000 │\n", + "│ 32.0 ┆ 54.6 ┆ Smolensk ┆ Retreat ┆ 24000 │\n", + "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 │\n", + "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 │\n", + "└───────────┴──────────┴─────────────┴───────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 5)
LongitudeLatitudeCityDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -589,70 +514,51 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "A common pattern is to assign the original name `minard` to the new table, so that all future uses of `minard` will refer to the relabeled table." + "A common pattern is to assign the original name `minard` to the new DataFrame, so that all future uses of `minard` will refer to the renamed DataFrame." ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 13, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Longitude Latitude City Name Direction Survivors
32 54.8 Smolensk Advance 145000
33.2 54.9 Dorogobouge Advance 140000
34.4 55.5 Chjat Advance 127100
37.6 55.8 Moscou Advance 100000
34.3 55.2 Wixma Retreat 55000
32 54.6 Smolensk Retreat 24000
30.4 54.4 Orscha Retreat 20000
26.8 54.3 Moiodexno Retreat 12000
" - ], "text/plain": [ - "Longitude | Latitude | City Name | Direction | Survivors\n", - "32 | 54.8 | Smolensk | Advance | 145000\n", - "33.2 | 54.9 | Dorogobouge | Advance | 140000\n", - "34.4 | 55.5 | Chjat | Advance | 127100\n", - "37.6 | 55.8 | Moscou | Advance | 100000\n", - "34.3 | 55.2 | Wixma | Retreat | 55000\n", - "32 | 54.6 | Smolensk | Retreat | 24000\n", - "30.4 | 54.4 | Orscha | Retreat | 20000\n", - "26.8 | 54.3 | Moiodexno | Retreat | 12000" + "shape: (8, 5)\n", + "┌───────────┬──────────┬─────────────┬───────────┬───────────┐\n", + "│ Longitude ┆ Latitude ┆ City Name ┆ Direction ┆ Survivors │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ f64 ┆ f64 ┆ str ┆ str ┆ i64 │\n", + "╞═══════════╪══════════╪═════════════╪═══════════╪═══════════╡\n", + "│ 32.0 ┆ 54.8 ┆ Smolensk ┆ Advance ┆ 145000 │\n", + "│ 33.2 ┆ 54.9 ┆ Dorogobouge ┆ Advance ┆ 140000 │\n", + "│ 34.4 ┆ 55.5 ┆ Chjat ┆ Advance ┆ 127100 │\n", + "│ 37.6 ┆ 55.8 ┆ Moscou ┆ Advance ┆ 100000 │\n", + "│ 34.3 ┆ 55.2 ┆ Wixma ┆ Retreat ┆ 55000 │\n", + "│ 32.0 ┆ 54.6 ┆ Smolensk ┆ Retreat ┆ 24000 │\n", + "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 │\n", + "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 │\n", + "└───────────┴──────────┴─────────────┴───────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 5)
LongitudeLatitudeCity NameDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard = minard.relabeled('City', 'City Name')\n", + "minard = minard.rename({\"City\": \"City Name\"})\n", "minard" ] }, @@ -662,27 +568,48 @@ "source": [ "**Accessing the Data in a Column**\n", "\n", - "We can use a column's label to access the array of data in the column." + "We can use a column's label to access the Polars Series of data in the column." ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 14, + "metadata": {}, "data": { "text/plain": [ - "array([145000, 140000, 127100, 100000, 55000, 24000, 20000, 12000])" + "shape: (8,)\n", + "Series: 'Survivors' [i64]\n", + "[\n", + "\t145000\n", + "\t140000\n", + "\t127100\n", + "\t100000\n", + "\t55000\n", + "\t24000\n", + "\t20000\n", + "\t12000\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (8,)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.column('Survivors')" + "minard.get_column(\"Survivors\")" ] }, { @@ -694,69 +621,90 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 15, + "metadata": {}, "data": { "text/plain": [ - "array([145000, 140000, 127100, 100000, 55000, 24000, 20000, 12000])" + "shape: (8,)\n", + "Series: 'Survivors' [i64]\n", + "[\n", + "\t145000\n", + "\t140000\n", + "\t127100\n", + "\t100000\n", + "\t55000\n", + "\t24000\n", + "\t20000\n", + "\t12000\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (8,)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.column(4)" + "minard.to_series(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The 8 items in the array are indexed 0, 1, 2, and so on, up to 7. The items in the column can be accessed using `item`, as with any array." + "The 8 items in the Polars Series are indexed 0, 1, 2, and so on, up to 7. The items in the column can be accessed using `item`." ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 16, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 16, + "metadata": {}, "data": { "text/plain": [ "145000" ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.column(4).item(0)" + "minard.to_series(4).item(0)" ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 17, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 17, + "metadata": {}, "data": { "text/plain": [ "24000" ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.column(4).item(5)" + "minard.to_series(4).item(5)" ] }, { @@ -765,72 +713,53 @@ "source": [ "**Working with the Data in a Column**\n", "\n", - "Because columns are arrays, we can use array operations on them to discover new information. For example, we can create a new column that contains the percent of all survivors at each city after Smolensk." + "Because columns are Polars Series, we can use Series operations on them to discover new information. For example, we can create a new column that contains the percent of all survivors at each city after Smolensk." ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 18, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 18, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Longitude Latitude City Name Direction Survivors Percent Surviving
32 54.8 Smolensk Advance 145000 1
33.2 54.9 Dorogobouge Advance 140000 0.965517
34.4 55.5 Chjat Advance 127100 0.876552
37.6 55.8 Moscou Advance 100000 0.689655
34.3 55.2 Wixma Retreat 55000 0.37931
32 54.6 Smolensk Retreat 24000 0.165517
30.4 54.4 Orscha Retreat 20000 0.137931
26.8 54.3 Moiodexno Retreat 12000 0.0827586
" - ], "text/plain": [ - "Longitude | Latitude | City Name | Direction | Survivors | Percent Surviving\n", - "32 | 54.8 | Smolensk | Advance | 145000 | 1\n", - "33.2 | 54.9 | Dorogobouge | Advance | 140000 | 0.965517\n", - "34.4 | 55.5 | Chjat | Advance | 127100 | 0.876552\n", - "37.6 | 55.8 | Moscou | Advance | 100000 | 0.689655\n", - "34.3 | 55.2 | Wixma | Retreat | 55000 | 0.37931\n", - "32 | 54.6 | Smolensk | Retreat | 24000 | 0.165517\n", - "30.4 | 54.4 | Orscha | Retreat | 20000 | 0.137931\n", - "26.8 | 54.3 | Moiodexno | Retreat | 12000 | 0.0827586" + "shape: (8, 6)\n", + "┌───────────┬──────────┬─────────────┬───────────┬───────────┬───────────────────┐\n", + "│ Longitude ┆ Latitude ┆ City Name ┆ Direction ┆ Survivors ┆ Percent Surviving │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ f64 ┆ f64 ┆ str ┆ str ┆ i64 ┆ f64 │\n", + "╞═══════════╪══════════╪═════════════╪═══════════╪═══════════╪═══════════════════╡\n", + "│ 32.0 ┆ 54.8 ┆ Smolensk ┆ Advance ┆ 145000 ┆ 1.0 │\n", + "│ 33.2 ┆ 54.9 ┆ Dorogobouge ┆ Advance ┆ 140000 ┆ 0.965517 │\n", + "│ 34.4 ┆ 55.5 ┆ Chjat ┆ Advance ┆ 127100 ┆ 0.876552 │\n", + "│ 37.6 ┆ 55.8 ┆ Moscou ┆ Advance ┆ 100000 ┆ 0.689655 │\n", + "│ 34.3 ┆ 55.2 ┆ Wixma ┆ Retreat ┆ 55000 ┆ 0.37931 │\n", + "│ 32.0 ┆ 54.6 ┆ Smolensk ┆ Retreat ┆ 24000 ┆ 0.165517 │\n", + "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 ┆ 0.137931 │\n", + "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 ┆ 0.082759 │\n", + "└───────────┴──────────┴─────────────┴───────────┴───────────┴───────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 6)
LongitudeLatitudeCity NameDirectionSurvivorsPercent Surviving
f64f64strstri64f64
32.054.8"Smolensk""Advance"1450001.0
33.254.9"Dorogobouge""Advance"1400000.965517
34.455.5"Chjat""Advance"1271000.876552
37.655.8"Moscou""Advance"1000000.689655
34.355.2"Wixma""Retreat"550000.37931
32.054.6"Smolensk""Retreat"240000.165517
30.454.4"Orscha""Retreat"200000.137931
26.854.3"Moiodexno""Retreat"120000.082759
" ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "initial = minard.column('Survivors').item(0)\n", + "initial = minard.get_column(\"Survivors\").item(0)\n", "minard = minard.with_columns(\n", - " 'Percent Surviving', minard.column('Survivors')/initial\n", + " (pl.col(\"Survivors\") / initial).alias(\"Percent Surviving\")\n", ")\n", "minard" ] @@ -839,70 +768,54 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To make the proportions in the new columns appear as percents, we can use the method `set_format` with the option `PercentFormatter`. The `set_format` method takes `Formatter` objects, which exist for dates (`DateFormatter`), currencies (`CurrencyFormatter`), numbers, and percentages." + "To make the proportions in the new column appear as percents, multiply by 100, round to two decimal places, and append a percent sign. `with_columns` returns a new DataFrame, so the result is assigned back to `minard`." ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 19, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 19, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Longitude Latitude City Name Direction Survivors Percent Surviving
32 54.8 Smolensk Advance 145000 100.00%
33.2 54.9 Dorogobouge Advance 140000 96.55%
34.4 55.5 Chjat Advance 127100 87.66%
37.6 55.8 Moscou Advance 100000 68.97%
34.3 55.2 Wixma Retreat 55000 37.93%
32 54.6 Smolensk Retreat 24000 16.55%
30.4 54.4 Orscha Retreat 20000 13.79%
26.8 54.3 Moiodexno Retreat 12000 8.28%
" - ], "text/plain": [ - "Longitude | Latitude | City Name | Direction | Survivors | Percent Surviving\n", - "32 | 54.8 | Smolensk | Advance | 145000 | 100.00%\n", - "33.2 | 54.9 | Dorogobouge | Advance | 140000 | 96.55%\n", - "34.4 | 55.5 | Chjat | Advance | 127100 | 87.66%\n", - "37.6 | 55.8 | Moscou | Advance | 100000 | 68.97%\n", - "34.3 | 55.2 | Wixma | Retreat | 55000 | 37.93%\n", - "32 | 54.6 | Smolensk | Retreat | 24000 | 16.55%\n", - "30.4 | 54.4 | Orscha | Retreat | 20000 | 13.79%\n", - "26.8 | 54.3 | Moiodexno | Retreat | 12000 | 8.28%" + "shape: (8, 6)\n", + "┌───────────┬──────────┬─────────────┬───────────┬───────────┬───────────────────┐\n", + "│ Longitude ┆ Latitude ┆ City Name ┆ Direction ┆ Survivors ┆ Percent Surviving │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ f64 ┆ f64 ┆ str ┆ str ┆ i64 ┆ str │\n", + "╞═══════════╪══════════╪═════════════╪═══════════╪═══════════╪═══════════════════╡\n", + "│ 32.0 ┆ 54.8 ┆ Smolensk ┆ Advance ┆ 145000 ┆ 100.0% │\n", + "│ 33.2 ┆ 54.9 ┆ Dorogobouge ┆ Advance ┆ 140000 ┆ 96.55% │\n", + "│ 34.4 ┆ 55.5 ┆ Chjat ┆ Advance ┆ 127100 ┆ 87.66% │\n", + "│ 37.6 ┆ 55.8 ┆ Moscou ┆ Advance ┆ 100000 ┆ 68.97% │\n", + "│ 34.3 ┆ 55.2 ┆ Wixma ┆ Retreat ┆ 55000 ┆ 37.93% │\n", + "│ 32.0 ┆ 54.6 ┆ Smolensk ┆ Retreat ┆ 24000 ┆ 16.55% │\n", + "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 ┆ 13.79% │\n", + "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 ┆ 8.28% │\n", + "└───────────┴──────────┴─────────────┴───────────┴───────────┴───────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 6)
LongitudeLatitudeCity NameDirectionSurvivorsPercent Surviving
f64f64strstri64str
32.054.8"Smolensk""Advance"145000"100.0%"
33.254.9"Dorogobouge""Advance"140000"96.55%"
34.455.5"Chjat""Advance"127100"87.66%"
37.655.8"Moscou""Advance"100000"68.97%"
34.355.2"Wixma""Retreat"55000"37.93%"
32.054.6"Smolensk""Retreat"24000"16.55%"
30.454.4"Orscha""Retreat"20000"13.79%"
26.854.3"Moiodexno""Retreat"12000"8.28%"
" ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.set_format('Percent Surviving', PercentFormatter)" + "minard = minard.with_columns(\n", + " ((pl.col(\"Percent Surviving\") * 100).round(2).cast(pl.String) + \"%\").alias(\"Percent Surviving\")\n", + ")\n", + "minard" ] }, { @@ -911,70 +824,51 @@ "source": [ "**Choosing Sets of Columns**\n", "\n", - "The method `select` creates a new table that contains only the specified columns." + "The method `select` creates a new DataFrame that contains only the specified columns." ] }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 20, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 20, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Longitude Latitude
32 54.8
33.2 54.9
34.4 55.5
37.6 55.8
34.3 55.2
32 54.6
30.4 54.4
26.8 54.3
" - ], "text/plain": [ - "Longitude | Latitude\n", - "32 | 54.8\n", - "33.2 | 54.9\n", - "34.4 | 55.5\n", - "37.6 | 55.8\n", - "34.3 | 55.2\n", - "32 | 54.6\n", - "30.4 | 54.4\n", - "26.8 | 54.3" + "shape: (8, 2)\n", + "┌───────────┬──────────┐\n", + "│ Longitude ┆ Latitude │\n", + "│ --- ┆ --- │\n", + "│ f64 ┆ f64 │\n", + "╞═══════════╪══════════╡\n", + "│ 32.0 ┆ 54.8 │\n", + "│ 33.2 ┆ 54.9 │\n", + "│ 34.4 ┆ 55.5 │\n", + "│ 37.6 ┆ 55.8 │\n", + "│ 34.3 ┆ 55.2 │\n", + "│ 32.0 ┆ 54.6 │\n", + "│ 30.4 ┆ 54.4 │\n", + "│ 26.8 ┆ 54.3 │\n", + "└───────────┴──────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 2)
LongitudeLatitude
f64f64
32.054.8
33.254.9
34.455.5
37.655.8
34.355.2
32.054.6
30.454.4
26.854.3
" ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.select('Longitude', 'Latitude')" + "minard.select(\"Longitude\", \"Latitude\")" ] }, { @@ -986,298 +880,243 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 21, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 21, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Longitude Latitude
32 54.8
33.2 54.9
34.4 55.5
37.6 55.8
34.3 55.2
32 54.6
30.4 54.4
26.8 54.3
" - ], "text/plain": [ - "Longitude | Latitude\n", - "32 | 54.8\n", - "33.2 | 54.9\n", - "34.4 | 55.5\n", - "37.6 | 55.8\n", - "34.3 | 55.2\n", - "32 | 54.6\n", - "30.4 | 54.4\n", - "26.8 | 54.3" + "shape: (8, 2)\n", + "┌───────────┬──────────┐\n", + "│ Longitude ┆ Latitude │\n", + "│ --- ┆ --- │\n", + "│ f64 ┆ f64 │\n", + "╞═══════════╪══════════╡\n", + "│ 32.0 ┆ 54.8 │\n", + "│ 33.2 ┆ 54.9 │\n", + "│ 34.4 ┆ 55.5 │\n", + "│ 37.6 ┆ 55.8 │\n", + "│ 34.3 ┆ 55.2 │\n", + "│ 32.0 ┆ 54.6 │\n", + "│ 30.4 ┆ 54.4 │\n", + "│ 26.8 ┆ 54.3 │\n", + "└───────────┴──────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 2)
LongitudeLatitude
f64f64
32.054.8
33.254.9
34.455.5
37.655.8
34.355.2
32.054.6
30.454.4
26.854.3
" ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.select(0, 1)" + "minard.select(pl.nth(0), pl.nth(1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The result of using `select` is a new table, even when you select just one column." + "The result of using `select` is a new DataFrame, even when you select just one column." ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 22, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 22, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Survivors
145000
140000
127100
100000
55000
24000
20000
12000
" - ], "text/plain": [ - "Survivors\n", - "145000\n", - "140000\n", - "127100\n", - "100000\n", - "55000\n", - "24000\n", - "20000\n", - "12000" + "shape: (8, 1)\n", + "┌───────────┐\n", + "│ Survivors │\n", + "│ --- │\n", + "│ i64 │\n", + "╞═══════════╡\n", + "│ 145000 │\n", + "│ 140000 │\n", + "│ 127100 │\n", + "│ 100000 │\n", + "│ 55000 │\n", + "│ 24000 │\n", + "│ 20000 │\n", + "│ 12000 │\n", + "└───────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 1)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.select('Survivors')" + "minard.select(\"Survivors\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Notice that the result is a table, unlike the result of `column`, which is an array." + "Notice that the result is a DataFrame, unlike the result of `get_column`, which is a Polars Series." ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 23, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 23, + "metadata": {}, "data": { "text/plain": [ - "array([145000, 140000, 127100, 100000, 55000, 24000, 20000, 12000])" + "shape: (8,)\n", + "Series: 'Survivors' [i64]\n", + "[\n", + "\t145000\n", + "\t140000\n", + "\t127100\n", + "\t100000\n", + "\t55000\n", + "\t24000\n", + "\t20000\n", + "\t12000\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (8,)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.column('Survivors')" + "minard.get_column(\"Survivors\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Another way to create a new table consisting of a set of columns is to `drop` the columns you don't want." + "Another way to create a new DataFrame consisting of a set of columns is to `drop` the columns you don't want." ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 24, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 24, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
City Name Survivors Percent Surviving
Smolensk 145000 100.00%
Dorogobouge 140000 96.55%
Chjat 127100 87.66%
Moscou 100000 68.97%
Wixma 55000 37.93%
Smolensk 24000 16.55%
Orscha 20000 13.79%
Moiodexno 12000 8.28%
" - ], "text/plain": [ - "City Name | Survivors | Percent Surviving\n", - "Smolensk | 145000 | 100.00%\n", - "Dorogobouge | 140000 | 96.55%\n", - "Chjat | 127100 | 87.66%\n", - "Moscou | 100000 | 68.97%\n", - "Wixma | 55000 | 37.93%\n", - "Smolensk | 24000 | 16.55%\n", - "Orscha | 20000 | 13.79%\n", - "Moiodexno | 12000 | 8.28%" + "shape: (8, 3)\n", + "┌─────────────┬───────────┬───────────────────┐\n", + "│ City Name ┆ Survivors ┆ Percent Surviving │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ str ┆ i64 ┆ str │\n", + "╞═════════════╪═══════════╪═══════════════════╡\n", + "│ Smolensk ┆ 145000 ┆ 100.0% │\n", + "│ Dorogobouge ┆ 140000 ┆ 96.55% │\n", + "│ Chjat ┆ 127100 ┆ 87.66% │\n", + "│ Moscou ┆ 100000 ┆ 68.97% │\n", + "│ Wixma ┆ 55000 ┆ 37.93% │\n", + "│ Smolensk ┆ 24000 ┆ 16.55% │\n", + "│ Orscha ┆ 20000 ┆ 13.79% │\n", + "│ Moiodexno ┆ 12000 ┆ 8.28% │\n", + "└─────────────┴───────────┴───────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 3)
City NameSurvivorsPercent Surviving
stri64str
"Smolensk"145000"100.0%"
"Dorogobouge"140000"96.55%"
"Chjat"127100"87.66%"
"Moscou"100000"68.97%"
"Wixma"55000"37.93%"
"Smolensk"24000"16.55%"
"Orscha"20000"13.79%"
"Moiodexno"12000"8.28%"
" ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "minard.drop('Longitude', 'Latitude', 'Direction')" + "minard.drop(\"Longitude\", \"Latitude\", \"Direction\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Neither `select` nor `drop` change the original table. Instead, they create new smaller tables that share the same data. The fact that the original table is preserved is useful! You can generate multiple different tables that only consider certain columns without worrying that one analysis will affect the other." + "Neither `select` nor `drop` change the original DataFrame. Instead, they create new smaller DataFrames that share the same data. The fact that the original DataFrame is preserved is useful! You can generate multiple different DataFrames that only consider certain columns without worrying that one analysis will affect the other." ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 25, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 25, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Longitude Latitude City Name Direction Survivors Percent Surviving
32 54.8 Smolensk Advance 145000 100.00%
33.2 54.9 Dorogobouge Advance 140000 96.55%
34.4 55.5 Chjat Advance 127100 87.66%
37.6 55.8 Moscou Advance 100000 68.97%
34.3 55.2 Wixma Retreat 55000 37.93%
32 54.6 Smolensk Retreat 24000 16.55%
30.4 54.4 Orscha Retreat 20000 13.79%
26.8 54.3 Moiodexno Retreat 12000 8.28%
" - ], "text/plain": [ - "Longitude | Latitude | City Name | Direction | Survivors | Percent Surviving\n", - "32 | 54.8 | Smolensk | Advance | 145000 | 100.00%\n", - "33.2 | 54.9 | Dorogobouge | Advance | 140000 | 96.55%\n", - "34.4 | 55.5 | Chjat | Advance | 127100 | 87.66%\n", - "37.6 | 55.8 | Moscou | Advance | 100000 | 68.97%\n", - "34.3 | 55.2 | Wixma | Retreat | 55000 | 37.93%\n", - "32 | 54.6 | Smolensk | Retreat | 24000 | 16.55%\n", - "30.4 | 54.4 | Orscha | Retreat | 20000 | 13.79%\n", - "26.8 | 54.3 | Moiodexno | Retreat | 12000 | 8.28%" + "shape: (8, 6)\n", + "┌───────────┬──────────┬─────────────┬───────────┬───────────┬───────────────────┐\n", + "│ Longitude ┆ Latitude ┆ City Name ┆ Direction ┆ Survivors ┆ Percent Surviving │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ f64 ┆ f64 ┆ str ┆ str ┆ i64 ┆ str │\n", + "╞═══════════╪══════════╪═════════════╪═══════════╪═══════════╪═══════════════════╡\n", + "│ 32.0 ┆ 54.8 ┆ Smolensk ┆ Advance ┆ 145000 ┆ 100.0% │\n", + "│ 33.2 ┆ 54.9 ┆ Dorogobouge ┆ Advance ┆ 140000 ┆ 96.55% │\n", + "│ 34.4 ┆ 55.5 ┆ Chjat ┆ Advance ┆ 127100 ┆ 87.66% │\n", + "│ 37.6 ┆ 55.8 ┆ Moscou ┆ Advance ┆ 100000 ┆ 68.97% │\n", + "│ 34.3 ┆ 55.2 ┆ Wixma ┆ Retreat ┆ 55000 ┆ 37.93% │\n", + "│ 32.0 ┆ 54.6 ┆ Smolensk ┆ Retreat ┆ 24000 ┆ 16.55% │\n", + "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 ┆ 13.79% │\n", + "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 ┆ 8.28% │\n", + "└───────────┴──────────┴─────────────┴───────────┴───────────┴───────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (8, 6)
LongitudeLatitudeCity NameDirectionSurvivorsPercent Surviving
f64f64strstri64str
32.054.8"Smolensk""Advance"145000"100.0%"
33.254.9"Dorogobouge""Advance"140000"96.55%"
34.455.5"Chjat""Advance"127100"87.66%"
37.655.8"Moscou""Advance"100000"68.97%"
34.355.2"Wixma""Retreat"55000"37.93%"
32.054.6"Smolensk""Retreat"24000"16.55%"
30.454.4"Orscha""Retreat"20000"13.79%"
26.854.3"Moiodexno""Retreat"12000"8.28%"
" ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -1288,7 +1127,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "All of the methods that we have used above can be applied to any table." + "All of the methods that we have used above can be applied to any DataFrame." ] } ], From ec9f37fd8021706803f560ae89320c199ab85ec3 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Thu, 15 Oct 2026 23:07:43 -0700 Subject: [PATCH 02/17] feat(ch. 6) --- chapters/06/Tables.ipynb | 566 +++++++++++++++++++-------------------- 1 file changed, 283 insertions(+), 283 deletions(-) diff --git a/chapters/06/Tables.ipynb b/chapters/06/Tables.ipynb index cb0fcc359..d9fdf9df6 100644 --- a/chapters/06/Tables.ipynb +++ b/chapters/06/Tables.ipynb @@ -40,16 +40,7 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 2, - "metadata": {}, "data": { - "text/plain": [ - "shape: (0, 0)\n", - "┌┐\n", - "╞╡\n", - "└┘" - ], "text/html": [ "
\n", "shape: (0, 0)
" + ], + "text/plain": [ + "shape: (0, 0)\n", + "┌┐\n", + "╞╡\n", + "└┘" ] - } + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -82,10 +82,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 3, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (3, 1)
Number of petals
i64
8
34
5
" + ], "text/plain": [ "shape: (3, 1)\n", "┌──────────────────┐\n", @@ -97,18 +104,11 @@ "│ 34 │\n", "│ 5 │\n", "└──────────────────┘" - ], - "text/html": [ - "
\n", - "shape: (3, 1)
Number of petals
i64
8
34
5
" ] - } + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -130,10 +130,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 4, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (3, 2)
Number of petalsName
i64str
8"lotus"
34"sunflower"
5"rose"
" + ], "text/plain": [ "shape: (3, 2)\n", "┌──────────────────┬───────────┐\n", @@ -145,18 +152,11 @@ "│ 34 ┆ sunflower │\n", "│ 5 ┆ rose │\n", "└──────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (3, 2)
Number of petalsName
i64str
8"lotus"
34"sunflower"
5"rose"
" ] - } + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -179,10 +179,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 5, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (3, 3)
Number of petalsNameColor
i64strstr
8"lotus""pink"
34"sunflower""yellow"
5"rose""red"
" + ], "text/plain": [ "shape: (3, 3)\n", "┌──────────────────┬───────────┬────────┐\n", @@ -194,18 +201,11 @@ "│ 34 ┆ sunflower ┆ yellow │\n", "│ 5 ┆ rose ┆ red │\n", "└──────────────────┴───────────┴────────┘" - ], - "text/html": [ - "
\n", - "shape: (3, 3)
Number of petalsNameColor
i64strstr
8"lotus""pink"
34"sunflower""yellow"
5"rose""red"
" ] - } + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -232,10 +232,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 6, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (3, 2)
Number of petalsName
i64str
8"lotus"
34"sunflower"
5"rose"
" + ], "text/plain": [ "shape: (3, 2)\n", "┌──────────────────┬───────────┐\n", @@ -247,18 +254,11 @@ "│ 34 ┆ sunflower │\n", "│ 5 ┆ rose │\n", "└──────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (3, 2)
Number of petalsName
i64str
8"lotus"
34"sunflower"
5"rose"
" ] - } + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -284,10 +284,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 7, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 5)
LongitudeLatitudeCityDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" + ], "text/plain": [ "shape: (8, 5)\n", "┌───────────┬──────────┬─────────────┬───────────┬───────────┐\n", @@ -304,18 +311,11 @@ "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 │\n", "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 │\n", "└───────────┴──────────┴─────────────┴───────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 5)
LongitudeLatitudeCityDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" ] - } + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -345,14 +345,14 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 8, - "metadata": {}, "data": { "text/plain": [ "5" ] - } + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -365,14 +365,14 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 9, - "metadata": {}, "data": { "text/plain": [ "8" ] - } + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -394,14 +394,14 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 10, - "metadata": {}, "data": { "text/plain": [ "['Longitude', 'Latitude', 'City', 'Direction', 'Survivors']" ] - } + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -421,10 +421,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 11, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 5)
LongitudeLatitudeCity NameDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" + ], "text/plain": [ "shape: (8, 5)\n", "┌───────────┬──────────┬─────────────┬───────────┬───────────┐\n", @@ -441,18 +448,11 @@ "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 │\n", "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 │\n", "└───────────┴──────────┴─────────────┴───────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 5)
LongitudeLatitudeCity NameDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" ] - } + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -472,10 +472,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 12, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 5)
LongitudeLatitudeCityDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" + ], "text/plain": [ "shape: (8, 5)\n", "┌───────────┬──────────┬─────────────┬───────────┬───────────┐\n", @@ -492,18 +499,11 @@ "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 │\n", "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 │\n", "└───────────┴──────────┴─────────────┴───────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 5)
LongitudeLatitudeCityDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" ] - } + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -523,10 +523,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 13, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 5)
LongitudeLatitudeCity NameDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" + ], "text/plain": [ "shape: (8, 5)\n", "┌───────────┬──────────┬─────────────┬───────────┬───────────┐\n", @@ -543,18 +550,11 @@ "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 │\n", "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 │\n", "└───────────┴──────────┴─────────────┴───────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 5)
LongitudeLatitudeCity NameDirectionSurvivors
f64f64strstri64
32.054.8"Smolensk""Advance"145000
33.254.9"Dorogobouge""Advance"140000
34.455.5"Chjat""Advance"127100
37.655.8"Moscou""Advance"100000
34.355.2"Wixma""Retreat"55000
32.054.6"Smolensk""Retreat"24000
30.454.4"Orscha""Retreat"20000
26.854.3"Moiodexno""Retreat"12000
" ] - } + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -577,10 +577,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 14, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8,)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" + ], "text/plain": [ "shape: (8,)\n", "Series: 'Survivors' [i64]\n", @@ -594,18 +601,11 @@ "\t20000\n", "\t12000\n", "]" - ], - "text/html": [ - "
\n", - "shape: (8,)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" ] - } + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -625,10 +625,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 15, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8,)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" + ], "text/plain": [ "shape: (8,)\n", "Series: 'Survivors' [i64]\n", @@ -642,18 +649,11 @@ "\t20000\n", "\t12000\n", "]" - ], - "text/html": [ - "
\n", - "shape: (8,)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" ] - } + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -673,14 +673,14 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 16, - "metadata": {}, "data": { "text/plain": [ "145000" ] - } + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -693,14 +693,14 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 17, - "metadata": {}, "data": { "text/plain": [ "24000" ] - } + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -722,10 +722,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 18, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 6)
LongitudeLatitudeCity NameDirectionSurvivorsPercent Surviving
f64f64strstri64f64
32.054.8"Smolensk""Advance"1450001.0
33.254.9"Dorogobouge""Advance"1400000.965517
34.455.5"Chjat""Advance"1271000.876552
37.655.8"Moscou""Advance"1000000.689655
34.355.2"Wixma""Retreat"550000.37931
32.054.6"Smolensk""Retreat"240000.165517
30.454.4"Orscha""Retreat"200000.137931
26.854.3"Moiodexno""Retreat"120000.082759
" + ], "text/plain": [ "shape: (8, 6)\n", "┌───────────┬──────────┬─────────────┬───────────┬───────────┬───────────────────┐\n", @@ -742,18 +749,11 @@ "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 ┆ 0.137931 │\n", "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 ┆ 0.082759 │\n", "└───────────┴──────────┴─────────────┴───────────┴───────────┴───────────────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 6)
LongitudeLatitudeCity NameDirectionSurvivorsPercent Surviving
f64f64strstri64f64
32.054.8"Smolensk""Advance"1450001.0
33.254.9"Dorogobouge""Advance"1400000.965517
34.455.5"Chjat""Advance"1271000.876552
37.655.8"Moscou""Advance"1000000.689655
34.355.2"Wixma""Retreat"550000.37931
32.054.6"Smolensk""Retreat"240000.165517
30.454.4"Orscha""Retreat"200000.137931
26.854.3"Moiodexno""Retreat"120000.082759
" ] - } + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -768,7 +768,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To make the proportions in the new column appear as percents, multiply by 100, round to two decimal places, and append a percent sign. `with_columns` returns a new DataFrame, so the result is assigned back to `minard`." + "[POLARS_CHANGE] To make the proportions in the new column appear as percents, multiply by 100, round to two decimal places, and append a percent sign. `with_columns` returns a new DataFrame, so the result is assigned back to `minard`." ] }, { @@ -777,10 +777,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 19, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 6)
LongitudeLatitudeCity NameDirectionSurvivorsPercent Surviving
f64f64strstri64str
32.054.8"Smolensk""Advance"145000"100.0%"
33.254.9"Dorogobouge""Advance"140000"96.55%"
34.455.5"Chjat""Advance"127100"87.66%"
37.655.8"Moscou""Advance"100000"68.97%"
34.355.2"Wixma""Retreat"55000"37.93%"
32.054.6"Smolensk""Retreat"24000"16.55%"
30.454.4"Orscha""Retreat"20000"13.79%"
26.854.3"Moiodexno""Retreat"12000"8.28%"
" + ], "text/plain": [ "shape: (8, 6)\n", "┌───────────┬──────────┬─────────────┬───────────┬───────────┬───────────────────┐\n", @@ -797,18 +804,11 @@ "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 ┆ 13.79% │\n", "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 ┆ 8.28% │\n", "└───────────┴──────────┴─────────────┴───────────┴───────────┴───────────────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 6)
LongitudeLatitudeCity NameDirectionSurvivorsPercent Surviving
f64f64strstri64str
32.054.8"Smolensk""Advance"145000"100.0%"
33.254.9"Dorogobouge""Advance"140000"96.55%"
34.455.5"Chjat""Advance"127100"87.66%"
37.655.8"Moscou""Advance"100000"68.97%"
34.355.2"Wixma""Retreat"55000"37.93%"
32.054.6"Smolensk""Retreat"24000"16.55%"
30.454.4"Orscha""Retreat"20000"13.79%"
26.854.3"Moiodexno""Retreat"12000"8.28%"
" ] - } + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -833,10 +833,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 20, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 2)
LongitudeLatitude
f64f64
32.054.8
33.254.9
34.455.5
37.655.8
34.355.2
32.054.6
30.454.4
26.854.3
" + ], "text/plain": [ "shape: (8, 2)\n", "┌───────────┬──────────┐\n", @@ -853,18 +860,11 @@ "│ 30.4 ┆ 54.4 │\n", "│ 26.8 ┆ 54.3 │\n", "└───────────┴──────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 2)
LongitudeLatitude
f64f64
32.054.8
33.254.9
34.455.5
37.655.8
34.355.2
32.054.6
30.454.4
26.854.3
" ] - } + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -884,10 +884,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 21, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 2)
LongitudeLatitude
f64f64
32.054.8
33.254.9
34.455.5
37.655.8
34.355.2
32.054.6
30.454.4
26.854.3
" + ], "text/plain": [ "shape: (8, 2)\n", "┌───────────┬──────────┐\n", @@ -904,18 +911,11 @@ "│ 30.4 ┆ 54.4 │\n", "│ 26.8 ┆ 54.3 │\n", "└───────────┴──────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 2)
LongitudeLatitude
f64f64
32.054.8
33.254.9
34.455.5
37.655.8
34.355.2
32.054.6
30.454.4
26.854.3
" ] - } + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -935,10 +935,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 22, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 1)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" + ], "text/plain": [ "shape: (8, 1)\n", "┌───────────┐\n", @@ -955,18 +962,11 @@ "│ 20000 │\n", "│ 12000 │\n", "└───────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 1)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" ] - } + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -986,10 +986,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 23, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8,)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" + ], "text/plain": [ "shape: (8,)\n", "Series: 'Survivors' [i64]\n", @@ -1003,18 +1010,11 @@ "\t20000\n", "\t12000\n", "]" - ], - "text/html": [ - "
\n", - "shape: (8,)
Survivors
i64
145000
140000
127100
100000
55000
24000
20000
12000
" ] - } + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -1034,10 +1034,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 24, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 3)
City NameSurvivorsPercent Surviving
stri64str
"Smolensk"145000"100.0%"
"Dorogobouge"140000"96.55%"
"Chjat"127100"87.66%"
"Moscou"100000"68.97%"
"Wixma"55000"37.93%"
"Smolensk"24000"16.55%"
"Orscha"20000"13.79%"
"Moiodexno"12000"8.28%"
" + ], "text/plain": [ "shape: (8, 3)\n", "┌─────────────┬───────────┬───────────────────┐\n", @@ -1054,18 +1061,11 @@ "│ Orscha ┆ 20000 ┆ 13.79% │\n", "│ Moiodexno ┆ 12000 ┆ 8.28% │\n", "└─────────────┴───────────┴───────────────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 3)
City NameSurvivorsPercent Surviving
stri64str
"Smolensk"145000"100.0%"
"Dorogobouge"140000"96.55%"
"Chjat"127100"87.66%"
"Moscou"100000"68.97%"
"Wixma"55000"37.93%"
"Smolensk"24000"16.55%"
"Orscha"20000"13.79%"
"Moiodexno"12000"8.28%"
" ] - } + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -1085,10 +1085,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 25, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (8, 6)
LongitudeLatitudeCity NameDirectionSurvivorsPercent Surviving
f64f64strstri64str
32.054.8"Smolensk""Advance"145000"100.0%"
33.254.9"Dorogobouge""Advance"140000"96.55%"
34.455.5"Chjat""Advance"127100"87.66%"
37.655.8"Moscou""Advance"100000"68.97%"
34.355.2"Wixma""Retreat"55000"37.93%"
32.054.6"Smolensk""Retreat"24000"16.55%"
30.454.4"Orscha""Retreat"20000"13.79%"
26.854.3"Moiodexno""Retreat"12000"8.28%"
" + ], "text/plain": [ "shape: (8, 6)\n", "┌───────────┬──────────┬─────────────┬───────────┬───────────┬───────────────────┐\n", @@ -1105,18 +1112,11 @@ "│ 30.4 ┆ 54.4 ┆ Orscha ┆ Retreat ┆ 20000 ┆ 13.79% │\n", "│ 26.8 ┆ 54.3 ┆ Moiodexno ┆ Retreat ┆ 12000 ┆ 8.28% │\n", "└───────────┴──────────┴─────────────┴───────────┴───────────┴───────────────────┘" - ], - "text/html": [ - "
\n", - "shape: (8, 6)
LongitudeLatitudeCity NameDirectionSurvivorsPercent Surviving
f64f64strstri64str
32.054.8"Smolensk""Advance"145000"100.0%"
33.254.9"Dorogobouge""Advance"140000"96.55%"
34.455.5"Chjat""Advance"127100"87.66%"
37.655.8"Moscou""Advance"100000"68.97%"
34.355.2"Wixma""Retreat"55000"37.93%"
32.054.6"Smolensk""Retreat"24000"16.55%"
30.454.4"Orscha""Retreat"20000"13.79%"
26.854.3"Moiodexno""Retreat"12000"8.28%"
" ] - } + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ From cb75b0935e639e21cf2ebec6031d35564a720708 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Thu, 15 Oct 2026 23:26:26 -0700 Subject: [PATCH 03/17] Ch. 6.1 polars - nba_salaries.sort(pl.nth(0)).head(5) --> .sort using column indexes, cannot just use a number to sort --- chapters/06/1/Sorting_Rows.ipynb | 631 +++++++++++++++---------------- 1 file changed, 311 insertions(+), 320 deletions(-) diff --git a/chapters/06/1/Sorting_Rows.ipynb b/chapters/06/1/Sorting_Rows.ipynb index c79b09652..1adbd63b6 100644 --- a/chapters/06/1/Sorting_Rows.ipynb +++ b/chapters/06/1/Sorting_Rows.ipynb @@ -6,7 +6,7 @@ "source": [ "# Sorting Rows\n", "\n", - "\"The NBA is the highest paying professional sports league in the world,\" [reported CNN](http://edition.cnn.com/2015/12/04/sport/gallery/highest-paid-nba-players/) in March 2016. The table `nba_salaries` contains the salaries of all National Basketball Association players in 2015-2016.\n", + "\"The NBA is the highest paying professional sports league in the world,\" [reported CNN](http://edition.cnn.com/2015/12/04/sport/gallery/highest-paid-nba-players/) in March 2016. The DataFrame `nba_salaries` contains the salaries of all National Basketball Association players in 2015-2016.\n", "\n", "Each row represents one player. The columns are:\n", "\n", @@ -32,10 +32,8 @@ }, "outputs": [], "source": [ - "from datascience import *\n", - "import numpy as np\n", - "path_data = '../../../assets/data/'\n", - "np.set_printoptions(threshold=50)" + "import polars as pl\n", + "path_data = '../../../assets/data/'" ] }, { @@ -44,72 +42,46 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 2, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM '15-'16 SALARY
Paul Millsap PF Atlanta Hawks 18.6717
Al Horford C Atlanta Hawks 12
Tiago Splitter C Atlanta Hawks 9.75625
Jeff Teague PG Atlanta Hawks 8
Kyle Korver SG Atlanta Hawks 5.74648
Thabo Sefolosha SF Atlanta Hawks 4
Mike Scott PF Atlanta Hawks 3.33333
Kent Bazemore SF Atlanta Hawks 2
Dennis Schroder PG Atlanta Hawks 1.7634
Tim Hardaway Jr. SG Atlanta Hawks 1.30452
\n", - "

... (407 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | '15-'16 SALARY\n", - "Paul Millsap | PF | Atlanta Hawks | 18.6717\n", - "Al Horford | C | Atlanta Hawks | 12\n", - "Tiago Splitter | C | Atlanta Hawks | 9.75625\n", - "Jeff Teague | PG | Atlanta Hawks | 8\n", - "Kyle Korver | SG | Atlanta Hawks | 5.74648\n", - "Thabo Sefolosha | SF | Atlanta Hawks | 4\n", - "Mike Scott | PF | Atlanta Hawks | 3.33333\n", - "Kent Bazemore | SF | Atlanta Hawks | 2\n", - "Dennis Schroder | PG | Atlanta Hawks | 1.7634\n", - "Tim Hardaway Jr. | SG | Atlanta Hawks | 1.30452\n", - "... (407 rows omitted)" + "shape: (417, 4)\n", + "┌─────────────────┬──────────┬────────────────────┬────────────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ '15-'16 SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═════════════════╪══════════╪════════════════════╪════════════════╡\n", + "│ Paul Millsap ┆ PF ┆ Atlanta Hawks ┆ 18.671659 │\n", + "│ Al Horford ┆ C ┆ Atlanta Hawks ┆ 12.0 │\n", + "│ Tiago Splitter ┆ C ┆ Atlanta Hawks ┆ 9.75625 │\n", + "│ Jeff Teague ┆ PG ┆ Atlanta Hawks ┆ 8.0 │\n", + "│ Kyle Korver ┆ SG ┆ Atlanta Hawks ┆ 5.746479 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Gary Neal ┆ PG ┆ Washington Wizards ┆ 2.139 │\n", + "│ DeJuan Blair ┆ C ┆ Washington Wizards ┆ 2.0 │\n", + "│ Kelly Oubre Jr. ┆ SF ┆ Washington Wizards ┆ 1.92024 │\n", + "│ Garrett Temple ┆ SG ┆ Washington Wizards ┆ 1.100602 │\n", + "│ Jarell Eddie ┆ SG ┆ Washington Wizards ┆ 0.561716 │\n", + "└─────────────────┴──────────┴────────────────────┴────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAM'15-'16 SALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Tiago Splitter""C""Atlanta Hawks"9.75625
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
…………
"Gary Neal""PG""Washington Wizards"2.139
"DeJuan Blair""C""Washington Wizards"2.0
"Kelly Oubre Jr.""SF""Washington Wizards"1.92024
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "# This table can be found online: https://www.statcrunch.com/app/index.php?dataid=1843341\n", - "nba_salaries = Table.read_table(path_data + 'nba_salaries.csv')\n", + "# This DataFrame can be found online: https://www.statcrunch.com/app/index.php?dataid=1843341\n", + "nba_salaries = pl.read_csv(path_data + 'nba_salaries.csv')\n", "nba_salaries" ] }, @@ -117,7 +89,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The table contains 417 rows, one for each player. Only 10 of the rows are displayed. The `show` method allows us to specify the number of rows, with the default (no specification) being all the rows of the table." + "The DataFrame contains 417 rows, one for each player. The display shows the first five and last five rows. `head` returns the first rows of a DataFrame." ] }, { @@ -126,45 +98,46 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 3, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM '15-'16 SALARY
Paul Millsap PF Atlanta Hawks 18.6717
Al Horford C Atlanta Hawks 12
Tiago Splitter C Atlanta Hawks 9.75625
\n", - "

... (414 rows omitted)

" - ], "text/plain": [ - "" + "shape: (3, 4)\n", + "┌────────────────┬──────────┬───────────────┬────────────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ '15-'16 SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════════════╪══════════╪═══════════════╪════════════════╡\n", + "│ Paul Millsap ┆ PF ┆ Atlanta Hawks ┆ 18.671659 │\n", + "│ Al Horford ┆ C ┆ Atlanta Hawks ┆ 12.0 │\n", + "│ Tiago Splitter ┆ C ┆ Atlanta Hawks ┆ 9.75625 │\n", + "└────────────────┴──────────┴───────────────┴────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (3, 4)
PLAYERPOSITIONTEAM'15-'16 SALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Tiago Splitter""C""Atlanta Hawks"9.75625
" ] - }, - "metadata": {}, - "output_type": "display_data" + } } ], "source": [ - "nba_salaries.show(3)" + "nba_salaries.head(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Glance through about 20 rows or so, and you will see that the rows are in alphabetical order by team name. It's also possible to list the same rows in alphabetical order by player name using the `sort` method. The argument to `sort` is a column label or index." + "Glance through about 20 rows or so, and you will see that the rows are in alphabetical order by team name. It's also possible to list the same rows in alphabetical order by player name using the `sort` method. The argument to `sort` is a column name.\n", + "\n", + "POLARS_CHANGE: To sort by a column position instead of a name, pass `pl.nth(index)`." ] }, { @@ -173,44 +146,81 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 4, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM '15-'16 SALARY
Aaron Brooks PG Chicago Bulls 2.25
Aaron Gordon PF Orlando Magic 4.17168
Aaron Harrison SG Charlotte Hornets 0.525093
Adreian Payne PF Minnesota Timberwolves 1.93884
Al Horford C Atlanta Hawks 12
\n", - "

... (412 rows omitted)

" - ], "text/plain": [ - "" + "shape: (5, 4)\n", + "┌────────────────┬──────────┬────────────────────────┬────────────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ '15-'16 SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════════════╪══════════╪════════════════════════╪════════════════╡\n", + "│ Aaron Brooks ┆ PG ┆ Chicago Bulls ┆ 2.25 │\n", + "│ Aaron Gordon ┆ PF ┆ Orlando Magic ┆ 4.17168 │\n", + "│ Aaron Harrison ┆ SG ┆ Charlotte Hornets ┆ 0.525093 │\n", + "│ Adreian Payne ┆ PF ┆ Minnesota Timberwolves ┆ 1.93884 │\n", + "│ Al Horford ┆ C ┆ Atlanta Hawks ┆ 12.0 │\n", + "└────────────────┴──────────┴────────────────────────┴────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (5, 4)
PLAYERPOSITIONTEAM'15-'16 SALARY
strstrstrf64
"Aaron Brooks""PG""Chicago Bulls"2.25
"Aaron Gordon""PF""Orlando Magic"4.17168
"Aaron Harrison""SG""Charlotte Hornets"0.525093
"Adreian Payne""PF""Minnesota Timberwolves"1.93884
"Al Horford""C""Atlanta Hawks"12.0
" ] - }, + } + } + ], + "source": [ + "nba_salaries.sort(\"PLAYER\").head(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 5, "metadata": {}, - "output_type": "display_data" + "data": { + "text/plain": [ + "shape: (5, 4)\n", + "┌────────────────┬──────────┬────────────────────────┬────────────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ '15-'16 SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════════════╪══════════╪════════════════════════╪════════════════╡\n", + "│ Aaron Brooks ┆ PG ┆ Chicago Bulls ┆ 2.25 │\n", + "│ Aaron Gordon ┆ PF ┆ Orlando Magic ┆ 4.17168 │\n", + "│ Aaron Harrison ┆ SG ┆ Charlotte Hornets ┆ 0.525093 │\n", + "│ Adreian Payne ┆ PF ┆ Minnesota Timberwolves ┆ 1.93884 │\n", + "│ Al Horford ┆ C ┆ Atlanta Hawks ┆ 12.0 │\n", + "└────────────────┴──────────┴────────────────────────┴────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (5, 4)
PLAYERPOSITIONTEAM'15-'16 SALARY
strstrstrf64
"Aaron Brooks""PG""Chicago Bulls"2.25
"Aaron Gordon""PF""Orlando Magic"4.17168
"Aaron Harrison""SG""Charlotte Hornets"0.525093
"Adreian Payne""PF""Minnesota Timberwolves"1.93884
"Al Horford""C""Atlanta Hawks"12.0
" + ] + } } ], "source": [ - "nba_salaries.sort('PLAYER').show(5)" + "# POLARS_CHANGE: column 0 is PLAYER, so this sort matches the cell above\n", + "nba_salaries.sort(pl.nth(0)).head(5)" ] }, { @@ -219,167 +229,115 @@ "source": [ "To examine the players' salaries, it would be much more helpful if the data were ordered by salary.\n", "\n", - "To do this, we will first simplify the label of the column of salaries (just for convenience), and then sort by the new label `SALARY`. \n", + "To do this, we will first simplify the label of the column of salaries (just for convenience), and then sort by the new label `SALARY`.\n", "\n", - "This arranges all the rows of the table in *increasing* order of salary, with the lowest salary appearing first. The output is a new table with the same columns as the original but with the rows rearranged." + "This arranges all the rows of the DataFrame in *increasing* order of salary, with the lowest salary appearing first. The output is a new DataFrame with the same columns as the original but with the rows rearranged." ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 6, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Thanasis Antetokounmpo SF New York Knicks 0.030888
Jordan McRae SG Phoenix Suns 0.049709
Cory Jefferson PF Phoenix Suns 0.049709
Elliot Williams SG Memphis Grizzlies 0.055722
Orlando Johnson SG Phoenix Suns 0.055722
Phil Pressey PG Phoenix Suns 0.055722
Keith Appling PG Orlando Magic 0.061776
Sean Kilpatrick SG Denver Nuggets 0.099418
Erick Green PG Utah Jazz 0.099418
Jeff Ayres PF Los Angeles Clippers 0.111444
\n", - "

... (407 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Thanasis Antetokounmpo | SF | New York Knicks | 0.030888\n", - "Jordan McRae | SG | Phoenix Suns | 0.049709\n", - "Cory Jefferson | PF | Phoenix Suns | 0.049709\n", - "Elliot Williams | SG | Memphis Grizzlies | 0.055722\n", - "Orlando Johnson | SG | Phoenix Suns | 0.055722\n", - "Phil Pressey | PG | Phoenix Suns | 0.055722\n", - "Keith Appling | PG | Orlando Magic | 0.061776\n", - "Sean Kilpatrick | SG | Denver Nuggets | 0.099418\n", - "Erick Green | PG | Utah Jazz | 0.099418\n", - "Jeff Ayres | PF | Los Angeles Clippers | 0.111444\n", - "... (407 rows omitted)" + "shape: (417, 4)\n", + "┌────────────────────────┬──────────┬─────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════════════════════╪══════════╪═════════════════════╪═══════════╡\n", + "│ Thanasis Antetokounmpo ┆ SF ┆ New York Knicks ┆ 0.030888 │\n", + "│ Jordan McRae ┆ SG ┆ Phoenix Suns ┆ 0.049709 │\n", + "│ Cory Jefferson ┆ PF ┆ Phoenix Suns ┆ 0.049709 │\n", + "│ Elliot Williams ┆ SG ┆ Memphis Grizzlies ┆ 0.055722 │\n", + "│ Orlando Johnson ┆ SG ┆ Phoenix Suns ┆ 0.055722 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Dwight Howard ┆ C ┆ Houston Rockets ┆ 22.359364 │\n", + "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", + "│ LeBron James ┆ SF ┆ Cleveland Cavaliers ┆ 22.9705 │\n", + "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", + "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", + "└────────────────────────┴──────────┴─────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Thanasis Antetokounmpo""SF""New York Knicks"0.030888
"Jordan McRae""SG""Phoenix Suns"0.049709
"Cory Jefferson""PF""Phoenix Suns"0.049709
"Elliot Williams""SG""Memphis Grizzlies"0.055722
"Orlando Johnson""SG""Phoenix Suns"0.055722
…………
"Dwight Howard""C""Houston Rockets"22.359364
"Carmelo Anthony""SF""New York Knicks"22.875
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Kobe Bryant""SF""Los Angeles Lakers"25.0
" ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba = nba_salaries.relabeled(\"'15-'16 SALARY\", 'SALARY')\n", - "nba.sort('SALARY')" + "nba = nba_salaries.rename({\"'15-'16 SALARY\": \"SALARY\"})\n", + "nba.sort(\"SALARY\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "These figures are somewhat difficult to compare as some of these players changed teams during the season and received salaries from more than one team; only the salary from the last team appears in the table. Point Guard Phil Pressey, for example, moved from Philadelphia to Phoenix during the year, and might be moving yet again to the Golden State Warriors. \n", + "These figures are somewhat difficult to compare as some of these players changed teams during the season and received salaries from more than one team; only the salary from the last team appears in the DataFrame. Point Guard Phil Pressey, for example, moved from Philadelphia to Phoenix during the year, and might be moving yet again to the Golden State Warriors.\n", "\n", - "The CNN report is about the other end of the salary scale – the players who are among the highest paid in the world. \n", + "The CNN report is about the other end of the salary scale – the players who are among the highest paid in the world.\n", "\n", - "To order the rows of the table in *decreasing* order of salary, we must use `sort` with the option `descending=True`." + "To order the rows of the DataFrame in *decreasing* order of salary, we must use `sort` with the option `descending=True`." ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 7, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Kobe Bryant SF Los Angeles Lakers 25
Joe Johnson SF Brooklyn Nets 24.8949
LeBron James SF Cleveland Cavaliers 22.9705
Carmelo Anthony SF New York Knicks 22.875
Dwight Howard C Houston Rockets 22.3594
Chris Bosh PF Miami Heat 22.1927
Chris Paul PG Los Angeles Clippers 21.4687
Kevin Durant SF Oklahoma City Thunder 20.1586
Derrick Rose PG Chicago Bulls 20.0931
Dwyane Wade SG Miami Heat 20
\n", - "

... (407 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Kobe Bryant | SF | Los Angeles Lakers | 25\n", - "Joe Johnson | SF | Brooklyn Nets | 24.8949\n", - "LeBron James | SF | Cleveland Cavaliers | 22.9705\n", - "Carmelo Anthony | SF | New York Knicks | 22.875\n", - "Dwight Howard | C | Houston Rockets | 22.3594\n", - "Chris Bosh | PF | Miami Heat | 22.1927\n", - "Chris Paul | PG | Los Angeles Clippers | 21.4687\n", - "Kevin Durant | SF | Oklahoma City Thunder | 20.1586\n", - "Derrick Rose | PG | Chicago Bulls | 20.0931\n", - "Dwyane Wade | SG | Miami Heat | 20\n", - "... (407 rows omitted)" + "shape: (417, 4)\n", + "┌────────────────────────┬──────────┬─────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════════════════════╪══════════╪═════════════════════╪═══════════╡\n", + "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", + "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", + "│ LeBron James ┆ SF ┆ Cleveland Cavaliers ┆ 22.9705 │\n", + "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", + "│ Dwight Howard ┆ C ┆ Houston Rockets ┆ 22.359364 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Orlando Johnson ┆ SG ┆ Phoenix Suns ┆ 0.055722 │\n", + "│ Phil Pressey ┆ PG ┆ Phoenix Suns ┆ 0.055722 │\n", + "│ Jordan McRae ┆ SG ┆ Phoenix Suns ┆ 0.049709 │\n", + "│ Cory Jefferson ┆ PF ┆ Phoenix Suns ┆ 0.049709 │\n", + "│ Thanasis Antetokounmpo ┆ SF ┆ New York Knicks ┆ 0.030888 │\n", + "└────────────────────────┴──────────┴─────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Carmelo Anthony""SF""New York Knicks"22.875
"Dwight Howard""C""Houston Rockets"22.359364
…………
"Orlando Johnson""SG""Phoenix Suns"0.055722
"Phil Pressey""PG""Phoenix Suns"0.055722
"Jordan McRae""SG""Phoenix Suns"0.049709
"Cory Jefferson""PF""Phoenix Suns"0.049709
"Thanasis Antetokounmpo""SF""New York Knicks"0.030888
" ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.sort('SALARY', descending=True)" + "nba.sort(\"SALARY\", descending=True)" ] }, { @@ -400,75 +358,107 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": {}, "outputs": [ { - "name": "stdout", "output_type": "stream", + "name": "stdout", "text": [ - "Help on method sort in module datascience.tables:\n", + "Help on method sort in module polars.dataframe.frame:\n", + "\n", + "sort(\n", + " by: 'IntoExpr | Iterable[IntoExpr]',\n", + " *more_by: 'IntoExpr',\n", + " descending: 'bool | Sequence[bool]' = False,\n", + " nulls_last: 'bool | Sequence[bool]' = False,\n", + " multithreaded: 'bool' = True,\n", + " maintain_order: 'bool' = False\n", + ") -> 'DataFrame' method of polars.dataframe.frame.DataFrame instance\n", + " Sort the dataframe by the given columns.\n", + "\n", + " Parameters\n", + " ----------\n", + " by\n", + " Column(s) to sort by. Accepts expression input, including selectors. Strings\n", + " are parsed as column names.\n", + " *more_by\n", + " Additional columns to sort by, specified as positional arguments.\n", + " descending\n", + " Sort in descending order. When sorting by multiple columns, can be specified\n", + " per column by passing a sequence of booleans.\n", + " nulls_last\n", + " Place null values last; can specify a single boolean applying to all columns\n", + " or a sequence of booleans for per-column control.\n", + " multithreaded\n", + " Sort using multiple threads.\n", + " maintain_order\n", + " Whether the order should be maintained if elements are equal.\n", + "\n", + " Examples\n", + " --------\n", + " Pass a single column name to sort by that column.\n", + "\n", + " >>> df = pl.DataFrame(\n", + " ... {\n", + " ... \"a\": [1, 2, None],\n", + " ... \"b\": [6.0, 5.0, 4.0],\n", + " ... \"c\": [\"a\", \"c\", \"b\"],\n", + " ... }\n", + " ... )\n", + " >>> df.sort(\"a\")\n", + " shape: (3, 3)\n", + " ┌──────┬─────┬─────┐\n", + " │ a ┆ b ┆ c │\n", + " │ --- ┆ --- ┆ --- │\n", + " │ i64 ┆ f64 ┆ str │\n", + " ╞══════╪═════╪═════╡\n", + " │ null ┆ 4.0 ┆ b │\n", + " │ 1 ┆ 6.0 ┆ a │\n", + " │ 2 ┆ 5.0 ┆ c │\n", + " └──────┴─────┴─────┘\n", "\n", - "sort(column_or_label, descending=False, distinct=False) method of datascience.tables.Table instance\n", - " Return a Table of rows sorted according to the values in a column.\n", - " \n", - " Args:\n", - " ``column_or_label``: the column whose values are used for sorting.\n", - " \n", - " ``descending``: if True, sorting will be in descending, rather than\n", - " ascending order.\n", - " \n", - " ``distinct``: if True, repeated values in ``column_or_label`` will\n", - " be omitted.\n", - " \n", - " Returns:\n", - " An instance of ``Table`` containing rows sorted based on the values\n", - " in ``column_or_label``.\n", - " \n", - " >>> marbles = Table().with_columns(\n", - " ... \"Color\", make_array(\"Red\", \"Green\", \"Blue\", \"Red\", \"Green\", \"Green\"),\n", - " ... \"Shape\", make_array(\"Round\", \"Rectangular\", \"Rectangular\", \"Round\", \"Rectangular\", \"Round\"),\n", - " ... \"Amount\", make_array(4, 6, 12, 7, 9, 2),\n", - " ... \"Price\", make_array(1.30, 1.30, 2.00, 1.75, 1.40, 1.00))\n", - " >>> marbles\n", - " Color | Shape | Amount | Price\n", - " Red | Round | 4 | 1.3\n", - " Green | Rectangular | 6 | 1.3\n", - " Blue | Rectangular | 12 | 2\n", - " Red | Round | 7 | 1.75\n", - " Green | Rectangular | 9 | 1.4\n", - " Green | Round | 2 | 1\n", - " >>> marbles.sort(\"Amount\")\n", - " Color | Shape | Amount | Price\n", - " Green | Round | 2 | 1\n", - " Red | Round | 4 | 1.3\n", - " Green | Rectangular | 6 | 1.3\n", - " Red | Round | 7 | 1.75\n", - " Green | Rectangular | 9 | 1.4\n", - " Blue | Rectangular | 12 | 2\n", - " >>> marbles.sort(\"Amount\", descending = True)\n", - " Color | Shape | Amount | Price\n", - " Blue | Rectangular | 12 | 2\n", - " Green | Rectangular | 9 | 1.4\n", - " Red | Round | 7 | 1.75\n", - " Green | Rectangular | 6 | 1.3\n", - " Red | Round | 4 | 1.3\n", - " Green | Round | 2 | 1\n", - " >>> marbles.sort(3) # the Price column\n", - " Color | Shape | Amount | Price\n", - " Green | Round | 2 | 1\n", - " Red | Round | 4 | 1.3\n", - " Green | Rectangular | 6 | 1.3\n", - " Green | Rectangular | 9 | 1.4\n", - " Red | Round | 7 | 1.75\n", - " Blue | Rectangular | 12 | 2\n", - " >>> marbles.sort(3, distinct = True)\n", - " Color | Shape | Amount | Price\n", - " Green | Round | 2 | 1\n", - " Red | Round | 4 | 1.3\n", - " Green | Rectangular | 9 | 1.4\n", - " Red | Round | 7 | 1.75\n", - " Blue | Rectangular | 12 | 2\n", + " Sorting by expressions is also supported.\n", + "\n", + " >>> df.sort(pl.col(\"a\") + pl.col(\"b\") * 2, nulls_last=True)\n", + " shape: (3, 3)\n", + " ┌──────┬─────┬─────┐\n", + " │ a ┆ b ┆ c │\n", + " │ --- ┆ --- ┆ --- │\n", + " │ i64 ┆ f64 ┆ str │\n", + " ╞══════╪═════╪═════╡\n", + " │ 2 ┆ 5.0 ┆ c │\n", + " │ 1 ┆ 6.0 ┆ a │\n", + " │ null ┆ 4.0 ┆ b │\n", + " └──────┴─────┴─────┘\n", + "\n", + " Sort by multiple columns by passing a list of columns.\n", + "\n", + " >>> df.sort([\"c\", \"a\"], descending=True)\n", + " shape: (3, 3)\n", + " ┌──────┬─────┬─────┐\n", + " │ a ┆ b ┆ c │\n", + " │ --- ┆ --- ┆ --- │\n", + " │ i64 ┆ f64 ┆ str │\n", + " ╞══════╪═════╪═════╡\n", + " │ 2 ┆ 5.0 ┆ c │\n", + " │ null ┆ 4.0 ┆ b │\n", + " │ 1 ┆ 6.0 ┆ a │\n", + " └──────┴─────┴─────┘\n", + "\n", + " Or use positional arguments to sort by multiple columns in the same way.\n", + "\n", + " >>> df.sort(\"c\", \"a\", descending=[False, True])\n", + " shape: (3, 3)\n", + " ┌──────┬─────┬─────┐\n", + " │ a ┆ b ┆ c │\n", + " │ --- ┆ --- ┆ --- │\n", + " │ i64 ┆ f64 ┆ str │\n", + " ╞══════╪═════╪═════╡\n", + " │ 1 ┆ 6.0 ┆ a │\n", + " │ null ┆ 4.0 ┆ b │\n", + " │ 2 ┆ 5.0 ┆ c │\n", + " └──────┴─────┴─────┘\n", "\n" ] } @@ -483,15 +473,16 @@ "source": [ "At the very top of this `help` text, the *signature* of the `sort` method appears:\n", "\n", - " sort(column_or_label, descending=False, distinct=False)\n", - " \n", - "This describes the positions, names, and default values of the three arguments to `sort`. When calling this method, you can use either positional arguments or named arguments, so the following three calls do exactly the same thing.\n", + " sort(by, *more_by, descending=False, nulls_last=False, multithreaded=True, maintain_order=False)\n", + "\n", + "`by` names the column to sort by. The following two calls do exactly the same thing.\n", "\n", - " sort('SALARY', True)\n", " sort('SALARY', descending=True)\n", - " sort(column_or_label='SALARY', descending=True)\n", - " \n", - "When an argument is simply `True` or `False`, it's a useful convention to include the argument name so that it's more obvious what the argument value means." + " sort(by='SALARY', descending=True)\n", + "\n", + "When an argument is simply `True` or `False`, it's a useful convention to include the argument name so that it's more obvious what the argument value means.\n", + "\n", + "POLARS_CHANGE: A second positional argument is another column to sort by, not `descending`." ] } ], From cfd3471ede0c85570866a967c265f31c2e4a4766 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Thu, 15 Oct 2026 23:47:17 -0700 Subject: [PATCH 04/17] Ch.6.2 to polars nothing out of the ordinary --- chapters/06/2/Selecting_Rows.ipynb | 1278 +++++++++++----------------- 1 file changed, 519 insertions(+), 759 deletions(-) diff --git a/chapters/06/2/Selecting_Rows.ipynb b/chapters/06/2/Selecting_Rows.ipynb index 5740d2782..20d73416c 100644 --- a/chapters/06/2/Selecting_Rows.ipynb +++ b/chapters/06/2/Selecting_Rows.ipynb @@ -19,10 +19,8 @@ }, "outputs": [], "source": [ - "from datascience import *\n", - "import numpy as np\n", - "path_data = '../../../assets/data/'\n", - "np.set_printoptions(threshold=50)" + "import polars as pl\n", + "path_data = '../../../assets/data/'" ] }, { @@ -35,8 +33,8 @@ }, "outputs": [], "source": [ - "nba_salaries = Table.read_table(path_data + 'nba_salaries.csv')\n", - "nba = nba_salaries.relabeled(\"'15-'16 SALARY\", 'SALARY')" + "nba_salaries = pl.read_csv(path_data + 'nba_salaries.csv')\n", + "nba = nba_salaries.rename({\"'15-'16 SALARY\": \"SALARY\"})" ] }, { @@ -44,9 +42,9 @@ "metadata": {}, "source": [ "## Specified Rows\n", - "The Table method `take` does just that – it takes a specified set of rows. Its argument is a row index or array of indices, and it creates a new table consisting of only those rows.\n", + "The DataFrame method `gather` does just that – it takes a specified set of rows. Its argument is a row index or a sequence of indices, and it creates a new DataFrame consisting of only those rows.\n", "\n", - "For example, if we wanted just the first row of `nba`, we could use `take` as follows." + "For example, if we wanted just the first row of `nba`, we could use `gather` as follows." ] }, { @@ -55,67 +53,41 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 3, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Paul Millsap PF Atlanta Hawks 18.6717
Al Horford C Atlanta Hawks 12
Tiago Splitter C Atlanta Hawks 9.75625
Jeff Teague PG Atlanta Hawks 8
Kyle Korver SG Atlanta Hawks 5.74648
Thabo Sefolosha SF Atlanta Hawks 4
Mike Scott PF Atlanta Hawks 3.33333
Kent Bazemore SF Atlanta Hawks 2
Dennis Schroder PG Atlanta Hawks 1.7634
Tim Hardaway Jr. SG Atlanta Hawks 1.30452
\n", - "

... (407 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Paul Millsap | PF | Atlanta Hawks | 18.6717\n", - "Al Horford | C | Atlanta Hawks | 12\n", - "Tiago Splitter | C | Atlanta Hawks | 9.75625\n", - "Jeff Teague | PG | Atlanta Hawks | 8\n", - "Kyle Korver | SG | Atlanta Hawks | 5.74648\n", - "Thabo Sefolosha | SF | Atlanta Hawks | 4\n", - "Mike Scott | PF | Atlanta Hawks | 3.33333\n", - "Kent Bazemore | SF | Atlanta Hawks | 2\n", - "Dennis Schroder | PG | Atlanta Hawks | 1.7634\n", - "Tim Hardaway Jr. | SG | Atlanta Hawks | 1.30452\n", - "... (407 rows omitted)" + "shape: (417, 4)\n", + "┌─────────────────┬──────────┬────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═════════════════╪══════════╪════════════════════╪═══════════╡\n", + "│ Paul Millsap ┆ PF ┆ Atlanta Hawks ┆ 18.671659 │\n", + "│ Al Horford ┆ C ┆ Atlanta Hawks ┆ 12.0 │\n", + "│ Tiago Splitter ┆ C ┆ Atlanta Hawks ┆ 9.75625 │\n", + "│ Jeff Teague ┆ PG ┆ Atlanta Hawks ┆ 8.0 │\n", + "│ Kyle Korver ┆ SG ┆ Atlanta Hawks ┆ 5.746479 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Gary Neal ┆ PG ┆ Washington Wizards ┆ 2.139 │\n", + "│ DeJuan Blair ┆ C ┆ Washington Wizards ┆ 2.0 │\n", + "│ Kelly Oubre Jr. ┆ SF ┆ Washington Wizards ┆ 1.92024 │\n", + "│ Garrett Temple ┆ SG ┆ Washington Wizards ┆ 1.100602 │\n", + "│ Jarell Eddie ┆ SG ┆ Washington Wizards ┆ 0.561716 │\n", + "└─────────────────┴──────────┴────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Tiago Splitter""C""Atlanta Hawks"9.75625
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
…………
"Gary Neal""PG""Washington Wizards"2.139
"DeJuan Blair""C""Washington Wizards"2.0
"Kelly Oubre Jr.""SF""Washington Wizards"1.92024
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -128,40 +100,42 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 4, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Paul Millsap PF Atlanta Hawks 18.6717
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Paul Millsap | PF | Atlanta Hawks | 18.6717" + "shape: (1, 4)\n", + "┌──────────────┬──────────┬───────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞══════════════╪══════════╪═══════════════╪═══════════╡\n", + "│ Paul Millsap ┆ PF ┆ Atlanta Hawks ┆ 18.671659 │\n", + "└──────────────┴──────────┴───────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (1, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
" ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.take(0)" + "nba.gather(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This is a new table with just the single row that we specified.\n", + "This is a new DataFrame with just the single row that we specified.\n", "\n", "We could also get the fourth, fifth, and sixth rows by specifying a range of indices as the argument." ] @@ -172,48 +146,44 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 5, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Jeff Teague PG Atlanta Hawks 8
Kyle Korver SG Atlanta Hawks 5.74648
Thabo Sefolosha SF Atlanta Hawks 4
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Jeff Teague | PG | Atlanta Hawks | 8\n", - "Kyle Korver | SG | Atlanta Hawks | 5.74648\n", - "Thabo Sefolosha | SF | Atlanta Hawks | 4" + "shape: (3, 4)\n", + "┌─────────────────┬──────────┬───────────────┬──────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═════════════════╪══════════╪═══════════════╪══════════╡\n", + "│ Jeff Teague ┆ PG ┆ Atlanta Hawks ┆ 8.0 │\n", + "│ Kyle Korver ┆ SG ┆ Atlanta Hawks ┆ 5.746479 │\n", + "│ Thabo Sefolosha ┆ SF ┆ Atlanta Hawks ┆ 4.0 │\n", + "└─────────────────┴──────────┴───────────────┴──────────┘" + ], + "text/html": [ + "
\n", + "shape: (3, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
"Thabo Sefolosha""SF""Atlanta Hawks"4.0
" ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.take(np.arange(3, 6))" + "nba.gather(range(3, 6))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "If we want a table of the top 5 highest paid players, we can first sort the list by salary and then `take` the first five rows:" + "If we want a DataFrame of the top 5 highest paid players, we can first sort the rows by salary and then use `head` to keep the first five rows:" ] }, { @@ -222,49 +192,39 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 6, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Kobe Bryant SF Los Angeles Lakers 25
Joe Johnson SF Brooklyn Nets 24.8949
LeBron James SF Cleveland Cavaliers 22.9705
Carmelo Anthony SF New York Knicks 22.875
Dwight Howard C Houston Rockets 22.3594
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Kobe Bryant | SF | Los Angeles Lakers | 25\n", - "Joe Johnson | SF | Brooklyn Nets | 24.8949\n", - "LeBron James | SF | Cleveland Cavaliers | 22.9705\n", - "Carmelo Anthony | SF | New York Knicks | 22.875\n", - "Dwight Howard | C | Houston Rockets | 22.3594" + "shape: (5, 4)\n", + "┌─────────────────┬──────────┬─────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═════════════════╪══════════╪═════════════════════╪═══════════╡\n", + "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", + "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", + "│ LeBron James ┆ SF ┆ Cleveland Cavaliers ┆ 22.9705 │\n", + "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", + "│ Dwight Howard ┆ C ┆ Houston Rockets ┆ 22.359364 │\n", + "└─────────────────┴──────────┴─────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (5, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Carmelo Anthony""SF""New York Knicks"22.875
"Dwight Howard""C""Houston Rockets"22.359364
" ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.sort('SALARY', descending=True).take(np.arange(5))" + "nba.sort(\"SALARY\", descending=True).head(5)" ] }, { @@ -272,13 +232,11 @@ "metadata": {}, "source": [ "## Rows Corresponding to a Specified Feature\n", - "More often, we will want to access data in a set of rows that have a certain feature, but whose indices we don't know ahead of time. For example, we might want data on all the players who made more than $\\$10$ million, but we don't want to spend time counting rows in the sorted table.\n", + "More often, we will want to access data in a set of rows that have a certain feature, but whose indices we don't know ahead of time. For example, we might want data on all the players who made more than $\\$10$ million, but we don't want to spend time counting rows in the sorted DataFrame.\n", "\n", - "The method `where` does the job for us. Its output is a table with the same columns as the original but only the rows *where* the feature occurs.\n", + "The method `filter` does the job for us. Its output is a DataFrame with the same columns as the original but only the rows where the feature occurs.\n", "\n", - "The first argument of `where` is the label of the column that contains the information about whether or not a row has the feature we want. If the feature is \"made more than $\\$10$ million\", the column is `SALARY`.\n", - "\n", - "The second argument of `where` is a way of specifying the feature. A couple of examples will make the general method of specification easier to understand.\n", + "`filter` takes a condition built from `pl.col`. If the feature is \"made more than $\\$10$ million\", the column is `SALARY`.\n", "\n", "In the first example, we extract the data for all those who earned more than $\\$10$ million." ] @@ -289,80 +247,54 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 7, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Paul Millsap PF Atlanta Hawks 18.6717
Al Horford C Atlanta Hawks 12
Joe Johnson SF Brooklyn Nets 24.8949
Thaddeus Young PF Brooklyn Nets 11.236
Al Jefferson C Charlotte Hornets 13.5
Nicolas Batum SG Charlotte Hornets 13.1253
Kemba Walker PG Charlotte Hornets 12
Derrick Rose PG Chicago Bulls 20.0931
Jimmy Butler SG Chicago Bulls 16.4075
Joakim Noah C Chicago Bulls 13.4
\n", - "

... (59 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Paul Millsap | PF | Atlanta Hawks | 18.6717\n", - "Al Horford | C | Atlanta Hawks | 12\n", - "Joe Johnson | SF | Brooklyn Nets | 24.8949\n", - "Thaddeus Young | PF | Brooklyn Nets | 11.236\n", - "Al Jefferson | C | Charlotte Hornets | 13.5\n", - "Nicolas Batum | SG | Charlotte Hornets | 13.1253\n", - "Kemba Walker | PG | Charlotte Hornets | 12\n", - "Derrick Rose | PG | Chicago Bulls | 20.0931\n", - "Jimmy Butler | SG | Chicago Bulls | 16.4075\n", - "Joakim Noah | C | Chicago Bulls | 13.4\n", - "... (59 rows omitted)" + "shape: (69, 4)\n", + "┌────────────────┬──────────┬────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════════════╪══════════╪════════════════════╪═══════════╡\n", + "│ Paul Millsap ┆ PF ┆ Atlanta Hawks ┆ 18.671659 │\n", + "│ Al Horford ┆ C ┆ Atlanta Hawks ┆ 12.0 │\n", + "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", + "│ Thaddeus Young ┆ PF ┆ Brooklyn Nets ┆ 11.235955 │\n", + "│ Al Jefferson ┆ C ┆ Charlotte Hornets ┆ 13.5 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ DeMar DeRozan ┆ SG ┆ Toronto Raptors ┆ 10.05 │\n", + "│ Gordon Hayward ┆ SF ┆ Utah Jazz ┆ 15.40957 │\n", + "│ John Wall ┆ PG ┆ Washington Wizards ┆ 15.85195 │\n", + "│ Nene Hilario ┆ C ┆ Washington Wizards ┆ 13.0 │\n", + "│ Marcin Gortat ┆ C ┆ Washington Wizards ┆ 11.217391 │\n", + "└────────────────┴──────────┴────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (69, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Thaddeus Young""PF""Brooklyn Nets"11.235955
"Al Jefferson""C""Charlotte Hornets"13.5
…………
"DeMar DeRozan""SG""Toronto Raptors"10.05
"Gordon Hayward""SF""Utah Jazz"15.40957
"John Wall""PG""Washington Wizards"15.85195
"Nene Hilario""C""Washington Wizards"13.0
"Marcin Gortat""C""Washington Wizards"11.217391
" ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.where('SALARY', are.above(10))" + "nba.filter(pl.col(\"SALARY\") > 10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The use of the argument `are.above(10)` ensured that each selected row had a value of `SALARY` that was greater than 10.\n", + "The condition `pl.col(\"SALARY\") > 10` ensured that each selected row had a value of `SALARY` that was greater than 10.\n", "\n", - "There are 69 rows in the new table, corresponding to the 69 players who made more than $10$ million dollars. Arranging these rows in order makes the data easier to analyze. DeMar DeRozan of the Toronto Raptors was the \"poorest\" of this group, at a salary of just over $10$ million dollars." + "There are 69 rows in the new DataFrame, corresponding to the 69 players who made more than $10$ million dollars. Arranging these rows in order makes the data easier to analyze. DeMar DeRozan of the Toronto Raptors was the \"poorest\" of this group, at a salary of just over $10$ million dollars." ] }, { @@ -371,78 +303,52 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 8, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
DeMar DeRozan SG Toronto Raptors 10.05
Gerald Wallace SF Philadelphia 76ers 10.1059
Luol Deng SF Miami Heat 10.1516
Monta Ellis SG Indiana Pacers 10.3
Wilson Chandler SF Denver Nuggets 10.4494
Brendan Haywood C Cleveland Cavaliers 10.5225
Jrue Holiday PG New Orleans Pelicans 10.5955
Tyreke Evans SG New Orleans Pelicans 10.7346
Marcin Gortat C Washington Wizards 11.2174
Thaddeus Young PF Brooklyn Nets 11.236
\n", - "

... (59 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "DeMar DeRozan | SG | Toronto Raptors | 10.05\n", - "Gerald Wallace | SF | Philadelphia 76ers | 10.1059\n", - "Luol Deng | SF | Miami Heat | 10.1516\n", - "Monta Ellis | SG | Indiana Pacers | 10.3\n", - "Wilson Chandler | SF | Denver Nuggets | 10.4494\n", - "Brendan Haywood | C | Cleveland Cavaliers | 10.5225\n", - "Jrue Holiday | PG | New Orleans Pelicans | 10.5955\n", - "Tyreke Evans | SG | New Orleans Pelicans | 10.7346\n", - "Marcin Gortat | C | Washington Wizards | 11.2174\n", - "Thaddeus Young | PF | Brooklyn Nets | 11.236\n", - "... (59 rows omitted)" + "shape: (69, 4)\n", + "┌─────────────────┬──────────┬─────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═════════════════╪══════════╪═════════════════════╪═══════════╡\n", + "│ DeMar DeRozan ┆ SG ┆ Toronto Raptors ┆ 10.05 │\n", + "│ Gerald Wallace ┆ SF ┆ Philadelphia 76ers ┆ 10.105855 │\n", + "│ Luol Deng ┆ SF ┆ Miami Heat ┆ 10.151612 │\n", + "│ Monta Ellis ┆ SG ┆ Indiana Pacers ┆ 10.3 │\n", + "│ Wilson Chandler ┆ SF ┆ Denver Nuggets ┆ 10.449438 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Dwight Howard ┆ C ┆ Houston Rockets ┆ 22.359364 │\n", + "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", + "│ LeBron James ┆ SF ┆ Cleveland Cavaliers ┆ 22.9705 │\n", + "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", + "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", + "└─────────────────┴──────────┴─────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (69, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"DeMar DeRozan""SG""Toronto Raptors"10.05
"Gerald Wallace""SF""Philadelphia 76ers"10.105855
"Luol Deng""SF""Miami Heat"10.151612
"Monta Ellis""SG""Indiana Pacers"10.3
"Wilson Chandler""SF""Denver Nuggets"10.449438
…………
"Dwight Howard""C""Houston Rockets"22.359364
"Carmelo Anthony""SF""New York Knicks"22.875
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Kobe Bryant""SF""Los Angeles Lakers"25.0
" ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.where('SALARY', are.above(10)).sort('SALARY')" + "nba.filter(pl.col(\"SALARY\") > 10).sort(\"SALARY\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "How much did Stephen Curry make? For the answer, we have to access the row where the value of `PLAYER` is equal to `Stephen Curry`. That is placed a table consisting of just one line:" + "How much did Stephen Curry make? For the answer, we have to access the row where the value of `PLAYER` is equal to `Stephen Curry`. That is placed a DataFrame consisting of just one line:" ] }, { @@ -451,42 +357,44 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 9, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Stephen Curry PG Golden State Warriors 11.3708
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Stephen Curry | PG | Golden State Warriors | 11.3708" + "shape: (1, 4)\n", + "┌───────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═══════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", + "└───────────────┴──────────┴───────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (1, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Stephen Curry""PG""Golden State Warriors"11.370786
" ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.where('PLAYER', are.equal_to('Stephen Curry'))" + "nba.filter(pl.col(\"PLAYER\") == \"Stephen Curry\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Curry made just under $\\$11.4$ million dollars. That's a lot of money, but it's less than half the salary of LeBron James. You'll find that salary in the \"Top 5\" table earlier in this section, or you could find it replacing `'Stephen Curry'` by `'LeBron James'` in the line of code above.\n", + "Curry made just under $\\$11.4$ million dollars. That's a lot of money, but it's less than half the salary of LeBron James. You'll find that salary in the \"Top 5\" DataFrame earlier in this section, or you could find it replacing `'Stephen Curry'` by `'LeBron James'` in the line of code above.\n", "\n", - "In the code, `are` is used again, but this time with the *predicate* `equal_to` instead of `above`. Thus for example you can get a table of all the Warriors:" + "Equality is written with `==`, just as `>` selects values above a cutoff. Thus for example you can get a DataFrame of all the Warriors:" ] }, { @@ -495,79 +403,58 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 10, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Klay Thompson SG Golden State Warriors 15.501
Draymond Green PF Golden State Warriors 14.2609
Andrew Bogut C Golden State Warriors 13.8
Andre Iguodala SF Golden State Warriors 11.7105
Stephen Curry PG Golden State Warriors 11.3708
Jason Thompson PF Golden State Warriors 7.00847
Shaun Livingston PG Golden State Warriors 5.54373
Harrison Barnes SF Golden State Warriors 3.8734
Marreese Speights C Golden State Warriors 3.815
Leandro Barbosa SG Golden State Warriors 2.5
Festus Ezeli C Golden State Warriors 2.00875
Brandon Rush SF Golden State Warriors 1.27096
Kevon Looney SF Golden State Warriors 1.13196
Anderson Varejao PF Golden State Warriors 0.289755
" - ], "text/plain": [ - "" + "shape: (14, 4)\n", + "┌───────────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═══════════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Klay Thompson ┆ SG ┆ Golden State Warriors ┆ 15.501 │\n", + "│ Draymond Green ┆ PF ┆ Golden State Warriors ┆ 14.26087 │\n", + "│ Andrew Bogut ┆ C ┆ Golden State Warriors ┆ 13.8 │\n", + "│ Andre Iguodala ┆ SF ┆ Golden State Warriors ┆ 11.710456 │\n", + "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", + "│ Jason Thompson ┆ PF ┆ Golden State Warriors ┆ 7.008475 │\n", + "│ Shaun Livingston ┆ PG ┆ Golden State Warriors ┆ 5.543725 │\n", + "│ Harrison Barnes ┆ SF ┆ Golden State Warriors ┆ 3.873398 │\n", + "│ Marreese Speights ┆ C ┆ Golden State Warriors ┆ 3.815 │\n", + "│ Leandro Barbosa ┆ SG ┆ Golden State Warriors ┆ 2.5 │\n", + "│ Festus Ezeli ┆ C ┆ Golden State Warriors ┆ 2.008748 │\n", + "│ Brandon Rush ┆ SF ┆ Golden State Warriors ┆ 1.270964 │\n", + "│ Kevon Looney ┆ SF ┆ Golden State Warriors ┆ 1.13196 │\n", + "│ Anderson Varejao ┆ PF ┆ Golden State Warriors ┆ 0.289755 │\n", + "└───────────────────┴──────────┴───────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
"Jason Thompson""PF""Golden State Warriors"7.008475
"Shaun Livingston""PG""Golden State Warriors"5.543725
"Harrison Barnes""SF""Golden State Warriors"3.873398
"Marreese Speights""C""Golden State Warriors"3.815
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" ] - }, - "metadata": {}, - "output_type": "display_data" + } } ], "source": [ - "nba.where('TEAM', are.equal_to('Golden State Warriors')).show()" + "with pl.Config(tbl_rows=-1):\n", + " display(nba.filter(pl.col(\"TEAM\") == \"Golden State Warriors\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This portion of the table is already sorted by salary, because the original table listed players sorted by salary within the same team. The `.show()` at the end of the line ensures that all rows are shown, not just the first 10.\n", + "This portion of the DataFrame is already sorted by salary, because the original DataFrame listed players sorted by salary within the same team. `pl.Config(tbl_rows=-1)` makes `display` show every row. Without it, the display shows the first five and last five rows.\n", "\n", - "It is so common to ask for the rows for which some column is equal to some value that the `are.equal_to` call is optional. Instead, the `where` method can be called with only a column name and a value to achieve the same effect." + "Equality uses `==` inside `filter`." ] }, { @@ -576,71 +463,45 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 11, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Danilo Gallinari SF Denver Nuggets 14
Kenneth Faried PF Denver Nuggets 11.236
Wilson Chandler SF Denver Nuggets 10.4494
JJ Hickson C Denver Nuggets 5.6135
Jameer Nelson PG Denver Nuggets 4.345
Will Barton SF Denver Nuggets 3.53333
Emmanuel Mudiay PG Denver Nuggets 3.10224
Darrell Arthur PF Denver Nuggets 2.814
Jusuf Nurkic C Denver Nuggets 1.842
Joffrey Lauvergne C Denver Nuggets 1.70972
\n", - "

... (4 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Danilo Gallinari | SF | Denver Nuggets | 14\n", - "Kenneth Faried | PF | Denver Nuggets | 11.236\n", - "Wilson Chandler | SF | Denver Nuggets | 10.4494\n", - "JJ Hickson | C | Denver Nuggets | 5.6135\n", - "Jameer Nelson | PG | Denver Nuggets | 4.345\n", - "Will Barton | SF | Denver Nuggets | 3.53333\n", - "Emmanuel Mudiay | PG | Denver Nuggets | 3.10224\n", - "Darrell Arthur | PF | Denver Nuggets | 2.814\n", - "Jusuf Nurkic | C | Denver Nuggets | 1.842\n", - "Joffrey Lauvergne | C | Denver Nuggets | 1.70972\n", - "... (4 rows omitted)" + "shape: (14, 4)\n", + "┌─────────────────────┬──────────┬────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═════════════════════╪══════════╪════════════════╪═══════════╡\n", + "│ Danilo Gallinari ┆ SF ┆ Denver Nuggets ┆ 14.0 │\n", + "│ Kenneth Faried ┆ PF ┆ Denver Nuggets ┆ 11.235955 │\n", + "│ Wilson Chandler ┆ SF ┆ Denver Nuggets ┆ 10.449438 │\n", + "│ JJ Hickson ┆ C ┆ Denver Nuggets ┆ 5.6135 │\n", + "│ Jameer Nelson ┆ PG ┆ Denver Nuggets ┆ 4.345 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Joffrey Lauvergne ┆ C ┆ Denver Nuggets ┆ 1.709719 │\n", + "│ Gary Harris ┆ SG ┆ Denver Nuggets ┆ 1.58448 │\n", + "│ Nikola Jokic ┆ C ┆ Denver Nuggets ┆ 1.3 │\n", + "│ Kostas Papanikolaou ┆ SF ┆ Denver Nuggets ┆ 0.800321 │\n", + "│ Sean Kilpatrick ┆ SG ┆ Denver Nuggets ┆ 0.099418 │\n", + "└─────────────────────┴──────────┴────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Danilo Gallinari""SF""Denver Nuggets"14.0
"Kenneth Faried""PF""Denver Nuggets"11.235955
"Wilson Chandler""SF""Denver Nuggets"10.449438
"JJ Hickson""C""Denver Nuggets"5.6135
"Jameer Nelson""PG""Denver Nuggets"4.345
…………
"Joffrey Lauvergne""C""Denver Nuggets"1.709719
"Gary Harris""SG""Denver Nuggets"1.58448
"Nikola Jokic""C""Denver Nuggets"1.3
"Kostas Papanikolaou""SF""Denver Nuggets"0.800321
"Sean Kilpatrick""SG""Denver Nuggets"0.099418
" ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.where('TEAM', 'Denver Nuggets') # equivalent to nba.where('TEAM', are.equal_to('Denver Nuggets'))" + "nba.filter(pl.col(\"TEAM\") == \"Denver Nuggets\")" ] }, { @@ -648,7 +509,9 @@ "metadata": {}, "source": [ "## Multiple Features\n", - "You can access rows that have multiple specified features, by using `where` repeatedly. For example, here is a way to extract all the Point Guards whose salaries were over $\\$15$ million." + "You can access rows that have multiple specified features, by using `filter` repeatedly. For example, here is a way to extract all the Point Guards whose salaries were over $\\$15$ million.\n", + "\n", + "POLARS_CHANGE: The same rows can be selected in one call, `nba.filter((pl.col(\"POSITION\") == \"PG\") & (pl.col(\"SALARY\") > 15))`." ] }, { @@ -657,49 +520,39 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 12, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Derrick Rose PG Chicago Bulls 20.0931
Kyrie Irving PG Cleveland Cavaliers 16.4075
Chris Paul PG Los Angeles Clippers 21.4687
Russell Westbrook PG Oklahoma City Thunder 16.7442
John Wall PG Washington Wizards 15.852
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Derrick Rose | PG | Chicago Bulls | 20.0931\n", - "Kyrie Irving | PG | Cleveland Cavaliers | 16.4075\n", - "Chris Paul | PG | Los Angeles Clippers | 21.4687\n", - "Russell Westbrook | PG | Oklahoma City Thunder | 16.7442\n", - "John Wall | PG | Washington Wizards | 15.852" + "shape: (5, 4)\n", + "┌───────────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═══════════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Derrick Rose ┆ PG ┆ Chicago Bulls ┆ 20.093064 │\n", + "│ Kyrie Irving ┆ PG ┆ Cleveland Cavaliers ┆ 16.407501 │\n", + "│ Chris Paul ┆ PG ┆ Los Angeles Clippers ┆ 21.468695 │\n", + "│ Russell Westbrook ┆ PG ┆ Oklahoma City Thunder ┆ 16.744218 │\n", + "│ John Wall ┆ PG ┆ Washington Wizards ┆ 15.85195 │\n", + "└───────────────────┴──────────┴───────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (5, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Derrick Rose""PG""Chicago Bulls"20.093064
"Kyrie Irving""PG""Cleveland Cavaliers"16.407501
"Chris Paul""PG""Los Angeles Clippers"21.468695
"Russell Westbrook""PG""Oklahoma City Thunder"16.744218
"John Wall""PG""Washington Wizards"15.85195
" ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.where('POSITION', 'PG').where('SALARY', are.above(15))" + "nba.filter(pl.col(\"POSITION\") == \"PG\").filter(pl.col(\"SALARY\") > 15)" ] }, { @@ -707,9 +560,9 @@ "metadata": {}, "source": [ "## General Form\n", - "By now you will have realized that the general way to create a new table by selecting rows with a given feature is to use `where` and `are` with the appropriate condition:\n", + "By now you will have realized that the general way to create a new DataFrame by selecting rows with a given feature is to use `filter` and `pl.col` with the appropriate condition:\n", "\n", - "`original_table_name.where(column_label_string, are.condition)`" + "`df.filter(pl.col(\"column_name\") value)`" ] }, { @@ -718,59 +571,52 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 13, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Luol Deng SF Miami Heat 10.1516
Gerald Wallace SF Philadelphia 76ers 10.1059
Danny Green SG San Antonio Spurs 10
DeMar DeRozan SG Toronto Raptors 10.05
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Luol Deng | SF | Miami Heat | 10.1516\n", - "Gerald Wallace | SF | Philadelphia 76ers | 10.1059\n", - "Danny Green | SG | San Antonio Spurs | 10\n", - "DeMar DeRozan | SG | Toronto Raptors | 10.05" + "shape: (4, 4)\n", + "┌────────────────┬──────────┬────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════════════╪══════════╪════════════════════╪═══════════╡\n", + "│ Luol Deng ┆ SF ┆ Miami Heat ┆ 10.151612 │\n", + "│ Gerald Wallace ┆ SF ┆ Philadelphia 76ers ┆ 10.105855 │\n", + "│ Danny Green ┆ SG ┆ San Antonio Spurs ┆ 10.0 │\n", + "│ DeMar DeRozan ┆ SG ┆ Toronto Raptors ┆ 10.05 │\n", + "└────────────────┴──────────┴────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (4, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Luol Deng""SF""Miami Heat"10.151612
"Gerald Wallace""SF""Philadelphia 76ers"10.105855
"Danny Green""SG""San Antonio Spurs"10.0
"DeMar DeRozan""SG""Toronto Raptors"10.05
" ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.where('SALARY', are.between(10, 10.3))" + "nba.filter(pl.col(\"SALARY\").is_between(10, 10.3, closed=\"left\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Notice that the table above includes Danny Green who made $\\$10$ million, but *not* Monta Ellis who made $\\$10.3$ million. As elsewhere in Python, the range `between` includes the left end but not the right." + "Notice that the DataFrame above includes Danny Green who made $\\$10$ million, but *not* Monta Ellis who made $\\$10.3$ million. `is_between` with `closed=\"left\"` includes the left end but not the right." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "If we specify a condition that isn't satisfied by any row, we get a table with column labels but no rows." + "If we specify a condition that isn't satisfied by any row, we get a DataFrame with column labels but no rows." ] }, { @@ -779,29 +625,34 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 14, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY" + "shape: (0, 4)\n", + "┌────────┬──────────┬──────┬────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════╪══════════╪══════╪════════╡\n", + "└────────┴──────────┴──────┴────────┘" + ], + "text/html": [ + "
\n", + "shape: (0, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
" ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.where('PLAYER', are.equal_to('Barack Obama'))" + "nba.filter(pl.col(\"PLAYER\") == \"Barack Obama\")" ] }, { @@ -809,31 +660,31 @@ "metadata": {}, "source": [ "## Some More Conditions\n", - "Here are some predicates of `are` that you might find useful. Note that `x` and `y` are numbers, `STRING` is a string, and `Z` is either a number or a string; you have to specify these depending on the feature you want.\n", + "Here are some conditions you can use in `filter`. Note that `x` and `y` are numbers, `S` is a string, and `Z` is either a number or a string; you have to specify these depending on the feature you want.\n", "\n", - "| **Predicate** | Description |\n", - "|----------------------------|------------------------------------------|\n", - "| `are.equal_to(Z)` | Equal to `Z` | \n", - "| `are.above(x)` | Greater than `x` |\n", - "| `are.above_or_equal_to(x)` | Greater than or equal to `x` |\n", - "| `are.below(x)` | Less than `x` |\n", - "| `are.below_or_equal_to(x)` | Less than or equal to `x` |\n", - "| `are.between(x, y)` | Greater than or equal to `x`, and less than `y` |\n", - "| `are.strictly_between(x, y)` | Greater than `x` and less than `y` |\n", - "| `are.between_or_equal_to(x, y)` | Greater than or equal to `x`, and less than or equal to `y` |\n", - "| `are.containing(S)` | Contains the string `S` | " + "| **Condition** | Description |\n", + "|---|---|\n", + "| `pl.col(\"col\") == Z` | Equal to `Z` |\n", + "| `pl.col(\"col\") > x` | Greater than `x` |\n", + "| `pl.col(\"col\") >= x` | Greater than or equal to `x` |\n", + "| `pl.col(\"col\") < x` | Less than `x` |\n", + "| `pl.col(\"col\") <= x` | Less than or equal to `x` |\n", + "| `pl.col(\"col\").is_between(x, y, closed=\"left\")` | Greater than or equal to `x`, and less than `y` |\n", + "| `pl.col(\"col\").is_between(x, y, closed=\"none\")` | Greater than `x` and less than `y` |\n", + "| `pl.col(\"col\").is_between(x, y, closed=\"both\")` | Greater than or equal to `x`, and less than or equal to `y` |\n", + "| `pl.col(\"col\").str.contains(S)` | Contains the string `S` |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "You can also specify the negation of any of these conditions, by using `.not_` before the condition:\n", + "You can also negate any of these conditions by putting `~` in front of the comparison:\n", "\n", - "| **Predicate** | Description |\n", - "|----------------------------|------------------------------------------|\n", - "| `are.not_equal_to(Z)` | Not equal to `Z` | \n", - "| `are.not_above(x)` | Not above `x` |" + "| **Condition** | Description |\n", + "|---|---|\n", + "| `pl.col(\"col\") != Z` | Not equal to `Z` |\n", + "| `~(pl.col(\"col\") > x)` | Not above `x` |" ] }, { @@ -854,7 +705,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The use of `are.containing` can help save some typing. For example, you can just specify `Warriors` instead of `Golden State Warriors`:" + "The use of `str.contains` can help save some typing. For example, you can just specify `Warriors` instead of `Golden State Warriors`:" ] }, { @@ -863,70 +714,49 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 15, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Klay Thompson SG Golden State Warriors 15.501
Draymond Green PF Golden State Warriors 14.2609
Andrew Bogut C Golden State Warriors 13.8
Andre Iguodala SF Golden State Warriors 11.7105
Stephen Curry PG Golden State Warriors 11.3708
Jason Thompson PF Golden State Warriors 7.00847
Shaun Livingston PG Golden State Warriors 5.54373
Harrison Barnes SF Golden State Warriors 3.8734
Marreese Speights C Golden State Warriors 3.815
Leandro Barbosa SG Golden State Warriors 2.5
Festus Ezeli C Golden State Warriors 2.00875
Brandon Rush SF Golden State Warriors 1.27096
Kevon Looney SF Golden State Warriors 1.13196
Anderson Varejao PF Golden State Warriors 0.289755
" - ], "text/plain": [ - "" + "shape: (14, 4)\n", + "┌───────────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═══════════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Klay Thompson ┆ SG ┆ Golden State Warriors ┆ 15.501 │\n", + "│ Draymond Green ┆ PF ┆ Golden State Warriors ┆ 14.26087 │\n", + "│ Andrew Bogut ┆ C ┆ Golden State Warriors ┆ 13.8 │\n", + "│ Andre Iguodala ┆ SF ┆ Golden State Warriors ┆ 11.710456 │\n", + "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", + "│ Jason Thompson ┆ PF ┆ Golden State Warriors ┆ 7.008475 │\n", + "│ Shaun Livingston ┆ PG ┆ Golden State Warriors ┆ 5.543725 │\n", + "│ Harrison Barnes ┆ SF ┆ Golden State Warriors ┆ 3.873398 │\n", + "│ Marreese Speights ┆ C ┆ Golden State Warriors ┆ 3.815 │\n", + "│ Leandro Barbosa ┆ SG ┆ Golden State Warriors ┆ 2.5 │\n", + "│ Festus Ezeli ┆ C ┆ Golden State Warriors ┆ 2.008748 │\n", + "│ Brandon Rush ┆ SF ┆ Golden State Warriors ┆ 1.270964 │\n", + "│ Kevon Looney ┆ SF ┆ Golden State Warriors ┆ 1.13196 │\n", + "│ Anderson Varejao ┆ PF ┆ Golden State Warriors ┆ 0.289755 │\n", + "└───────────────────┴──────────┴───────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
"Jason Thompson""PF""Golden State Warriors"7.008475
"Shaun Livingston""PG""Golden State Warriors"5.543725
"Harrison Barnes""SF""Golden State Warriors"3.873398
"Marreese Speights""C""Golden State Warriors"3.815
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" ] - }, - "metadata": {}, - "output_type": "display_data" + } } ], "source": [ - "nba.where('TEAM', are.containing('Warriors')).show()" + "with pl.Config(tbl_rows=-1):\n", + " display(nba.filter(pl.col(\"TEAM\").str.contains(\"Warriors\")))" ] }, { @@ -942,71 +772,45 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 16, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Jeff Teague PG Atlanta Hawks 8
Kyle Korver SG Atlanta Hawks 5.74648
Dennis Schroder PG Atlanta Hawks 1.7634
Tim Hardaway Jr. SG Atlanta Hawks 1.30452
Jason Richardson SG Atlanta Hawks 0.947276
Lamar Patterson SG Atlanta Hawks 0.525093
Terran Petteway SG Atlanta Hawks 0.525093
Avery Bradley PG Boston Celtics 7.73034
Isaiah Thomas PG Boston Celtics 6.91287
Marcus Smart PG Boston Celtics 3.43104
\n", - "

... (171 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Jeff Teague | PG | Atlanta Hawks | 8\n", - "Kyle Korver | SG | Atlanta Hawks | 5.74648\n", - "Dennis Schroder | PG | Atlanta Hawks | 1.7634\n", - "Tim Hardaway Jr. | SG | Atlanta Hawks | 1.30452\n", - "Jason Richardson | SG | Atlanta Hawks | 0.947276\n", - "Lamar Patterson | SG | Atlanta Hawks | 0.525093\n", - "Terran Petteway | SG | Atlanta Hawks | 0.525093\n", - "Avery Bradley | PG | Boston Celtics | 7.73034\n", - "Isaiah Thomas | PG | Boston Celtics | 6.91287\n", - "Marcus Smart | PG | Boston Celtics | 3.43104\n", - "... (171 rows omitted)" + "shape: (181, 4)\n", + "┌──────────────────┬──────────┬────────────────────┬──────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞══════════════════╪══════════╪════════════════════╪══════════╡\n", + "│ Jeff Teague ┆ PG ┆ Atlanta Hawks ┆ 8.0 │\n", + "│ Kyle Korver ┆ SG ┆ Atlanta Hawks ┆ 5.746479 │\n", + "│ Dennis Schroder ┆ PG ┆ Atlanta Hawks ┆ 1.7634 │\n", + "│ Tim Hardaway Jr. ┆ SG ┆ Atlanta Hawks ┆ 1.30452 │\n", + "│ Jason Richardson ┆ SG ┆ Atlanta Hawks ┆ 0.947276 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Alan Anderson ┆ SG ┆ Washington Wizards ┆ 4.0 │\n", + "│ Ramon Sessions ┆ PG ┆ Washington Wizards ┆ 2.170465 │\n", + "│ Gary Neal ┆ PG ┆ Washington Wizards ┆ 2.139 │\n", + "│ Garrett Temple ┆ SG ┆ Washington Wizards ┆ 1.100602 │\n", + "│ Jarell Eddie ┆ SG ┆ Washington Wizards ┆ 0.561716 │\n", + "└──────────────────┴──────────┴────────────────────┴──────────┘" + ], + "text/html": [ + "
\n", + "shape: (181, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
"Dennis Schroder""PG""Atlanta Hawks"1.7634
"Tim Hardaway Jr.""SG""Atlanta Hawks"1.30452
"Jason Richardson""SG""Atlanta Hawks"0.947276
…………
"Alan Anderson""SG""Washington Wizards"4.0
"Ramon Sessions""PG""Washington Wizards"2.170465
"Gary Neal""PG""Washington Wizards"2.139
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.where('POSITION', are.containing('G'))" + "nba.filter(pl.col(\"POSITION\").str.contains(\"G\"))" ] }, { @@ -1022,73 +826,51 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 17, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Joe Johnson SF Brooklyn Nets 24.8949
Derrick Rose PG Chicago Bulls 20.0931
Dwight Howard C Houston Rockets 22.3594
Chris Paul PG Los Angeles Clippers 21.4687
Kobe Bryant SF Los Angeles Lakers 25
Chris Bosh PF Miami Heat 22.1927
Dwyane Wade SG Miami Heat 20
Carmelo Anthony SF New York Knicks 22.875
Kevin Durant SF Oklahoma City Thunder 20.1586
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Joe Johnson | SF | Brooklyn Nets | 24.8949\n", - "Derrick Rose | PG | Chicago Bulls | 20.0931\n", - "Dwight Howard | C | Houston Rockets | 22.3594\n", - "Chris Paul | PG | Los Angeles Clippers | 21.4687\n", - "Kobe Bryant | SF | Los Angeles Lakers | 25\n", - "Chris Bosh | PF | Miami Heat | 22.1927\n", - "Dwyane Wade | SG | Miami Heat | 20\n", - "Carmelo Anthony | SF | New York Knicks | 22.875\n", - "Kevin Durant | SF | Oklahoma City Thunder | 20.1586" + "shape: (9, 4)\n", + "┌─────────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═════════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", + "│ Derrick Rose ┆ PG ┆ Chicago Bulls ┆ 20.093064 │\n", + "│ Dwight Howard ┆ C ┆ Houston Rockets ┆ 22.359364 │\n", + "│ Chris Paul ┆ PG ┆ Los Angeles Clippers ┆ 21.468695 │\n", + "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", + "│ Chris Bosh ┆ PF ┆ Miami Heat ┆ 22.19273 │\n", + "│ Dwyane Wade ┆ SG ┆ Miami Heat ┆ 20.0 │\n", + "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", + "│ Kevin Durant ┆ SF ┆ Oklahoma City Thunder ┆ 20.158622 │\n", + "└─────────────────┴──────────┴───────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (9, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Derrick Rose""PG""Chicago Bulls"20.093064
"Dwight Howard""C""Houston Rockets"22.359364
"Chris Paul""PG""Los Angeles Clippers"21.468695
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Chris Bosh""PF""Miami Heat"22.19273
"Dwyane Wade""SG""Miami Heat"20.0
"Carmelo Anthony""SF""New York Knicks"22.875
"Kevin Durant""SF""Oklahoma City Thunder"20.158622
" ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "other_than_Cavs = nba.where('TEAM', are.not_equal_to('Cleveland Cavaliers'))\n", - "other_than_Cavs.where('SALARY', are.not_below(20))" + "other_than_Cavs = nba.filter(pl.col(\"TEAM\") != \"Cleveland Cavaliers\")\n", + "other_than_Cavs.filter(~(pl.col(\"SALARY\") < 20))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The same table can be created in many ways. Here is another, and no doubt you can think of more." + "The same DataFrame can be created in many ways. Here is another, and no doubt you can think of more." ] }, { @@ -1097,72 +879,50 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 18, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Joe Johnson SF Brooklyn Nets 24.8949
Derrick Rose PG Chicago Bulls 20.0931
Dwight Howard C Houston Rockets 22.3594
Chris Paul PG Los Angeles Clippers 21.4687
Kobe Bryant SF Los Angeles Lakers 25
Chris Bosh PF Miami Heat 22.1927
Dwyane Wade SG Miami Heat 20
Carmelo Anthony SF New York Knicks 22.875
Kevin Durant SF Oklahoma City Thunder 20.1586
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Joe Johnson | SF | Brooklyn Nets | 24.8949\n", - "Derrick Rose | PG | Chicago Bulls | 20.0931\n", - "Dwight Howard | C | Houston Rockets | 22.3594\n", - "Chris Paul | PG | Los Angeles Clippers | 21.4687\n", - "Kobe Bryant | SF | Los Angeles Lakers | 25\n", - "Chris Bosh | PF | Miami Heat | 22.1927\n", - "Dwyane Wade | SG | Miami Heat | 20\n", - "Carmelo Anthony | SF | New York Knicks | 22.875\n", - "Kevin Durant | SF | Oklahoma City Thunder | 20.1586" + "shape: (9, 4)\n", + "┌─────────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═════════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", + "│ Derrick Rose ┆ PG ┆ Chicago Bulls ┆ 20.093064 │\n", + "│ Dwight Howard ┆ C ┆ Houston Rockets ┆ 22.359364 │\n", + "│ Chris Paul ┆ PG ┆ Los Angeles Clippers ┆ 21.468695 │\n", + "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", + "│ Chris Bosh ┆ PF ┆ Miami Heat ┆ 22.19273 │\n", + "│ Dwyane Wade ┆ SG ┆ Miami Heat ┆ 20.0 │\n", + "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", + "│ Kevin Durant ┆ SF ┆ Oklahoma City Thunder ┆ 20.158622 │\n", + "└─────────────────┴──────────┴───────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (9, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Derrick Rose""PG""Chicago Bulls"20.093064
"Dwight Howard""C""Houston Rockets"22.359364
"Chris Paul""PG""Los Angeles Clippers"21.468695
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Chris Bosh""PF""Miami Heat"22.19273
"Dwyane Wade""SG""Miami Heat"20.0
"Carmelo Anthony""SF""New York Knicks"22.875
"Kevin Durant""SF""Oklahoma City Thunder"20.158622
" ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "other_than_Cavs.where('SALARY', are.above_or_equal_to(20))" + "other_than_Cavs.filter(pl.col(\"SALARY\") >= 20)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "As you can see, the use of `where` with `are` gives you great flexibility in accessing rows with features that interest you. Don't hesitate to experiment!" + "As you can see, the use of `filter` with `pl.col` gives you great flexibility in accessing rows with features that interest you. Don't hesitate to experiment!" ] } ], From 06937c351ed106184bc051ea7923f75f2aecf39a Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 01:24:16 -0700 Subject: [PATCH 05/17] feat(6.2) --- chapters/06/2/Selecting_Rows.ipynb | 446 ++++++++++++++--------------- 1 file changed, 223 insertions(+), 223 deletions(-) diff --git a/chapters/06/2/Selecting_Rows.ipynb b/chapters/06/2/Selecting_Rows.ipynb index 20d73416c..901b814fd 100644 --- a/chapters/06/2/Selecting_Rows.ipynb +++ b/chapters/06/2/Selecting_Rows.ipynb @@ -53,10 +53,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 3, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Tiago Splitter""C""Atlanta Hawks"9.75625
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
…………
"Gary Neal""PG""Washington Wizards"2.139
"DeJuan Blair""C""Washington Wizards"2.0
"Kelly Oubre Jr.""SF""Washington Wizards"1.92024
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" + ], "text/plain": [ "shape: (417, 4)\n", "┌─────────────────┬──────────┬────────────────────┬───────────┐\n", @@ -76,18 +83,11 @@ "│ Garrett Temple ┆ SG ┆ Washington Wizards ┆ 1.100602 │\n", "│ Jarell Eddie ┆ SG ┆ Washington Wizards ┆ 0.561716 │\n", "└─────────────────┴──────────┴────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Tiago Splitter""C""Atlanta Hawks"9.75625
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
…………
"Gary Neal""PG""Washington Wizards"2.139
"DeJuan Blair""C""Washington Wizards"2.0
"Kelly Oubre Jr.""SF""Washington Wizards"1.92024
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" ] - } + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -100,20 +100,7 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 4, - "metadata": {}, "data": { - "text/plain": [ - "shape: (1, 4)\n", - "┌──────────────┬──────────┬───────────────┬───────────┐\n", - "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", - "│ --- ┆ --- ┆ --- ┆ --- │\n", - "│ str ┆ str ┆ str ┆ f64 │\n", - "╞══════════════╪══════════╪═══════════════╪═══════════╡\n", - "│ Paul Millsap ┆ PF ┆ Atlanta Hawks ┆ 18.671659 │\n", - "└──────────────┴──────────┴───────────────┴───────────┘" - ], "text/html": [ "
\n", "shape: (1, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
" + ], + "text/plain": [ + "shape: (1, 4)\n", + "┌──────────────┬──────────┬───────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞══════════════╪══════════╪═══════════════╪═══════════╡\n", + "│ Paul Millsap ┆ PF ┆ Atlanta Hawks ┆ 18.671659 │\n", + "└──────────────┴──────────┴───────────────┴───────────┘" ] - } + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -146,10 +146,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 5, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (3, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
"Thabo Sefolosha""SF""Atlanta Hawks"4.0
" + ], "text/plain": [ "shape: (3, 4)\n", "┌─────────────────┬──────────┬───────────────┬──────────┐\n", @@ -161,18 +168,11 @@ "│ Kyle Korver ┆ SG ┆ Atlanta Hawks ┆ 5.746479 │\n", "│ Thabo Sefolosha ┆ SF ┆ Atlanta Hawks ┆ 4.0 │\n", "└─────────────────┴──────────┴───────────────┴──────────┘" - ], - "text/html": [ - "
\n", - "shape: (3, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
"Thabo Sefolosha""SF""Atlanta Hawks"4.0
" ] - } + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -192,10 +192,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 6, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (5, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Carmelo Anthony""SF""New York Knicks"22.875
"Dwight Howard""C""Houston Rockets"22.359364
" + ], "text/plain": [ "shape: (5, 4)\n", "┌─────────────────┬──────────┬─────────────────────┬───────────┐\n", @@ -209,18 +216,11 @@ "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", "│ Dwight Howard ┆ C ┆ Houston Rockets ┆ 22.359364 │\n", "└─────────────────┴──────────┴─────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (5, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Carmelo Anthony""SF""New York Knicks"22.875
"Dwight Howard""C""Houston Rockets"22.359364
" ] - } + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -247,10 +247,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 7, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (69, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Thaddeus Young""PF""Brooklyn Nets"11.235955
"Al Jefferson""C""Charlotte Hornets"13.5
…………
"DeMar DeRozan""SG""Toronto Raptors"10.05
"Gordon Hayward""SF""Utah Jazz"15.40957
"John Wall""PG""Washington Wizards"15.85195
"Nene Hilario""C""Washington Wizards"13.0
"Marcin Gortat""C""Washington Wizards"11.217391
" + ], "text/plain": [ "shape: (69, 4)\n", "┌────────────────┬──────────┬────────────────────┬───────────┐\n", @@ -270,18 +277,11 @@ "│ Nene Hilario ┆ C ┆ Washington Wizards ┆ 13.0 │\n", "│ Marcin Gortat ┆ C ┆ Washington Wizards ┆ 11.217391 │\n", "└────────────────┴──────────┴────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (69, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Thaddeus Young""PF""Brooklyn Nets"11.235955
"Al Jefferson""C""Charlotte Hornets"13.5
…………
"DeMar DeRozan""SG""Toronto Raptors"10.05
"Gordon Hayward""SF""Utah Jazz"15.40957
"John Wall""PG""Washington Wizards"15.85195
"Nene Hilario""C""Washington Wizards"13.0
"Marcin Gortat""C""Washington Wizards"11.217391
" ] - } + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -303,10 +303,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 8, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (69, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"DeMar DeRozan""SG""Toronto Raptors"10.05
"Gerald Wallace""SF""Philadelphia 76ers"10.105855
"Luol Deng""SF""Miami Heat"10.151612
"Monta Ellis""SG""Indiana Pacers"10.3
"Wilson Chandler""SF""Denver Nuggets"10.449438
…………
"Dwight Howard""C""Houston Rockets"22.359364
"Carmelo Anthony""SF""New York Knicks"22.875
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Kobe Bryant""SF""Los Angeles Lakers"25.0
" + ], "text/plain": [ "shape: (69, 4)\n", "┌─────────────────┬──────────┬─────────────────────┬───────────┐\n", @@ -326,18 +333,11 @@ "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", "└─────────────────┴──────────┴─────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (69, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"DeMar DeRozan""SG""Toronto Raptors"10.05
"Gerald Wallace""SF""Philadelphia 76ers"10.105855
"Luol Deng""SF""Miami Heat"10.151612
"Monta Ellis""SG""Indiana Pacers"10.3
"Wilson Chandler""SF""Denver Nuggets"10.449438
…………
"Dwight Howard""C""Houston Rockets"22.359364
"Carmelo Anthony""SF""New York Knicks"22.875
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Kobe Bryant""SF""Los Angeles Lakers"25.0
" ] - } + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -357,20 +357,7 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 9, - "metadata": {}, "data": { - "text/plain": [ - "shape: (1, 4)\n", - "┌───────────────┬──────────┬───────────────────────┬───────────┐\n", - "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", - "│ --- ┆ --- ┆ --- ┆ --- │\n", - "│ str ┆ str ┆ str ┆ f64 │\n", - "╞═══════════════╪══════════╪═══════════════════════╪═══════════╡\n", - "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", - "└───────────────┴──────────┴───────────────────────┴───────────┘" - ], "text/html": [ "
\n", "shape: (1, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Stephen Curry""PG""Golden State Warriors"11.370786
" + ], + "text/plain": [ + "shape: (1, 4)\n", + "┌───────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═══════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", + "└───────────────┴──────────┴───────────────────────┴───────────┘" ] - } + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -403,10 +403,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 10, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
"Jason Thompson""PF""Golden State Warriors"7.008475
"Shaun Livingston""PG""Golden State Warriors"5.543725
"Harrison Barnes""SF""Golden State Warriors"3.873398
"Marreese Speights""C""Golden State Warriors"3.815
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" + ], "text/plain": [ "shape: (14, 4)\n", "┌───────────────────┬──────────┬───────────────────────┬───────────┐\n", @@ -429,18 +436,11 @@ "│ Kevon Looney ┆ SF ┆ Golden State Warriors ┆ 1.13196 │\n", "│ Anderson Varejao ┆ PF ┆ Golden State Warriors ┆ 0.289755 │\n", "└───────────────────┴──────────┴───────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
"Jason Thompson""PF""Golden State Warriors"7.008475
"Shaun Livingston""PG""Golden State Warriors"5.543725
"Harrison Barnes""SF""Golden State Warriors"3.873398
"Marreese Speights""C""Golden State Warriors"3.815
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" ] - } + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -463,10 +463,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 11, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Danilo Gallinari""SF""Denver Nuggets"14.0
"Kenneth Faried""PF""Denver Nuggets"11.235955
"Wilson Chandler""SF""Denver Nuggets"10.449438
"JJ Hickson""C""Denver Nuggets"5.6135
"Jameer Nelson""PG""Denver Nuggets"4.345
…………
"Joffrey Lauvergne""C""Denver Nuggets"1.709719
"Gary Harris""SG""Denver Nuggets"1.58448
"Nikola Jokic""C""Denver Nuggets"1.3
"Kostas Papanikolaou""SF""Denver Nuggets"0.800321
"Sean Kilpatrick""SG""Denver Nuggets"0.099418
" + ], "text/plain": [ "shape: (14, 4)\n", "┌─────────────────────┬──────────┬────────────────┬───────────┐\n", @@ -486,18 +493,11 @@ "│ Kostas Papanikolaou ┆ SF ┆ Denver Nuggets ┆ 0.800321 │\n", "│ Sean Kilpatrick ┆ SG ┆ Denver Nuggets ┆ 0.099418 │\n", "└─────────────────────┴──────────┴────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Danilo Gallinari""SF""Denver Nuggets"14.0
"Kenneth Faried""PF""Denver Nuggets"11.235955
"Wilson Chandler""SF""Denver Nuggets"10.449438
"JJ Hickson""C""Denver Nuggets"5.6135
"Jameer Nelson""PG""Denver Nuggets"4.345
…………
"Joffrey Lauvergne""C""Denver Nuggets"1.709719
"Gary Harris""SG""Denver Nuggets"1.58448
"Nikola Jokic""C""Denver Nuggets"1.3
"Kostas Papanikolaou""SF""Denver Nuggets"0.800321
"Sean Kilpatrick""SG""Denver Nuggets"0.099418
" ] - } + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -520,10 +520,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 12, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (5, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Derrick Rose""PG""Chicago Bulls"20.093064
"Kyrie Irving""PG""Cleveland Cavaliers"16.407501
"Chris Paul""PG""Los Angeles Clippers"21.468695
"Russell Westbrook""PG""Oklahoma City Thunder"16.744218
"John Wall""PG""Washington Wizards"15.85195
" + ], "text/plain": [ "shape: (5, 4)\n", "┌───────────────────┬──────────┬───────────────────────┬───────────┐\n", @@ -537,18 +544,11 @@ "│ Russell Westbrook ┆ PG ┆ Oklahoma City Thunder ┆ 16.744218 │\n", "│ John Wall ┆ PG ┆ Washington Wizards ┆ 15.85195 │\n", "└───────────────────┴──────────┴───────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (5, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Derrick Rose""PG""Chicago Bulls"20.093064
"Kyrie Irving""PG""Cleveland Cavaliers"16.407501
"Chris Paul""PG""Los Angeles Clippers"21.468695
"Russell Westbrook""PG""Oklahoma City Thunder"16.744218
"John Wall""PG""Washington Wizards"15.85195
" ] - } + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -571,10 +571,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 13, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (4, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Luol Deng""SF""Miami Heat"10.151612
"Gerald Wallace""SF""Philadelphia 76ers"10.105855
"Danny Green""SG""San Antonio Spurs"10.0
"DeMar DeRozan""SG""Toronto Raptors"10.05
" + ], "text/plain": [ "shape: (4, 4)\n", "┌────────────────┬──────────┬────────────────────┬───────────┐\n", @@ -587,18 +594,11 @@ "│ Danny Green ┆ SG ┆ San Antonio Spurs ┆ 10.0 │\n", "│ DeMar DeRozan ┆ SG ┆ Toronto Raptors ┆ 10.05 │\n", "└────────────────┴──────────┴────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (4, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Luol Deng""SF""Miami Heat"10.151612
"Gerald Wallace""SF""Philadelphia 76ers"10.105855
"Danny Green""SG""San Antonio Spurs"10.0
"DeMar DeRozan""SG""Toronto Raptors"10.05
" ] - } + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -625,19 +625,7 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 14, - "metadata": {}, "data": { - "text/plain": [ - "shape: (0, 4)\n", - "┌────────┬──────────┬──────┬────────┐\n", - "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", - "│ --- ┆ --- ┆ --- ┆ --- │\n", - "│ str ┆ str ┆ str ┆ f64 │\n", - "╞════════╪══════════╪══════╪════════╡\n", - "└────────┴──────────┴──────┴────────┘" - ], "text/html": [ "
\n", "shape: (0, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
" + ], + "text/plain": [ + "shape: (0, 4)\n", + "┌────────┬──────────┬──────┬────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════╪══════════╪══════╪════════╡\n", + "└────────┴──────────┴──────┴────────┘" ] - } + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -714,10 +714,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 15, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
"Jason Thompson""PF""Golden State Warriors"7.008475
"Shaun Livingston""PG""Golden State Warriors"5.543725
"Harrison Barnes""SF""Golden State Warriors"3.873398
"Marreese Speights""C""Golden State Warriors"3.815
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" + ], "text/plain": [ "shape: (14, 4)\n", "┌───────────────────┬──────────┬───────────────────────┬───────────┐\n", @@ -740,18 +747,11 @@ "│ Kevon Looney ┆ SF ┆ Golden State Warriors ┆ 1.13196 │\n", "│ Anderson Varejao ┆ PF ┆ Golden State Warriors ┆ 0.289755 │\n", "└───────────────────┴──────────┴───────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
"Jason Thompson""PF""Golden State Warriors"7.008475
"Shaun Livingston""PG""Golden State Warriors"5.543725
"Harrison Barnes""SF""Golden State Warriors"3.873398
"Marreese Speights""C""Golden State Warriors"3.815
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" ] - } + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -772,10 +772,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 16, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (181, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
"Dennis Schroder""PG""Atlanta Hawks"1.7634
"Tim Hardaway Jr.""SG""Atlanta Hawks"1.30452
"Jason Richardson""SG""Atlanta Hawks"0.947276
…………
"Alan Anderson""SG""Washington Wizards"4.0
"Ramon Sessions""PG""Washington Wizards"2.170465
"Gary Neal""PG""Washington Wizards"2.139
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" + ], "text/plain": [ "shape: (181, 4)\n", "┌──────────────────┬──────────┬────────────────────┬──────────┐\n", @@ -795,18 +802,11 @@ "│ Garrett Temple ┆ SG ┆ Washington Wizards ┆ 1.100602 │\n", "│ Jarell Eddie ┆ SG ┆ Washington Wizards ┆ 0.561716 │\n", "└──────────────────┴──────────┴────────────────────┴──────────┘" - ], - "text/html": [ - "
\n", - "shape: (181, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
"Dennis Schroder""PG""Atlanta Hawks"1.7634
"Tim Hardaway Jr.""SG""Atlanta Hawks"1.30452
"Jason Richardson""SG""Atlanta Hawks"0.947276
…………
"Alan Anderson""SG""Washington Wizards"4.0
"Ramon Sessions""PG""Washington Wizards"2.170465
"Gary Neal""PG""Washington Wizards"2.139
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" ] - } + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -826,10 +826,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 17, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (9, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Derrick Rose""PG""Chicago Bulls"20.093064
"Dwight Howard""C""Houston Rockets"22.359364
"Chris Paul""PG""Los Angeles Clippers"21.468695
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Chris Bosh""PF""Miami Heat"22.19273
"Dwyane Wade""SG""Miami Heat"20.0
"Carmelo Anthony""SF""New York Knicks"22.875
"Kevin Durant""SF""Oklahoma City Thunder"20.158622
" + ], "text/plain": [ "shape: (9, 4)\n", "┌─────────────────┬──────────┬───────────────────────┬───────────┐\n", @@ -847,18 +854,11 @@ "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", "│ Kevin Durant ┆ SF ┆ Oklahoma City Thunder ┆ 20.158622 │\n", "└─────────────────┴──────────┴───────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (9, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Derrick Rose""PG""Chicago Bulls"20.093064
"Dwight Howard""C""Houston Rockets"22.359364
"Chris Paul""PG""Los Angeles Clippers"21.468695
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Chris Bosh""PF""Miami Heat"22.19273
"Dwyane Wade""SG""Miami Heat"20.0
"Carmelo Anthony""SF""New York Knicks"22.875
"Kevin Durant""SF""Oklahoma City Thunder"20.158622
" ] - } + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -879,10 +879,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 18, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (9, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Derrick Rose""PG""Chicago Bulls"20.093064
"Dwight Howard""C""Houston Rockets"22.359364
"Chris Paul""PG""Los Angeles Clippers"21.468695
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Chris Bosh""PF""Miami Heat"22.19273
"Dwyane Wade""SG""Miami Heat"20.0
"Carmelo Anthony""SF""New York Knicks"22.875
"Kevin Durant""SF""Oklahoma City Thunder"20.158622
" + ], "text/plain": [ "shape: (9, 4)\n", "┌─────────────────┬──────────┬───────────────────────┬───────────┐\n", @@ -900,18 +907,11 @@ "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", "│ Kevin Durant ┆ SF ┆ Oklahoma City Thunder ┆ 20.158622 │\n", "└─────────────────┴──────────┴───────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (9, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Derrick Rose""PG""Chicago Bulls"20.093064
"Dwight Howard""C""Houston Rockets"22.359364
"Chris Paul""PG""Los Angeles Clippers"21.468695
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Chris Bosh""PF""Miami Heat"22.19273
"Dwyane Wade""SG""Miami Heat"20.0
"Carmelo Anthony""SF""New York Knicks"22.875
"Kevin Durant""SF""Oklahoma City Thunder"20.158622
" ] - } + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ From 846e874e53c6d9fc0c22e277b6869294d544a277 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 01:51:28 -0700 Subject: [PATCH 06/17] Ch 6.3 to polars - with or without `.alias()`: change = (us_pop_by_age.get_column("2019") - us_pop_by_age.get_column("2014")).alias("Change") --- chapters/06/3/Example_Population_Trends.ipynb | 712 ++++++++---------- 1 file changed, 312 insertions(+), 400 deletions(-) diff --git a/chapters/06/3/Example_Population_Trends.ipynb b/chapters/06/3/Example_Population_Trends.ipynb index 1f9eae7b9..b73901d37 100644 --- a/chapters/06/3/Example_Population_Trends.ipynb +++ b/chapters/06/3/Example_Population_Trends.ipynb @@ -6,12 +6,12 @@ "source": [ "# Example: Population Trends\n", "\n", - "We are now ready to work with large tables of data. The file below contains \"Annual Estimates of the Resident Population by Single Year of Age and Sex for the United States.\" Notice that `read_table` can read data directly from a URL." + "We are now ready to work with large DataFrames of data. The file below contains \"Annual Estimates of the Resident Population by Single Year of Age and Sex for the United States.\" Notice that `pl.read_csv` can read data directly from a URL." ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 1, "metadata": { "tags": [ "remove-input" @@ -19,89 +19,62 @@ }, "outputs": [], "source": [ - "from datascience import *\n", - "import numpy as np\n", - "path_data = '../../../assets/data/'\n", - "np.set_printoptions(threshold=50)" + "import polars as pl\n", + "path_data = '../../../assets/data/'" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE CENSUS2010POP ESTIMATESBASE2010 POPESTIMATE2010 POPESTIMATE2011 POPESTIMATE2012 POPESTIMATE2013 POPESTIMATE2014 POPESTIMATE2015 POPESTIMATE2016 POPESTIMATE2017 POPESTIMATE2018 POPESTIMATE2019
0 0 3944153 3944160 3951430 3963092 3926570 3931258 3954787 3983981 3954773 3893990 3815343 3783052
0 1 3978070 3978090 3957730 3966225 3977549 3942698 3948891 3973133 4002903 3972711 3908830 3829599
0 2 4096929 4096939 4090621 3970654 3978925 3991740 3958711 3966321 3991349 4020045 3987032 3922044
0 3 4119040 4119051 4111688 4101644 3981531 3991017 4005928 3974351 3982984 4006946 4033038 3998665
0 4 4063170 4063186 4077346 4121488 4111490 3992502 4004032 4020292 3989750 3997280 4018719 4043323
0 5 4056858 4056872 4064521 4087054 4131049 4121876 4004576 4017589 4035033 4003452 4008443 4028281
0 6 4066381 4066412 4072904 4074531 4096631 4141126 4133372 4017388 4031568 4048018 4014057 4017227
0 7 4030579 4030594 4042990 4082821 4084175 4106756 4152666 4145872 4030888 4044139 4058370 4022319
0 8 4046486 4046497 4025501 4052773 4092559 4094513 4118349 4165033 4158848 4042924 4054236 4066194
0 9 4148353 4148369 4125312 4035319 4062726 4103052 4106068 4130887 4177895 4170813 4053179 4061874
\n", - "

... (296 rows omitted)

" + "
\n", + "shape: (306, 14)
SEXAGECENSUS2010POPESTIMATESBASE2010POPESTIMATE2010POPESTIMATE2011POPESTIMATE2012POPESTIMATE2013POPESTIMATE2014POPESTIMATE2015POPESTIMATE2016POPESTIMATE2017POPESTIMATE2018POPESTIMATE2019
i64i64i64i64i64i64i64i64i64i64i64i64i64i64
00394415339441603951430396309239265703931258395478739839813954773389399038153433783052
01397807039780903957730396622539775493942698394889139731334002903397271139088303829599
02409692940969394090621397065439789253991740395871139663213991349402004539870323922044
03411904041190514111688410164439815313991017400592839743513982984400694640330383998665
04406317040631864077346412148841114903992502400403240202923989750399728040187194043323
……………………………………
297535825360554165571235922160670624076860869709762768210084358
298366413667537567400784256143866458874661152122529785759362607
299261932621426098269952907630672322453356034278384893957642528
2100442024424645080474275004052817571086030964381671137215376850
2999156964212156969328157246908158356816159456593160511789161646584162778769163919526164939619165801767166582199
" ], "text/plain": [ - "SEX | AGE | CENSUS2010POP | ESTIMATESBASE2010 | POPESTIMATE2010 | POPESTIMATE2011 | POPESTIMATE2012 | POPESTIMATE2013 | POPESTIMATE2014 | POPESTIMATE2015 | POPESTIMATE2016 | POPESTIMATE2017 | POPESTIMATE2018 | POPESTIMATE2019\n", - "0 | 0 | 3944153 | 3944160 | 3951430 | 3963092 | 3926570 | 3931258 | 3954787 | 3983981 | 3954773 | 3893990 | 3815343 | 3783052\n", - "0 | 1 | 3978070 | 3978090 | 3957730 | 3966225 | 3977549 | 3942698 | 3948891 | 3973133 | 4002903 | 3972711 | 3908830 | 3829599\n", - "0 | 2 | 4096929 | 4096939 | 4090621 | 3970654 | 3978925 | 3991740 | 3958711 | 3966321 | 3991349 | 4020045 | 3987032 | 3922044\n", - "0 | 3 | 4119040 | 4119051 | 4111688 | 4101644 | 3981531 | 3991017 | 4005928 | 3974351 | 3982984 | 4006946 | 4033038 | 3998665\n", - "0 | 4 | 4063170 | 4063186 | 4077346 | 4121488 | 4111490 | 3992502 | 4004032 | 4020292 | 3989750 | 3997280 | 4018719 | 4043323\n", - "0 | 5 | 4056858 | 4056872 | 4064521 | 4087054 | 4131049 | 4121876 | 4004576 | 4017589 | 4035033 | 4003452 | 4008443 | 4028281\n", - "0 | 6 | 4066381 | 4066412 | 4072904 | 4074531 | 4096631 | 4141126 | 4133372 | 4017388 | 4031568 | 4048018 | 4014057 | 4017227\n", - "0 | 7 | 4030579 | 4030594 | 4042990 | 4082821 | 4084175 | 4106756 | 4152666 | 4145872 | 4030888 | 4044139 | 4058370 | 4022319\n", - "0 | 8 | 4046486 | 4046497 | 4025501 | 4052773 | 4092559 | 4094513 | 4118349 | 4165033 | 4158848 | 4042924 | 4054236 | 4066194\n", - "0 | 9 | 4148353 | 4148369 | 4125312 | 4035319 | 4062726 | 4103052 | 4106068 | 4130887 | 4177895 | 4170813 | 4053179 | 4061874\n", - "... (296 rows omitted)" + "shape: (306, 14)\n", + "┌─────┬─────┬─────────────┬─────────────┬───┬─────────────┬─────────────┬─────────────┬────────────┐\n", + "│ SEX ┆ AGE ┆ CENSUS2010P ┆ ESTIMATESBA ┆ … ┆ POPESTIMATE ┆ POPESTIMATE ┆ POPESTIMATE ┆ POPESTIMAT │\n", + "│ --- ┆ --- ┆ OP ┆ SE2010 ┆ ┆ 2016 ┆ 2017 ┆ 2018 ┆ E2019 │\n", + "│ i64 ┆ i64 ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ ┆ ┆ i64 ┆ i64 ┆ ┆ i64 ┆ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪═════════════╪═════════════╪═══╪═════════════╪═════════════╪═════════════╪════════════╡\n", + "│ 0 ┆ 0 ┆ 3944153 ┆ 3944160 ┆ … ┆ 3954773 ┆ 3893990 ┆ 3815343 ┆ 3783052 │\n", + "│ 0 ┆ 1 ┆ 3978070 ┆ 3978090 ┆ … ┆ 4002903 ┆ 3972711 ┆ 3908830 ┆ 3829599 │\n", + "│ 0 ┆ 2 ┆ 4096929 ┆ 4096939 ┆ … ┆ 3991349 ┆ 4020045 ┆ 3987032 ┆ 3922044 │\n", + "│ 0 ┆ 3 ┆ 4119040 ┆ 4119051 ┆ … ┆ 3982984 ┆ 4006946 ┆ 4033038 ┆ 3998665 │\n", + "│ 0 ┆ 4 ┆ 4063170 ┆ 4063186 ┆ … ┆ 3989750 ┆ 3997280 ┆ 4018719 ┆ 4043323 │\n", + "│ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 2 ┆ 97 ┆ 53582 ┆ 53605 ┆ … ┆ 69709 ┆ 76276 ┆ 82100 ┆ 84358 │\n", + "│ 2 ┆ 98 ┆ 36641 ┆ 36675 ┆ … ┆ 52122 ┆ 52978 ┆ 57593 ┆ 62607 │\n", + "│ 2 ┆ 99 ┆ 26193 ┆ 26214 ┆ … ┆ 34278 ┆ 38489 ┆ 39576 ┆ 42528 │\n", + "│ 2 ┆ 100 ┆ 44202 ┆ 44246 ┆ … ┆ 64381 ┆ 67113 ┆ 72153 ┆ 76850 │\n", + "│ 2 ┆ 999 ┆ 156964212 ┆ 156969328 ┆ … ┆ 163919526 ┆ 164939619 ┆ 165801767 ┆ 166582199 │\n", + "└─────┴─────┴─────────────┴─────────────┴───┴─────────────┴─────────────┴─────────────┴────────────┘" ] }, - "execution_count": 25, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "# As of August 2021, this census file is online here: \n", + "# As of August 2021, this census file is online here:\n", "data = 'http://www2.census.gov/programs-surveys/popest/technical-documentation/file-layouts/2010-2019/nc-est2019-agesex-res.csv'\n", "\n", "# A local copy can be accessed here in case census.gov moves the file:\n", "# data = path_data + 'nc-est2019-agesex-res.csv'\n", "\n", - "full_census_table = Table.read_table(data)\n", + "full_census_table = pl.read_csv(data)\n", "full_census_table" ] }, @@ -109,9 +82,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Only the first 10 rows of the table are displayed. Later we will see how to display the entire table; however, this is typically not useful with large tables.\n", + "Only the first five and last five rows of the DataFrame are displayed. Later we will see how to display the entire DataFrame; however, this is typically not useful with large DataFrames.\n", "\n", - "A [description of the table](https://www2.census.gov/programs-surveys/popest/technical-documentation/file-layouts/2010-2019/nc-est2019-agesex-res.pdf) appears online. \n", + "A [description of the data](https://www2.census.gov/programs-surveys/popest/technical-documentation/file-layouts/2010-2019/nc-est2019-agesex-res.pdf) appears online.\n", "\n", "The `SEX` column contains numeric codes: `0` stands for the total, `1` for male, and `2` for female. The assumptions underlying this binary categorization are questionable. We will discuss them in the next section.\n", "\n", @@ -121,14 +94,14 @@ "\n", "The other columns contain estimates of the US population in each category of sex and age in the years 2010 through 2019. The Census is decennial: it takes place every 10 years. The most recent Census was held in 2020 and the one before that in 2010. The Census Bureau also estimates population changes each year. As explained in the Bureau's description of its [methodology](https://www2.census.gov/programs-surveys/popest/technical-documentation/methodology/2010-2020/methods-statement-v2020-final.pdf), it \"adds [the estimated changes] to the last decennial census to produce updated population estimates every year.\"\n", "\n", - "Typically, a publicly available table will contain more information than necessary for a particular investigation or analysis. To get the large table into a more usable form, we have to do some *data cleaning*.\n", + "Typically, a publicly available DataFrame will contain more information than necessary for a particular investigation or analysis. To get the large DataFrame into a more usable form, we have to do some *data cleaning*.\n", "\n", "Suppose we are only interested in the population changes from 2014 to 2019. Let's `select` the relevant columns." ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 3, "metadata": { "scrolled": true }, @@ -136,63 +109,37 @@ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE POPESTIMATE2014 POPESTIMATE2019
0 0 3954787 3783052
0 1 3948891 3829599
0 2 3958711 3922044
0 3 4005928 3998665
0 4 4004032 4043323
0 5 4004576 4028281
0 6 4133372 4017227
0 7 4152666 4022319
0 8 4118349 4066194
0 9 4106068 4061874
\n", - "

... (296 rows omitted)

" + "
\n", + "shape: (306, 4)
SEXAGEPOPESTIMATE2014POPESTIMATE2019
i64i64i64i64
0039547873783052
0139488913829599
0239587113922044
0340059283998665
0440040324043323
…………
2976240784358
2984588762607
2993224542528
21005710876850
2999161646584166582199
" ], "text/plain": [ - "SEX | AGE | POPESTIMATE2014 | POPESTIMATE2019\n", - "0 | 0 | 3954787 | 3783052\n", - "0 | 1 | 3948891 | 3829599\n", - "0 | 2 | 3958711 | 3922044\n", - "0 | 3 | 4005928 | 3998665\n", - "0 | 4 | 4004032 | 4043323\n", - "0 | 5 | 4004576 | 4028281\n", - "0 | 6 | 4133372 | 4017227\n", - "0 | 7 | 4152666 | 4022319\n", - "0 | 8 | 4118349 | 4066194\n", - "0 | 9 | 4106068 | 4061874\n", - "... (296 rows omitted)" + "shape: (306, 4)\n", + "┌─────┬─────┬─────────────────┬─────────────────┐\n", + "│ SEX ┆ AGE ┆ POPESTIMATE2014 ┆ POPESTIMATE2019 │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪═════════════════╪═════════════════╡\n", + "│ 0 ┆ 0 ┆ 3954787 ┆ 3783052 │\n", + "│ 0 ┆ 1 ┆ 3948891 ┆ 3829599 │\n", + "│ 0 ┆ 2 ┆ 3958711 ┆ 3922044 │\n", + "│ 0 ┆ 3 ┆ 4005928 ┆ 3998665 │\n", + "│ 0 ┆ 4 ┆ 4004032 ┆ 4043323 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ 2 ┆ 97 ┆ 62407 ┆ 84358 │\n", + "│ 2 ┆ 98 ┆ 45887 ┆ 62607 │\n", + "│ 2 ┆ 99 ┆ 32245 ┆ 42528 │\n", + "│ 2 ┆ 100 ┆ 57108 ┆ 76850 │\n", + "│ 2 ┆ 999 ┆ 161646584 ┆ 166582199 │\n", + "└─────┴─────┴─────────────────┴─────────────────┘" ] }, - "execution_count": 26, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -211,75 +158,49 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2014 2019
0 0 3954787 3783052
0 1 3948891 3829599
0 2 3958711 3922044
0 3 4005928 3998665
0 4 4004032 4043323
0 5 4004576 4028281
0 6 4133372 4017227
0 7 4152666 4022319
0 8 4118349 4066194
0 9 4106068 4061874
\n", - "

... (296 rows omitted)

" + "
\n", + "shape: (306, 4)
SEXAGE20142019
i64i64i64i64
0039547873783052
0139488913829599
0239587113922044
0340059283998665
0440040324043323
…………
2976240784358
2984588762607
2993224542528
21005710876850
2999161646584166582199
" ], "text/plain": [ - "SEX | AGE | 2014 | 2019\n", - "0 | 0 | 3954787 | 3783052\n", - "0 | 1 | 3948891 | 3829599\n", - "0 | 2 | 3958711 | 3922044\n", - "0 | 3 | 4005928 | 3998665\n", - "0 | 4 | 4004032 | 4043323\n", - "0 | 5 | 4004576 | 4028281\n", - "0 | 6 | 4133372 | 4017227\n", - "0 | 7 | 4152666 | 4022319\n", - "0 | 8 | 4118349 | 4066194\n", - "0 | 9 | 4106068 | 4061874\n", - "... (296 rows omitted)" + "shape: (306, 4)\n", + "┌─────┬─────┬───────────┬───────────┐\n", + "│ SEX ┆ AGE ┆ 2014 ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪═══════════╪═══════════╡\n", + "│ 0 ┆ 0 ┆ 3954787 ┆ 3783052 │\n", + "│ 0 ┆ 1 ┆ 3948891 ┆ 3829599 │\n", + "│ 0 ┆ 2 ┆ 3958711 ┆ 3922044 │\n", + "│ 0 ┆ 3 ┆ 4005928 ┆ 3998665 │\n", + "│ 0 ┆ 4 ┆ 4004032 ┆ 4043323 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ 2 ┆ 97 ┆ 62407 ┆ 84358 │\n", + "│ 2 ┆ 98 ┆ 45887 ┆ 62607 │\n", + "│ 2 ┆ 99 ┆ 32245 ┆ 42528 │\n", + "│ 2 ┆ 100 ┆ 57108 ┆ 76850 │\n", + "│ 2 ┆ 999 ┆ 161646584 ┆ 166582199 │\n", + "└─────┴─────┴───────────┴───────────┘" ] }, - "execution_count": 27, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "us_pop = partial_census_table.relabeled('POPESTIMATE2014', '2014').relabeled('POPESTIMATE2019', '2019')\n", + "us_pop = partial_census_table.rename({\"POPESTIMATE2014\": \"2014\", \"POPESTIMATE2019\": \"2019\"})\n", "us_pop" ] }, @@ -293,75 +214,49 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
AGE 2014 2019
0 3954787 3783052
1 3948891 3829599
2 3958711 3922044
3 4005928 3998665
4 4004032 4043323
5 4004576 4028281
6 4133372 4017227
7 4152666 4022319
8 4118349 4066194
9 4106068 4061874
\n", - "

... (92 rows omitted)

" + "
\n", + "shape: (102, 3)
AGE20142019
i64i64i64
039547873783052
139488913829599
239587113922044
340059283998665
440040324043323
………
9782948116969
985954686150
994127757124
10070685100322
999318301008328239523
" ], "text/plain": [ - "AGE | 2014 | 2019\n", - "0 | 3954787 | 3783052\n", - "1 | 3948891 | 3829599\n", - "2 | 3958711 | 3922044\n", - "3 | 4005928 | 3998665\n", - "4 | 4004032 | 4043323\n", - "5 | 4004576 | 4028281\n", - "6 | 4133372 | 4017227\n", - "7 | 4152666 | 4022319\n", - "8 | 4118349 | 4066194\n", - "9 | 4106068 | 4061874\n", - "... (92 rows omitted)" + "shape: (102, 3)\n", + "┌─────┬───────────┬───────────┐\n", + "│ AGE ┆ 2014 ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═══════════╪═══════════╡\n", + "│ 0 ┆ 3954787 ┆ 3783052 │\n", + "│ 1 ┆ 3948891 ┆ 3829599 │\n", + "│ 2 ┆ 3958711 ┆ 3922044 │\n", + "│ 3 ┆ 4005928 ┆ 3998665 │\n", + "│ 4 ┆ 4004032 ┆ 4043323 │\n", + "│ … ┆ … ┆ … │\n", + "│ 97 ┆ 82948 ┆ 116969 │\n", + "│ 98 ┆ 59546 ┆ 86150 │\n", + "│ 99 ┆ 41277 ┆ 57124 │\n", + "│ 100 ┆ 70685 ┆ 100322 │\n", + "│ 999 ┆ 318301008 ┆ 328239523 │\n", + "└─────┴───────────┴───────────┘" ] }, - "execution_count": 28, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "us_pop_by_age = us_pop.where('SEX', are.equal_to(0)).drop('SEX')\n", + "us_pop_by_age = us_pop.filter(pl.col(\"SEX\") == 0).drop(\"SEX\")\n", "us_pop_by_age" ] }, @@ -369,54 +264,47 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now let's look at the population in the highest ages." + "Now let's look at the population in the highest ages. `closed=\"left\"` includes the lower endpoint and excludes the upper one, so ages 97, 98, 99, and 100 are kept and 101 is not." ] }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
AGE 2014 2019
97 82948 116969
98 59546 86150
99 41277 57124
100 70685 100322
" + "
\n", + "shape: (4, 3)
AGE20142019
i64i64i64
9782948116969
985954686150
994127757124
10070685100322
" ], "text/plain": [ - "AGE | 2014 | 2019\n", - "97 | 82948 | 116969\n", - "98 | 59546 | 86150\n", - "99 | 41277 | 57124\n", - "100 | 70685 | 100322" + "shape: (4, 3)\n", + "┌─────┬───────┬────────┐\n", + "│ AGE ┆ 2014 ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═══════╪════════╡\n", + "│ 97 ┆ 82948 ┆ 116969 │\n", + "│ 98 ┆ 59546 ┆ 86150 │\n", + "│ 99 ┆ 41277 ┆ 57124 │\n", + "│ 100 ┆ 70685 ┆ 100322 │\n", + "└─────┴───────┴────────┘" ] }, - "execution_count": 29, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "us_pop_by_age.where('AGE', are.between(97, 101))" + "us_pop_by_age.filter(pl.col(\"AGE\").is_between(97, 101, closed=\"left\"))" ] }, { @@ -434,30 +322,101 @@ "source": [ "## Percent Change\n", "\n", - "Each column of the table `us_pop_by_age` is an array of the same length, and so columns can be combined using arithmetic. The array below contains the change in population between 2014 and 2019. There is one entry corresponding to each row of `us_pop_by_age`." + "Each column of the DataFrame `us_pop_by_age` is a Polars Series of the same length, and so columns can be combined using arithmetic. The Polars Series below contains the change in population between 2014 and 2019. There is one entry corresponding to each row of `us_pop_by_age`." ] }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 1, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 1, + "metadata": {}, "data": { "text/plain": [ - "array([-171735, -119292, -36667, ..., 15847, 29637, 9938515])" + "shape: (102,)\n", + "Series: 'Change' [i64]\n", + "[\n", + "\t-171735\n", + "\t-119292\n", + "\t-36667\n", + "\t-7263\n", + "\t39291\n", + "\t…\n", + "\t34021\n", + "\t26604\n", + "\t15847\n", + "\t29637\n", + "\t9938515\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (102,)
Change
i64
-171735
-119292
-36667
-7263
39291
…
34021
26604
15847
29637
9938515
" ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "change = us_pop_by_age.column('2019') - us_pop_by_age.column('2014')\n", + "# Option 1: Assign with alias so it is ready for with_columns (gives a named Series)\n", + "change = (us_pop_by_age.get_column(\"2019\") - us_pop_by_age.get_column(\"2014\")).alias(\"Change\")\n", "change" ] }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "output_type": "execute_result", + "execution_count": 2, + "metadata": {}, + "data": { + "text/plain": [ + "shape: (102,)\n", + "Series: '2019' [i64]\n", + "[\n", + "\t-171735\n", + "\t-119292\n", + "\t-36667\n", + "\t-7263\n", + "\t39291\n", + "\t…\n", + "\t34021\n", + "\t26604\n", + "\t15847\n", + "\t29637\n", + "\t9938515\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (102,)
2019
i64
-171735
-119292
-36667
-7263
39291
…
34021
26604
15847
29637
9938515
" + ] + } + } + ], + "source": [ + "# Option 2: Simple difference (keeps the name of the left Series)\n", + "change_simple = us_pop_by_age.get_column(\"2019\") - us_pop_by_age.get_column(\"2014\")\n", + "change_simple" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -467,203 +426,156 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
AGE 2014 2019 Change Percent Change
0 3954787 3783052 -171735 -4.34%
1 3948891 3829599 -119292 -3.02%
2 3958711 3922044 -36667 -0.93%
3 4005928 3998665 -7263 -0.18%
4 4004032 4043323 39291 0.98%
5 4004576 4028281 23705 0.59%
6 4133372 4017227 -116145 -2.81%
7 4152666 4022319 -130347 -3.14%
8 4118349 4066194 -52155 -1.27%
9 4106068 4061874 -44194 -1.08%
\n", - "

... (92 rows omitted)

" + "
\n", + "shape: (102, 5)
AGE20142019ChangePercent Change
i64i64i64i64str
039547873783052-171735"-4.34%"
139488913829599-119292"-3.02%"
239587113922044-36667"-0.93%"
340059283998665-7263"-0.18%"
44004032404332339291"0.98%"
……………
978294811696934021"41.01%"
98595468615026604"44.68%"
99412775712415847"38.39%"
1007068510032229637"41.93%"
9993183010083282395239938515"3.12%"
" ], "text/plain": [ - "AGE | 2014 | 2019 | Change | Percent Change\n", - "0 | 3954787 | 3783052 | -171735 | -4.34%\n", - "1 | 3948891 | 3829599 | -119292 | -3.02%\n", - "2 | 3958711 | 3922044 | -36667 | -0.93%\n", - "3 | 4005928 | 3998665 | -7263 | -0.18%\n", - "4 | 4004032 | 4043323 | 39291 | 0.98%\n", - "5 | 4004576 | 4028281 | 23705 | 0.59%\n", - "6 | 4133372 | 4017227 | -116145 | -2.81%\n", - "7 | 4152666 | 4022319 | -130347 | -3.14%\n", - "8 | 4118349 | 4066194 | -52155 | -1.27%\n", - "9 | 4106068 | 4061874 | -44194 | -1.08%\n", - "... (92 rows omitted)" + "shape: (102, 5)\n", + "┌─────┬───────────┬───────────┬─────────┬────────────────┐\n", + "│ AGE ┆ 2014 ┆ 2019 ┆ Change ┆ Percent Change │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 ┆ i64 ┆ str │\n", + "╞═════╪═══════════╪═══════════╪═════════╪════════════════╡\n", + "│ 0 ┆ 3954787 ┆ 3783052 ┆ -171735 ┆ -4.34% │\n", + "│ 1 ┆ 3948891 ┆ 3829599 ┆ -119292 ┆ -3.02% │\n", + "│ 2 ┆ 3958711 ┆ 3922044 ┆ -36667 ┆ -0.93% │\n", + "│ 3 ┆ 4005928 ┆ 3998665 ┆ -7263 ┆ -0.18% │\n", + "│ 4 ┆ 4004032 ┆ 4043323 ┆ 39291 ┆ 0.98% │\n", + "│ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 97 ┆ 82948 ┆ 116969 ┆ 34021 ┆ 41.01% │\n", + "│ 98 ┆ 59546 ┆ 86150 ┆ 26604 ┆ 44.68% │\n", + "│ 99 ┆ 41277 ┆ 57124 ┆ 15847 ┆ 38.39% │\n", + "│ 100 ┆ 70685 ┆ 100322 ┆ 29637 ┆ 41.93% │\n", + "│ 999 ┆ 318301008 ┆ 328239523 ┆ 9938515 ┆ 3.12% │\n", + "└─────┴───────────┴───────────┴─────────┴────────────────┘" ] }, - "execution_count": 31, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "us_pop_change = us_pop_by_age.with_columns(\n", - " 'Change', change,\n", - " 'Percent Change', change/us_pop_by_age.column('2014')\n", + " change,\n", + " (change / us_pop_by_age.get_column(\"2014\")).alias(\"Percent Change\"),\n", + ")\n", + "us_pop_change = us_pop_change.with_columns(\n", + " ((pl.col(\"Percent Change\") * 100).round(2).cast(pl.String) + \"%\").alias(\"Percent Change\")\n", ")\n", - "us_pop_change.set_format('Percent Change', PercentFormatter)" + "us_pop_change" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Almost all the entries displayed in the `Percent Change` column are negative, demonstrating a drop in population at the youngest ages. However, the overall population grew by about 9.9 million people, a percent change of just over 3%." + "The first rows of the `Percent Change` column are negative, demonstrating a drop in population at the youngest ages. However, the overall population grew by about 9.9 million people, a percent change of just over 3%." ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
AGE 2014 2019 Change Percent Change
999 318301008 328239523 9938515 3.12%
" + "
\n", + "shape: (1, 5)
AGE20142019ChangePercent Change
i64i64i64i64str
9993183010083282395239938515"3.12%"
" ], "text/plain": [ - "AGE | 2014 | 2019 | Change | Percent Change\n", - "999 | 318301008 | 328239523 | 9938515 | 3.12%" + "shape: (1, 5)\n", + "┌─────┬───────────┬───────────┬─────────┬────────────────┐\n", + "│ AGE ┆ 2014 ┆ 2019 ┆ Change ┆ Percent Change │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 ┆ i64 ┆ str │\n", + "╞═════╪═══════════╪═══════════╪═════════╪════════════════╡\n", + "│ 999 ┆ 318301008 ┆ 328239523 ┆ 9938515 ┆ 3.12% │\n", + "└─────┴───────────┴───────────┴─────────┴────────────────┘" ] }, - "execution_count": 32, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "us_pop_change.where('AGE', are.equal_to(999))" + "us_pop_change.filter(pl.col(\"AGE\") == 999)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Let us compare this to the change at each age. For ease of interpretation, we will sort the table in decreasing order of the absolute change in population, contained in the column `Change`." + "Let us compare this to the change at each age. For ease of interpretation, we will sort the DataFrame in decreasing order of the absolute change in population, contained in the column `Change`." ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
AGE 2014 2019 Change Percent Change
72 2191642 3191048 999406 45.60%
68 2567511 3345475 777964 30.30%
69 2530460 3252423 721963 28.53%
70 2461426 3136704 675278 27.43%
71 2516392 3083083 566691 22.52%
76 1692960 2222392 529432 31.27%
62 3677408 4156645 479237 13.03%
28 4345247 4818725 473478 10.90%
64 3481789 3950578 468789 13.46%
38 3848856 4305576 456720 11.87%
\n", - "

... (91 rows omitted)

" + "
\n", + "shape: (101, 5)
AGE20142019ChangePercent Change
i64i64i64i64str
7221916423191048999406"45.6%"
6825675113345475777964"30.3%"
6925304603252423721963"28.53%"
7024614263136704675278"27.43%"
7125163923083083566691"22.52%"
……………
4443754503967275-408175"-9.33%"
5345232454068851-454394"-10.05%"
4343192653854040-465225"-10.77%"
5244677244001782-465942"-10.43%"
5144762814004343-471938"-10.54%"
" ], "text/plain": [ - "AGE | 2014 | 2019 | Change | Percent Change\n", - "72 | 2191642 | 3191048 | 999406 | 45.60%\n", - "68 | 2567511 | 3345475 | 777964 | 30.30%\n", - "69 | 2530460 | 3252423 | 721963 | 28.53%\n", - "70 | 2461426 | 3136704 | 675278 | 27.43%\n", - "71 | 2516392 | 3083083 | 566691 | 22.52%\n", - "76 | 1692960 | 2222392 | 529432 | 31.27%\n", - "62 | 3677408 | 4156645 | 479237 | 13.03%\n", - "28 | 4345247 | 4818725 | 473478 | 10.90%\n", - "64 | 3481789 | 3950578 | 468789 | 13.46%\n", - "38 | 3848856 | 4305576 | 456720 | 11.87%\n", - "... (91 rows omitted)" + "shape: (101, 5)\n", + "┌─────┬─────────┬─────────┬─────────┬────────────────┐\n", + "│ AGE ┆ 2014 ┆ 2019 ┆ Change ┆ Percent Change │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 ┆ i64 ┆ str │\n", + "╞═════╪═════════╪═════════╪═════════╪════════════════╡\n", + "│ 72 ┆ 2191642 ┆ 3191048 ┆ 999406 ┆ 45.6% │\n", + "│ 68 ┆ 2567511 ┆ 3345475 ┆ 777964 ┆ 30.3% │\n", + "│ 69 ┆ 2530460 ┆ 3252423 ┆ 721963 ┆ 28.53% │\n", + "│ 70 ┆ 2461426 ┆ 3136704 ┆ 675278 ┆ 27.43% │\n", + "│ 71 ┆ 2516392 ┆ 3083083 ┆ 566691 ┆ 22.52% │\n", + "│ … ┆ … ┆ … ┆ … ┆ … │\n", + "│ 44 ┆ 4375450 ┆ 3967275 ┆ -408175 ┆ -9.33% │\n", + "│ 53 ┆ 4523245 ┆ 4068851 ┆ -454394 ┆ -10.05% │\n", + "│ 43 ┆ 4319265 ┆ 3854040 ┆ -465225 ┆ -10.77% │\n", + "│ 52 ┆ 4467724 ┆ 4001782 ┆ -465942 ┆ -10.43% │\n", + "│ 51 ┆ 4476281 ┆ 4004343 ┆ -471938 ┆ -10.54% │\n", + "└─────┴─────────┴─────────┴─────────┴────────────────┘" ] }, - "execution_count": 33, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "us_pop_change.where(\n", - " 'AGE', are.below(999)\n", - ").sort('Change', descending=True)" + "us_pop_change.filter(\n", + " pl.col(\"AGE\") < 999\n", + ").sort(\"Change\", descending=True)" ] }, { From 5ef4557320496d706a175e055b63b089b7cda80c Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 01:54:05 -0700 Subject: [PATCH 07/17] feat(Ch 6.3) --- chapters/06/3/Example_Population_Trends.ipynb | 63 +++++++++---------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/chapters/06/3/Example_Population_Trends.ipynb b/chapters/06/3/Example_Population_Trends.ipynb index b73901d37..6f8a0df51 100644 --- a/chapters/06/3/Example_Population_Trends.ipynb +++ b/chapters/06/3/Example_Population_Trends.ipynb @@ -331,10 +331,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 1, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (102,)
Change
i64
-171735
-119292
-36667
-7263
39291
…
34021
26604
15847
29637
9938515
" + ], "text/plain": [ "shape: (102,)\n", "Series: 'Change' [i64]\n", @@ -351,18 +358,11 @@ "\t29637\n", "\t9938515\n", "]" - ], - "text/html": [ - "
\n", - "shape: (102,)
Change
i64
-171735
-119292
-36667
-7263
39291
…
34021
26604
15847
29637
9938515
" ] - } + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -377,10 +377,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 2, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (102,)
2019
i64
-171735
-119292
-36667
-7263
39291
…
34021
26604
15847
29637
9938515
" + ], "text/plain": [ "shape: (102,)\n", "Series: '2019' [i64]\n", @@ -397,18 +404,11 @@ "\t29637\n", "\t9938515\n", "]" - ], - "text/html": [ - "
\n", - "shape: (102,)
2019
i64
-171735
-119292
-36667
-7263
39291
…
34021
26604
15847
29637
9938515
" ] - } + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -592,13 +592,6 @@ "\n", "The post-war jump in births is a major reason for the large changes that we have observed." ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { From 4642ec8cd09b0c352870acddf4b963a712c616e5 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 02:08:04 -0700 Subject: [PATCH 08/17] Ch 6.4 to polars - with pl.Config(tbl_rows=-1) --> to display every row - matplotlib is used for visualization for now --- chapters/06/4/Example_Sex_Ratios.ipynb | 897 +++++++++++-------------- 1 file changed, 382 insertions(+), 515 deletions(-) diff --git a/chapters/06/4/Example_Sex_Ratios.ipynb b/chapters/06/4/Example_Sex_Ratios.ipynb index 289520681..9ad45f872 100644 --- a/chapters/06/4/Example_Sex_Ratios.ipynb +++ b/chapters/06/4/Example_Sex_Ratios.ipynb @@ -6,12 +6,12 @@ "source": [ "# Example: Sex Ratios\n", "\n", - "In this section we will continue using the `us_pop` table from the previous section. But this time we will focus on population trends in relation to the `SEX` column." + "In this section we will continue using the `us_pop` DataFrame from the previous section. But this time we will focus on population trends in relation to the `SEX` column." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 1, "metadata": { "tags": [ "remove-input" @@ -19,8 +19,7 @@ }, "outputs": [], "source": [ - "from datascience import *\n", - "import numpy as np\n", + "import polars as pl\n", "path_data = '../../../assets/data/'\n", "import matplotlib\n", "matplotlib.use('Agg')\n", @@ -31,7 +30,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": { "tags": [ "remove-input" @@ -39,86 +38,58 @@ }, "outputs": [], "source": [ - "# As of August 2021, this census file is online here: \n", + "# As of August 2021, this census file is online here:\n", "data = 'http://www2.census.gov/programs-surveys/popest/technical-documentation/file-layouts/2010-2019/nc-est2019-agesex-res.csv'\n", "\n", "# A local copy can be accessed here in case census.gov moves the file:\n", "# data = path_data + 'nc-est2019-agesex-res.csv'\n", "\n", - "full_census_table = Table.read_table(data)\n", - "#full_census_table\n", + "full_census_table = pl.read_csv(data)\n", "\n", "partial_census_table = full_census_table.select('SEX', 'AGE', 'POPESTIMATE2014', 'POPESTIMATE2019')\n", - "#partial_census_table\n", "\n", - "us_pop = partial_census_table.relabeled('POPESTIMATE2014', '2014').relabeled('POPESTIMATE2019', '2019')" + "us_pop = partial_census_table.rename({'POPESTIMATE2014': '2014', 'POPESTIMATE2019': '2019'})" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2014 2019
0 0 3954787 3783052
0 1 3948891 3829599
0 2 3958711 3922044
0 3 4005928 3998665
0 4 4004032 4043323
0 5 4004576 4028281
0 6 4133372 4017227
0 7 4152666 4022319
0 8 4118349 4066194
0 9 4106068 4061874
\n", - "

... (296 rows omitted)

" + "
\n", + "shape: (306, 4)
SEXAGE20142019
i64i64i64i64
0039547873783052
0139488913829599
0239587113922044
0340059283998665
0440040324043323
…………
2976240784358
2984588762607
2993224542528
21005710876850
2999161646584166582199
" ], "text/plain": [ - "SEX | AGE | 2014 | 2019\n", - "0 | 0 | 3954787 | 3783052\n", - "0 | 1 | 3948891 | 3829599\n", - "0 | 2 | 3958711 | 3922044\n", - "0 | 3 | 4005928 | 3998665\n", - "0 | 4 | 4004032 | 4043323\n", - "0 | 5 | 4004576 | 4028281\n", - "0 | 6 | 4133372 | 4017227\n", - "0 | 7 | 4152666 | 4022319\n", - "0 | 8 | 4118349 | 4066194\n", - "0 | 9 | 4106068 | 4061874\n", - "... (296 rows omitted)" + "shape: (306, 4)\n", + "┌─────┬─────┬───────────┬───────────┐\n", + "│ SEX ┆ AGE ┆ 2014 ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪═══════════╪═══════════╡\n", + "│ 0 ┆ 0 ┆ 3954787 ┆ 3783052 │\n", + "│ 0 ┆ 1 ┆ 3948891 ┆ 3829599 │\n", + "│ 0 ┆ 2 ┆ 3958711 ┆ 3922044 │\n", + "│ 0 ┆ 3 ┆ 4005928 ┆ 3998665 │\n", + "│ 0 ┆ 4 ┆ 4004032 ┆ 4043323 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ 2 ┆ 97 ┆ 62407 ┆ 84358 │\n", + "│ 2 ┆ 98 ┆ 45887 ┆ 62607 │\n", + "│ 2 ┆ 99 ┆ 32245 ┆ 42528 │\n", + "│ 2 ┆ 100 ┆ 57108 ┆ 76850 │\n", + "│ 2 ┆ 999 ┆ 161646584 ┆ 166582199 │\n", + "└─────┴─────┴───────────┴───────────┘" ] }, - "execution_count": 5, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -167,51 +138,47 @@ "metadata": {}, "source": [ "## Overall Proportions\n", - "We will now begin looking at sex ratios in 2019. First, let's look at all the age groups together. Remember that this means looking at the rows where the \"age\" is coded 999. The table `all_ages` contains this information. There are three rows: one for the total population, one for males, and one for females." + "We will now begin looking at sex ratios in 2019. First, let's look at all the age groups together. Remember that this means looking at the rows where the \"age\" is coded 999. The DataFrame `all_ages` contains this information. There are three rows: one for the total population, one for males, and one for females." ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2019
0 999 328239523
1 999 161657324
2 999 166582199
" + "
\n", + "shape: (3, 3)
SEXAGE2019
i64i64i64
0999328239523
1999161657324
2999166582199
" ], "text/plain": [ - "SEX | AGE | 2019\n", - "0 | 999 | 328239523\n", - "1 | 999 | 161657324\n", - "2 | 999 | 166582199" + "shape: (3, 3)\n", + "┌─────┬─────┬───────────┐\n", + "│ SEX ┆ AGE ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪═══════════╡\n", + "│ 0 ┆ 999 ┆ 328239523 │\n", + "│ 1 ┆ 999 ┆ 161657324 │\n", + "│ 2 ┆ 999 ┆ 166582199 │\n", + "└─────┴─────┴───────────┘" ] }, - "execution_count": 6, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "us_pop_2019 = us_pop.drop('2014')\n", - "all_ages = us_pop_2019.where('AGE', are.equal_to(999))\n", + "all_ages = us_pop_2019.filter(pl.col('AGE') == 999)\n", "all_ages" ] }, @@ -221,57 +188,53 @@ "source": [ "Row 0 of `all_ages` contains the total U.S. population in each of the two years. The United States had about 330 million people in 2019.\n", "\n", - "Row 1 contains the counts for males and Row 2 for females. Compare these two rows to see that in 2019, there were more females than males in the United States. \n", + "Row 1 contains the counts for males and Row 2 for females. Compare these two rows to see that in 2019, there were more females than males in the United States.\n", "\n", - "The population counts in Row 1 and Row 2 add up to the total population in Row 0. \n", + "The population counts in Row 1 and Row 2 add up to the total population in Row 0.\n", "\n", - "For comparability with other quantities, we will need to convert these counts to percents out of the total population. Let's access the total for 2019 and name it. Then, we'll show a population table with a proportion column. Consistent with our earlier observation that there were more females than males, 50.75% of the population in 2019 was female and about 49.25% was male. " + "For comparability with other quantities, we will need to convert these counts to percents out of the total population. Let's access the total for 2019 and name it. Then, we'll show a population DataFrame with a proportion column. Consistent with our earlier observation that there were more females than males, 50.75% of the population in 2019 was female and about 49.25% was male." ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2019 Proportion
0 999 328239523 100.00%
1 999 161657324 49.25%
2 999 166582199 50.75%
" + "
\n", + "shape: (3, 4)
SEXAGE2019Proportion
i64i64i64str
0999328239523"100.0%"
1999161657324"49.25%"
2999166582199"50.75%"
" ], "text/plain": [ - "SEX | AGE | 2019 | Proportion\n", - "0 | 999 | 328239523 | 100.00%\n", - "1 | 999 | 161657324 | 49.25%\n", - "2 | 999 | 166582199 | 50.75%" + "shape: (3, 4)\n", + "┌─────┬─────┬───────────┬────────────┐\n", + "│ SEX ┆ AGE ┆ 2019 ┆ Proportion │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 ┆ str │\n", + "╞═════╪═════╪═══════════╪════════════╡\n", + "│ 0 ┆ 999 ┆ 328239523 ┆ 100.0% │\n", + "│ 1 ┆ 999 ┆ 161657324 ┆ 49.25% │\n", + "│ 2 ┆ 999 ┆ 166582199 ┆ 50.75% │\n", + "└─────┴─────┴───────────┴────────────┘" ] }, - "execution_count": 7, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "pop_2019 = all_ages.column('2019').item(0)\n", - "all_ages.with_column(\n", - " 'Proportion', all_ages.column('2019')/pop_2019\n", - ").set_format('Proportion', PercentFormatter)" + "pop_2019 = all_ages.get_column('2019').item(0)\n", + "all_ages.with_columns(\n", + " ((pl.col('2019') / pop_2019) * 100).round(2).cast(pl.String).add('%').alias('Proportion')\n", + ")" ] }, { @@ -290,45 +253,41 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2019
0 0 3783052
1 0 1935117
2 0 1847935
" + "
\n", + "shape: (3, 3)
SEXAGE2019
i64i64i64
003783052
101935117
201847935
" ], "text/plain": [ - "SEX | AGE | 2019\n", - "0 | 0 | 3783052\n", - "1 | 0 | 1935117\n", - "2 | 0 | 1847935" + "shape: (3, 3)\n", + "┌─────┬─────┬─────────┐\n", + "│ SEX ┆ AGE ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪═════════╡\n", + "│ 0 ┆ 0 ┆ 3783052 │\n", + "│ 1 ┆ 0 ┆ 1935117 │\n", + "│ 2 ┆ 0 ┆ 1847935 │\n", + "└─────┴─────┴─────────┘" ] }, - "execution_count": 8, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "infants = us_pop_2019.where('AGE', are.equal_to(0))\n", + "infants = us_pop_2019.filter(pl.col('AGE') == 0)\n", "infants" ] }, @@ -336,53 +295,49 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "As before, we can convert these counts to percents out of the total numbers of infants. The resulting table shows that in 2019, just over 51% of infants in the U.S. were male. " + "As before, we can convert these counts to percents out of the total numbers of infants. The resulting DataFrame shows that in 2019, just over 51% of infants in the U.S. were male." ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2019 Proportion
0 0 3783052 100.00%
1 0 1935117 51.15%
2 0 1847935 48.85%
" + "
\n", + "shape: (3, 4)
SEXAGE2019Proportion
i64i64i64str
003783052"100.0%"
101935117"51.15%"
201847935"48.85%"
" ], "text/plain": [ - "SEX | AGE | 2019 | Proportion\n", - "0 | 0 | 3783052 | 100.00%\n", - "1 | 0 | 1935117 | 51.15%\n", - "2 | 0 | 1847935 | 48.85%" + "shape: (3, 4)\n", + "┌─────┬─────┬─────────┬────────────┐\n", + "│ SEX ┆ AGE ┆ 2019 ┆ Proportion │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 ┆ str │\n", + "╞═════╪═════╪═════════╪════════════╡\n", + "│ 0 ┆ 0 ┆ 3783052 ┆ 100.0% │\n", + "│ 1 ┆ 0 ┆ 1935117 ┆ 51.15% │\n", + "│ 2 ┆ 0 ┆ 1847935 ┆ 48.85% │\n", + "└─────┴─────┴─────────┴────────────┘" ] }, - "execution_count": 9, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "infants_2019 = infants.column('2019').item(0)\n", - "infants.with_column(\n", - " 'Proportion', infants.column('2019')/infants_2019\n", - ").set_format('Proportion', PercentFormatter)" + "infants_2019 = infants.get_column('2019').item(0)\n", + "infants.with_columns(\n", + " ((pl.col('2019') / infants_2019) * 100).round(2).cast(pl.String).add('%').alias('Proportion')\n", + ")" ] }, { @@ -407,156 +362,104 @@ "\n", "To study this variation, we will separate out the data for the females and the males, and eliminate the row where all the ages are aggregated and `AGE` is coded as 999.\n", "\n", - "The tables `females` and `males` contain the data for each the two sex codes." + "The DataFrames `females` and `males` contain the data for each the two sex codes." ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2019
2 0 1847935
2 1 1871014
2 2 1916500
2 3 1955655
2 4 1976372
2 5 1967081
2 6 1964271
2 7 1966584
2 8 1986471
2 9 1988726
\n", - "

... (91 rows omitted)

" + "
\n", + "shape: (101, 3)
SEXAGE2019
i64i64i64
201847935
211871014
221916500
231955655
241976372
………
296111417
29784358
29862607
29942528
210076850
" ], "text/plain": [ - "SEX | AGE | 2019\n", - "2 | 0 | 1847935\n", - "2 | 1 | 1871014\n", - "2 | 2 | 1916500\n", - "2 | 3 | 1955655\n", - "2 | 4 | 1976372\n", - "2 | 5 | 1967081\n", - "2 | 6 | 1964271\n", - "2 | 7 | 1966584\n", - "2 | 8 | 1986471\n", - "2 | 9 | 1988726\n", - "... (91 rows omitted)" + "shape: (101, 3)\n", + "┌─────┬─────┬─────────┐\n", + "│ SEX ┆ AGE ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪═════════╡\n", + "│ 2 ┆ 0 ┆ 1847935 │\n", + "│ 2 ┆ 1 ┆ 1871014 │\n", + "│ 2 ┆ 2 ┆ 1916500 │\n", + "│ 2 ┆ 3 ┆ 1955655 │\n", + "│ 2 ┆ 4 ┆ 1976372 │\n", + "│ … ┆ … ┆ … │\n", + "│ 2 ┆ 96 ┆ 111417 │\n", + "│ 2 ┆ 97 ┆ 84358 │\n", + "│ 2 ┆ 98 ┆ 62607 │\n", + "│ 2 ┆ 99 ┆ 42528 │\n", + "│ 2 ┆ 100 ┆ 76850 │\n", + "└─────┴─────┴─────────┘" ] }, - "execution_count": 10, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "females_all_rows = us_pop_2019.where('SEX', are.equal_to(2))\n", - "females = females_all_rows.where('AGE', are.not_equal_to(999))\n", + "females_all_rows = us_pop_2019.filter(pl.col('SEX') == 2)\n", + "females = females_all_rows.filter(pl.col('AGE') != 999)\n", "females" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2019
1 0 1935117
1 1 1958585
1 2 2005544
1 3 2043010
1 4 2066951
1 5 2061200
1 6 2052956
1 7 2055735
1 8 2079723
1 9 2073148
\n", - "

... (91 rows omitted)

" + "
\n", + "shape: (101, 3)
SEXAGE2019
i64i64i64
101935117
111958585
122005544
132043010
142066951
………
19646046
19732611
19823543
19914596
110023472
" ], "text/plain": [ - "SEX | AGE | 2019\n", - "1 | 0 | 1935117\n", - "1 | 1 | 1958585\n", - "1 | 2 | 2005544\n", - "1 | 3 | 2043010\n", - "1 | 4 | 2066951\n", - "1 | 5 | 2061200\n", - "1 | 6 | 2052956\n", - "1 | 7 | 2055735\n", - "1 | 8 | 2079723\n", - "1 | 9 | 2073148\n", - "... (91 rows omitted)" + "shape: (101, 3)\n", + "┌─────┬─────┬─────────┐\n", + "│ SEX ┆ AGE ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪═════════╡\n", + "│ 1 ┆ 0 ┆ 1935117 │\n", + "│ 1 ┆ 1 ┆ 1958585 │\n", + "│ 1 ┆ 2 ┆ 2005544 │\n", + "│ 1 ┆ 3 ┆ 2043010 │\n", + "│ 1 ┆ 4 ┆ 2066951 │\n", + "│ … ┆ … ┆ … │\n", + "│ 1 ┆ 96 ┆ 46046 │\n", + "│ 1 ┆ 97 ┆ 32611 │\n", + "│ 1 ┆ 98 ┆ 23543 │\n", + "│ 1 ┆ 99 ┆ 14596 │\n", + "│ 1 ┆ 100 ┆ 23472 │\n", + "└─────┴─────┴─────────┘" ] }, - "execution_count": 11, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "males_all_rows = us_pop_2019.where('SEX', are.equal_to(1))\n", - "males = males_all_rows.where('AGE', are.not_equal_to(999))\n", + "males_all_rows = us_pop_2019.filter(pl.col('SEX') == 1)\n", + "males = males_all_rows.filter(pl.col('AGE') != 999)\n", "males" ] }, @@ -564,146 +467,154 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The plan now is to compare the number of females and the number of males at each age, for each of the two years. Array and Table methods give us straightforward ways to do this. Both these tables have one row for each age." + "The plan now is to compare the number of females and the number of males at each age, for each of the two years. Polars Series and DataFrame methods give us straightforward ways to do this. Both these DataFrames have one row for each age." ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { + "text/html": [ + "
\n", + "shape: (101,)
AGE
i64
0
1
2
3
4
…
96
97
98
99
100
" + ], "text/plain": [ - "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", - " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", - " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", - " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", - " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", - " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", - " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", - " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100])" + "shape: (101,)\n", + "Series: 'AGE' [i64]\n", + "[\n", + "\t0\n", + "\t1\n", + "\t2\n", + "\t3\n", + "\t4\n", + "\t…\n", + "\t96\n", + "\t97\n", + "\t98\n", + "\t99\n", + "\t100\n", + "]" ] }, - "execution_count": 12, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "males.column('AGE')" + "males.get_column('AGE')" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { + "text/html": [ + "
\n", + "shape: (101,)
AGE
i64
0
1
2
3
4
…
96
97
98
99
100
" + ], "text/plain": [ - "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", - " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", - " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", - " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", - " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", - " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", - " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", - " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100])" + "shape: (101,)\n", + "Series: 'AGE' [i64]\n", + "[\n", + "\t0\n", + "\t1\n", + "\t2\n", + "\t3\n", + "\t4\n", + "\t…\n", + "\t96\n", + "\t97\n", + "\t98\n", + "\t99\n", + "\t100\n", + "]" ] }, - "execution_count": 13, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "females.column('AGE')" + "females.get_column('AGE')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "For any given age, we can get the Female:Male sex ratio by dividing the number of females by the number of males. \n", + "For any given age, we can get the Female:Male sex ratio by dividing the number of females by the number of males.\n", "\n", - "To do this in one step, we can use `column` to extract the array of female counts and the corresponding array of male counts, and then simply divide one array by the other. Elementwise division will create an array of sex ratios for all the years." + "To do this in one step, we can use `get_column` to extract the Polars Series of female counts and the corresponding Polars Series of male counts, and then simply divide one Series by the other. Elementwise division will create a Polars Series of sex ratios for all the years." ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
AGE 2019 F:M RATIO
0 0.954947
1 0.955289
2 0.955601
3 0.957242
4 0.956177
5 0.954338
6 0.956801
7 0.956633
8 0.955161
9 0.959278
\n", - "

... (91 rows omitted)

" + "
\n", + "shape: (101, 2)
AGE2019 F:M RATIO
i64f64
00.954947
10.955289
20.955601
30.957242
40.956177
……
962.419689
972.586796
982.659262
992.913675
1003.274114
" ], "text/plain": [ - "AGE | 2019 F:M RATIO\n", - "0 | 0.954947\n", - "1 | 0.955289\n", - "2 | 0.955601\n", - "3 | 0.957242\n", - "4 | 0.956177\n", - "5 | 0.954338\n", - "6 | 0.956801\n", - "7 | 0.956633\n", - "8 | 0.955161\n", - "9 | 0.959278\n", - "... (91 rows omitted)" + "shape: (101, 2)\n", + "┌─────┬────────────────┐\n", + "│ AGE ┆ 2019 F:M RATIO │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ f64 │\n", + "╞═════╪════════════════╡\n", + "│ 0 ┆ 0.954947 │\n", + "│ 1 ┆ 0.955289 │\n", + "│ 2 ┆ 0.955601 │\n", + "│ 3 ┆ 0.957242 │\n", + "│ 4 ┆ 0.956177 │\n", + "│ … ┆ … │\n", + "│ 96 ┆ 2.419689 │\n", + "│ 97 ┆ 2.586796 │\n", + "│ 98 ┆ 2.659262 │\n", + "│ 99 ┆ 2.913675 │\n", + "│ 100 ┆ 3.274114 │\n", + "└─────┴────────────────┘" ] }, - "execution_count": 14, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "ratios = Table().with_columns(\n", - " 'AGE', females.column('AGE'),\n", - " '2019 F:M RATIO', females.column('2019')/males.column('2019')\n", - ")\n", + "ratios = pl.DataFrame([\n", + " females.get_column('AGE'),\n", + " (females.get_column('2019') / males.get_column('2019')).alias('2019 F:M RATIO'),\n", + "])\n", "ratios" ] }, @@ -718,114 +629,71 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Then how can the overall proportion of females in the population be higher than the males? \n", + "Then how can the overall proportion of females in the population be higher than the males?\n", "\n", - "Something quite different happens when we examine the other end of the age range. Here are the Female:Male ratios for people aged more than 75." + "Something quite different happens when we examine the other end of the age range. Here are the Female:Male ratios for people aged more than 75. `pl.Config(tbl_rows=-1)` shows every row." ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
AGE 2019 F:M RATIO
76 1.21422
77 1.23558
78 1.26373
79 1.28129
80 1.29209
81 1.32745
82 1.36101
83 1.39749
84 1.44603
85 1.48588
86 1.53967
87 1.59775
88 1.66125
89 1.73365
90 1.80539
91 1.90275
92 1.99252
93 2.10192
94 2.2271
95 2.34042
96 2.41969
97 2.5868
98 2.65926
99 2.91367
100 3.27411
" + "
\n", + "shape: (25, 2)
AGE2019 F:M RATIO
i64f64
761.214222
771.235576
781.263727
791.281286
801.292093
811.327453
821.361014
831.397488
841.446027
851.485885
861.53967
871.597752
881.661249
891.733655
901.805392
911.902753
921.99252
932.101919
942.227101
952.34042
962.419689
972.586796
982.659262
992.913675
1003.274114
" ], "text/plain": [ - "" + "shape: (25, 2)\n", + "┌─────┬────────────────┐\n", + "│ AGE ┆ 2019 F:M RATIO │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ f64 │\n", + "╞═════╪════════════════╡\n", + "│ 76 ┆ 1.214222 │\n", + "│ 77 ┆ 1.235576 │\n", + "│ 78 ┆ 1.263727 │\n", + "│ 79 ┆ 1.281286 │\n", + "│ 80 ┆ 1.292093 │\n", + "│ 81 ┆ 1.327453 │\n", + "│ 82 ┆ 1.361014 │\n", + "│ 83 ┆ 1.397488 │\n", + "│ 84 ┆ 1.446027 │\n", + "│ 85 ┆ 1.485885 │\n", + "│ 86 ┆ 1.53967 │\n", + "│ 87 ┆ 1.597752 │\n", + "│ 88 ┆ 1.661249 │\n", + "│ 89 ┆ 1.733655 │\n", + "│ 90 ┆ 1.805392 │\n", + "│ 91 ┆ 1.902753 │\n", + "│ 92 ┆ 1.99252 │\n", + "│ 93 ┆ 2.101919 │\n", + "│ 94 ┆ 2.227101 │\n", + "│ 95 ┆ 2.34042 │\n", + "│ 96 ┆ 2.419689 │\n", + "│ 97 ┆ 2.586796 │\n", + "│ 98 ┆ 2.659262 │\n", + "│ 99 ┆ 2.913675 │\n", + "│ 100 ┆ 3.274114 │\n", + "└─────┴────────────────┘" ] }, + "execution_count": 13, "metadata": {}, - "output_type": "display_data" + "output_type": "execute_result" } ], "source": [ - "ratios.where('AGE', are.above(75)).show()" + "with pl.Config(tbl_rows=-1):\n", + " display(ratios.filter(pl.col('AGE') > 75))" ] }, { @@ -842,88 +710,80 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2019
1 92 131684
1 93 103415
1 99 14596
" + "
\n", + "shape: (3, 3)
SEXAGE2019
i64i64i64
192131684
193103415
19914596
" ], "text/plain": [ - "SEX | AGE | 2019\n", - "1 | 92 | 131684\n", - "1 | 93 | 103415\n", - "1 | 99 | 14596" + "shape: (3, 3)\n", + "┌─────┬─────┬────────┐\n", + "│ SEX ┆ AGE ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪════════╡\n", + "│ 1 ┆ 92 ┆ 131684 │\n", + "│ 1 ┆ 93 ┆ 103415 │\n", + "│ 1 ┆ 99 ┆ 14596 │\n", + "└─────┴─────┴────────┘" ] }, - "execution_count": 16, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "males.where('AGE', are.contained_in(make_array(92, 93, 99)))" + "males.filter(pl.col('AGE').is_in([92, 93, 99]))" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SEX AGE 2019
2 92 262383
2 93 217370
2 99 42528
" + "
\n", + "shape: (3, 3)
SEXAGE2019
i64i64i64
292262383
293217370
29942528
" ], "text/plain": [ - "SEX | AGE | 2019\n", - "2 | 92 | 262383\n", - "2 | 93 | 217370\n", - "2 | 99 | 42528" + "shape: (3, 3)\n", + "┌─────┬─────┬────────┐\n", + "│ SEX ┆ AGE ┆ 2019 │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ i64 ┆ i64 ┆ i64 │\n", + "╞═════╪═════╪════════╡\n", + "│ 2 ┆ 92 ┆ 262383 │\n", + "│ 2 ┆ 93 ┆ 217370 │\n", + "│ 2 ┆ 99 ┆ 42528 │\n", + "└─────┴─────┴────────┘" ] }, - "execution_count": 17, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "females.where('AGE', are.contained_in(make_array(92, 93, 99)))" + "females.filter(pl.col('AGE').is_in([92, 93, 99]))" ] }, { @@ -939,22 +799,29 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 16, "metadata": {}, "outputs": [ { "data": { - "image/png": "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", "text/plain": [ - "A line graph with 'AGE' on the x-axis ranging from 0 to 100 and '2019 F:M RATIO' on the y-axis labeled from 1.0 to 3.0. The line stays around/below 1.0 until age 40. From Age 40 to 8, the ratio increases slowly up to about 1.25. After 80, the ratio increases exponentially up to 3.0 and above." + "[]" ] }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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" + }, "metadata": {}, "output_type": "display_data" } ], "source": [ - "ratios.plot('AGE')" + "plots.plot(ratios.get_column('AGE'), ratios.get_column('2019 F:M RATIO'))" ] } ], From acdedee1d7af3e29087f6317e510090781f93559 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 02:54:36 -0700 Subject: [PATCH 09/17] Ch 1.3 to polars - `Table().with_column('Chapters', huck_finn_chapters)` builds a one-column DataFrame from a named Series: `pl.DataFrame([pl.Series('Chapters', huck_finn_chapters)])`. - The DataFrame display shows the first five and last five rows. A `datascience` table showed the first ten. --- chapters/01/3/Plotting_the_Classics.ipynb | 112 ++++++++++------------ 1 file changed, 48 insertions(+), 64 deletions(-) diff --git a/chapters/01/3/Plotting_the_Classics.ipynb b/chapters/01/3/Plotting_the_Classics.ipynb index ff5c883b0..dfde92327 100644 --- a/chapters/01/3/Plotting_the_Classics.ipynb +++ b/chapters/01/3/Plotting_the_Classics.ipynb @@ -17,10 +17,8 @@ }, "outputs": [], "source": [ - "from datascience import *\n", - "from datascience.predicates import are\n", + "import polars as pl\n", "path_data = '../../../../data/'\n", - "import numpy as np\n", "import matplotlib\n", "matplotlib.use('Agg')\n", "%matplotlib inline\n", @@ -67,7 +65,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "While a computer cannot understand the text of a book, it can provide us with some insight into the structure of the text. The name `huck_finn_chapters` is currently bound to a list of all the chapters in the book. We can place them into a table to see how each chapter begins." + "While a computer cannot understand the text of a book, it can provide us with some insight into the structure of the text. The name `huck_finn_chapters` is currently bound to a list of all the chapters in the book. We can place them into a DataFrame to see how each chapter begins." ] }, { @@ -76,73 +74,59 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 3, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Chapters
I. YOU don't know about me without you have read a book ...
II. WE went tiptoeing along a path amongst the trees bac ...
III. WELL, I got a good going-over in the morning from o ...
IV. WELL, three or four months run along, and it was wel ...
V. I had shut the door to. Then I turned around and ther ...
VI. WELL, pretty soon the old man was up and around agai ...
VII. \"GIT up! What you 'bout?\" I opened my eyes and look ...
VIII. THE sun was up so high when I waked that I judged ...
IX. I wanted to go and look at a place right about the m ...
X. AFTER breakfast I wanted to talk about the dead man a ...
\n", - "

... (33 rows omitted)

" - ], "text/plain": [ - "Chapters\n", - "I. YOU don't know about me without you have read a book ...\n", - "II. WE went tiptoeing along a path amongst the trees bac ...\n", - "III. WELL, I got a good going-over in the morning from o ...\n", - "IV. WELL, three or four months run along, and it was wel ...\n", - "V. I had shut the door to. Then I turned around and ther ...\n", - "VI. WELL, pretty soon the old man was up and around agai ...\n", - "VII. \"GIT up! What you 'bout?\" I opened my eyes and look ...\n", - "VIII. THE sun was up so high when I waked that I judged ...\n", - "IX. I wanted to go and look at a place right about the m ...\n", - "X. AFTER breakfast I wanted to talk about the dead man a ...\n", - "... (33 rows omitted)" + "shape: (43, 1)\n", + "┌──────────────────────────────────────────────────────────────────────────────────────────────────┐\n", + "│ Chapters │\n", + "│ --- │\n", + "│ str │\n", + "╞══════════════════════════════════════════════════════════════════════════════════════════════════╡\n", + "│ I. YOU don't know about me without you have read a book by the name of The Adventures of Tom │\n", + "│ Sawyer; but that ain't no matter. That book was made by Mr. Mark Tw… │\n", + "│ II. WE went tiptoeing along a path amongst the trees back towards the end of the widow's garden, │\n", + "│ stooping down so as the branches wouldn't scrape our heads. Whe… │\n", + "│ III. WELL, I got a good going-over in the morning from old Miss Watson on account of my clothes; │\n", + "│ but the widow she didn't scold, but only cleaned off the grease… │\n", + "│ IV. WELL, three or four months run along, and it was well into the winter now. I had been to │\n", + "│ school most all the time and could spell and read and write just a … │\n", + "│ V. I had shut the door to. Then I turned around and there he was. I used to be scared of him all │\n", + "│ the time, he tanned me so much. I reckoned I was scared now, to… │\n", + "│ … │\n", + "│ XXXIX. IN the morning we went up to the village and bought a wire rat-trap and fetched it down, │\n", + "│ and unstopped the best rat-hole, and in about an hour we had fif… │\n", + "│ XL. WE was feeling pretty good after breakfast, and took my canoe and went over the river │\n", + "│ a-fishing, with a lunch, and had a good time, and took a look at the r… │\n", + "│ XLI. THE doctor was an old man; a very nice, kind-looking old man when I got him up. I told him │\n", + "│ me and my brother was over on Spanish Island hunting yesterday a… │\n", + "│ XLII. THE old man was uptown again before breakfast, but couldn't get no track of Tom; and both │\n", + "│ of them set at the table thinking, and not saying nothing, and l… │\n", + "│ THE LAST THE first time I catched Tom private I asked him what was his idea, time of the │\n", + "│ evasion?--what it was he'd planned to do if the evasion worked all righ… │\n", + "└──────────────────────────────────────────────────────────────────────────────────────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (43, 1)
Chapters
str
"I. YOU don't know about me without you have read a book by the name of The Adventures of Tom Sawyer; but that ain't no matter. That book was made by Mr. Mark Tw…
"II. WE went tiptoeing along a path amongst the trees back towards the end of the widow's garden, stooping down so as the branches wouldn't scrape our heads. Whe…
"III. WELL, I got a good going-over in the morning from old Miss Watson on account of my clothes; but the widow she didn't scold, but only cleaned off the grease…
"IV. WELL, three or four months run along, and it was well into the winter now. I had been to school most all the time and could spell and read and write just a …
"V. I had shut the door to. Then I turned around and there he was. I used to be scared of him all the time, he tanned me so much. I reckoned I was scared now, to…
…
"XXXIX. IN the morning we went up to the village and bought a wire rat-trap and fetched it down, and unstopped the best rat-hole, and in about an hour we had fif…
"XL. WE was feeling pretty good after breakfast, and took my canoe and went over the river a-fishing, with a lunch, and had a good time, and took a look at the r…
"XLI. THE doctor was an old man; a very nice, kind-looking old man when I got him up. I told him me and my brother was over on Spanish Island hunting yesterday a…
"XLII. THE old man was uptown again before breakfast, but couldn't get no track of Tom; and both of them set at the table thinking, and not saying nothing, and l…
"THE LAST THE first time I catched Tom private I asked him what was his idea, time of the evasion?--what it was he'd planned to do if the evasion worked all righ…
" ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "# Display the chapters of Huckleberry Finn in a table.\n", + "# Display the chapters of Huckleberry Finn in a DataFrame.\n", "\n", - "Table().with_column('Chapters', huck_finn_chapters)" + "# POLARS_CHANGE: show enough of each chapter string to include the opening sentence\n", + "with pl.Config(fmt_str_lengths=160):\n", + " display(pl.DataFrame([pl.Series(\"Chapters\", huck_finn_chapters)]))" ] }, { From 69973b7adb8dc65def2eda25c6734ceb8aeecd62 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 02:55:06 -0700 Subject: [PATCH 10/17] Ch 1.3.1 to polars - `np.char.count(chapters, name)` counts a literal substring. `Series.str.count_matches(name)` treats the pattern as a regular expression, so the call passes `literal=True`. - `np.cumsum(...)` is `Series.cum_sum()` on that count Series. - `Table().with_columns([name, values, ...])` took a flat list of labels and arrays. The DataFrame is a list of named Series. - `np.arange(1, 44, 1)` and `np.arange(1, 48, 1)` are `range(1, 44)` and `range(1, 48)`, passed as a Series named `Chapter`. - `Table.with_column(name, values)` is `DataFrame.with_columns(pl.Series(name, values))`. - `cum_counts.plot(column_for_xticks=3)` plotted every other column against column 3 (`Chapter`). Polars does not plot, so each name is one `plots.plot` of `Chapter` against that name. The Little Women call used column 5, which is also `Chapter`. POLARS_CHANGE: - Comment on `literal=True`: `count_matches` treats the pattern as a regular expression unless `literal=True`. The same comment is on the Huckleberry Finn counts and the Little Women counts. - Comment on the plots: Polars does not plot, so each name is drawn against `Chapter`. - `fmt_str_lengths=160` on the Little Women chapter DataFrame, same reason as in Plotting the Classics. --- chapters/01/3/1/Literary_Characters.ipynb | 182 ++++++++++------------ 1 file changed, 85 insertions(+), 97 deletions(-) diff --git a/chapters/01/3/1/Literary_Characters.ipynb b/chapters/01/3/1/Literary_Characters.ipynb index c49f619ea..0b4acdabe 100644 --- a/chapters/01/3/1/Literary_Characters.ipynb +++ b/chapters/01/3/1/Literary_Characters.ipynb @@ -17,8 +17,7 @@ }, "outputs": [], "source": [ - "from datascience import Table\n", - "import numpy as np\n", + "import polars as pl\n", "path_data = '../../../'\n", "import matplotlib\n", "matplotlib.use('Agg')\n", @@ -64,35 +63,37 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [ { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, + "output_type": "display_data", "metadata": {}, - "output_type": "display_data" + "data": { + "image/png": "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aRWSCF8eJciKSdClV0LN33vIHyqPH6Q1UO6atB0grd1S4kTIHVHVRwCSoy2J/EKCd38dxmQZWVYC/VtuucXvukgLvLS0yfCv1R1Qwayz3NVpw4VLMOovVUDu1uR3SI9b2a7Squo9JLkE1hJwyx2X3OXp0Uodyu/0rlktj6K0FslA10cjObdSfkZT3Xb3R+5MZb3kgi0/y7EigZic6NLbvK7k5kEr8SbBXU0jT8nf7T3SpN7+isZjVe93ybEgQb8En3IcSIuBDIxSm5EL67LfAv2760pahaQmqrRCyM2ObA9ZF9k3Nf1tclGXGyU5ToIZ5U6PfNDI8SKpJtKbvTpyPGk3O/IYteoTH+9jS0Y581d/W1prtdEtJZ3HX4UCOX+13HnJma1uO0mfDbmBlnWQa7w8mZB9Lq08cu3x13dCjjdpaJFzUp6uyfvItUU+3OQDOZgycZLqE0hZt6rkplJv1FC5jsq5IUGwBNzypENa57TgW57GynVYguILL7yw2t8hx6B0UJbl5diSGzs5P+TJTtW/OdD9KqSGvpCnMXXpD+C9zWRdJNCpjjxp8u5oLQ0H/oLLYLZfNB7b/shng9bYIAFxoC3bGkmrlc9paUmVY1WOF0lV0BqtJNVSK+kmf6cEsfI3yPVCtnd1NZRD9T6h3IalYThuwnFNCllATURERESh5y8Qbqj3IV+hr6lGRERERBRHGFATEREREQWBATURERERURAYUBMRERERBaHOZfOIiIiIqP7JOB9SjlFIFYyGfh/yxSofRERERERBYMoHEREREVEQGFATEREREQWBATURERERURAYUBMRERERBYEBNRERERFREBhQExEREREFgQE1EREREVEQGFATEREREQWBATURERERURAYUBMRERERBYEBNRERERFREBhQExEREREFgQE1EREREVEQGFATEREREQWBATURERERURAYUBMRERERBYEBNRERERFREBhQExEREREFgQE1EREREVEQGFATEREREQWBATURERERURAYUBMRERERBYEBNRERERFREBhQExEREREFgQE1EREREVEQGFATEREREQWBATURERERURAYUBMRERERBYEBNRERERFREBhQExEREREFgQE1EREREVEQGFATEREREQWBATURERERURAYUBMRERERBYEBdQMrLy/H9u3b1e8Ue7h/Yx/3cWzj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AB/e+0yOB6kYIUGYHAdyIyXntgRfkqcrgTlFhvz8fLU1WXJi27Vrp6Z0SHAtZdG0p0gvvviiOhiIRlqm5Zp97NgxNTWvW7du6uiZkiIgdYvlHObw8pFPrsN6A7uIf/7zn3juuefU4FlGvpTPaQmu5WmV1KKWNBIiPQyoG4CcmDIEqrRkaY+a5AP4pptuUutlyocwRT5J3xg2bJjf+TI4hDZQgGbZsmUVw1Nr5MNcAjepY0uRQ/bT9OnTq11G9qcMWa3RWiulNUt+FvLBLIO9/Otf/6pUNYIaltzkSI60DDNetRSaBMWSLy9PKKqSJw4SWEltee8UEenAqFe/mKIroJbPZGkIkacU2pNEeeogg71IMO2vygsRA+oGJMMWy0ktAbTkbmVnZ/OIjCIFBQXq6Ib+SMumXsAtF+xVq1ap+19yMmXf8zFx5JGcWMmhrc6IESPUR8tVSWUBueESPXr0UPPjKXIDaxmMRZ4UScOGBMfydKm6hg1FUSrOYdm3klfLczh6yHVbrt9jxozxe5MrN1nSt0Wu1927d/dbf5xIw4CaiIiIiCgI7D1BRERERBQEBtREREREREFgQE1EREREFAQG1EREREREQWBATUREREQUBAbURERERERBYEBNRERERBQEBtREREREREFgQE1EREREFAQG1EREREREQWBATUREREQUBAbURERERERBYEBNRERERIS6+3/RgwIq2z3TcwAAAABJRU5ErkJggg==" + } } ], "source": [ "# Get the cumulative counts the names Jim, Tom, and Huck appear in each chapter.\n", "\n", - "counts = Table().with_columns([\n", - " 'Jim', np.cumsum(np.char.count(huck_finn_chapters, 'Jim')),\n", - " 'Tom', np.cumsum(np.char.count(huck_finn_chapters, 'Tom')),\n", - " 'Huck', np.cumsum(np.char.count(huck_finn_chapters, 'Huck'))\n", - " ])\n", + "# POLARS_CHANGE: count_matches treats the pattern as a regular expression unless literal=True\n", + "huck_finn = pl.Series(\"chapter\", huck_finn_chapters)\n", + "counts = pl.DataFrame([\n", + " huck_finn.str.count_matches(\"Jim\", literal=True).cum_sum().alias(\"Jim\"),\n", + " huck_finn.str.count_matches(\"Tom\", literal=True).cum_sum().alias(\"Tom\"),\n", + " huck_finn.str.count_matches(\"Huck\", literal=True).cum_sum().alias(\"Huck\"),\n", + "])\n", "\n", "# Plot the cumulative counts:\n", "# how many times in Chapter 1, how many times in Chapters 1 and 2, and so on.\n", "\n", - "cum_counts = counts.with_column('Chapter', np.arange(1, 44, 1))\n", - "cum_counts.plot(column_for_xticks=3)\n", - "plots.title('Cumulative Number of Times Each Name Appears', y=1.08);" + "cum_counts = counts.with_columns(pl.Series(\"Chapter\", range(1, 44)))\n", + "# POLARS_CHANGE: Polars does not plot, so each name is drawn against Chapter\n", + "for name in [\"Jim\", \"Tom\", \"Huck\"]:\n", + " plots.plot(cum_counts.get_column(\"Chapter\"), cum_counts.get_column(name), label=name)\n", + "plots.legend()\n", + "plots.title(\"Cumulative Number of Times Each Name Appears\", y=1.08);" ] }, { @@ -117,73 +118,59 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 4, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Chapters
ONE PLAYING PILGRIMS \"Christmas won't be Christmas witho ...
TWO A MERRY CHRISTMAS Jo was the first to wake in the gr ...
THREE THE LAURENCE BOY \"Jo! Jo! Where are you?\" cried Me ...
FOUR BURDENS \"Oh, dear, how hard it does seem to take up ...
FIVE BEING NEIGHBORLY \"What in the world are you going t ...
SIX BETH FINDS THE PALACE BEAUTIFUL The big house did pr ...
SEVEN AMY'S VALLEY OF HUMILIATION \"That boy is a perfect ...
EIGHT JO MEETS APOLLYON \"Girls, where are you going?\" as ...
NINE MEG GOES TO VANITY FAIR \"I do think it was the most ...
TEN THE P.C. AND P.O. As spring came on, a new set of am ...
\n", - "

... (37 rows omitted)

" - ], "text/plain": [ - "Chapters\n", - "ONE PLAYING PILGRIMS \"Christmas won't be Christmas witho ...\n", - "TWO A MERRY CHRISTMAS Jo was the first to wake in the gr ...\n", - "THREE THE LAURENCE BOY \"Jo! Jo! Where are you?\" cried Me ...\n", - "FOUR BURDENS \"Oh, dear, how hard it does seem to take up ...\n", - "FIVE BEING NEIGHBORLY \"What in the world are you going t ...\n", - "SIX BETH FINDS THE PALACE BEAUTIFUL The big house did pr ...\n", - "SEVEN AMY'S VALLEY OF HUMILIATION \"That boy is a perfect ...\n", - "EIGHT JO MEETS APOLLYON \"Girls, where are you going?\" as ...\n", - "NINE MEG GOES TO VANITY FAIR \"I do think it was the most ...\n", - "TEN THE P.C. AND P.O. As spring came on, a new set of am ...\n", - "... (37 rows omitted)" + "shape: (47, 1)\n", + "┌──────────────────────────────────────────────────────────────────────────────────────────────────┐\n", + "│ Chapters │\n", + "│ --- │\n", + "│ str │\n", + "╞══════════════════════════════════════════════════════════════════════════════════════════════════╡\n", + "│ ONE PLAYING PILGRIMS \"Christmas won't be Christmas without any presents,\" grumbled Jo, lying on │\n", + "│ the rug. \"It's so dreadful to be poor!\" sighed Meg, looking down… │\n", + "│ TWO A MERRY CHRISTMAS Jo was the first to wake in the gray dawn of Christmas morning. No │\n", + "│ stockings hung at the fireplace, and for a moment she felt as much disa… │\n", + "│ THREE THE LAURENCE BOY \"Jo! Jo! Where are you?\" cried Meg at the foot of the garret stairs. │\n", + "│ \"Here!\" answered a husky voice from above, and, running up, Meg foun… │\n", + "│ FOUR BURDENS \"Oh, dear, how hard it does seem to take up our packs and go on,\" sighed Meg the │\n", + "│ morning after the party, for now the holidays were over, the week … │\n", + "│ FIVE BEING NEIGHBORLY \"What in the world are you going to do now, Jo?\" asked Meg one snowy │\n", + "│ afternoon, as her sister came tramping through the hall, in rubber bo… │\n", + "│ … │\n", + "│ FORTY-THREE SURPRISES Jo was alone in the twilight, lying on the old sofa, looking at the fire, │\n", + "│ and thinking. It was her favorite way of spending the hour of du… │\n", + "│ FORTY-FOUR MY LORD AND LADY \"Please, Madam Mother, could you lend me my wife for half an hour? │\n", + "│ The luggage has come, and I've been making hay of Amy's Paris fin… │\n", + "│ FORTY-FIVE DAISY AND DEMI I cannot feel that I have done my duty as humble historian of the │\n", + "│ March family, without devoting at least one chapter to the two most … │\n", + "│ FORTY-SIX UNDER THE UMBRELLA While Laurie and Amy were taking conjugal strolls over velvet │\n", + "│ carpets, as they set their house in order, and planned a blissful fut… │\n", + "│ FORTY-SEVEN HARVEST TIME For a year Jo and her Professor worked and waited, hoped and loved, met │\n", + "│ occasionally, and wrote such voluminous letters that the rise i… │\n", + "└──────────────────────────────────────────────────────────────────────────────────────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (47, 1)
Chapters
str
"ONE PLAYING PILGRIMS "Christmas won't be Christmas without any presents," grumbled Jo, lying on the rug. "It's so dreadful to be poor!" sighed Meg, looking down…
"TWO A MERRY CHRISTMAS Jo was the first to wake in the gray dawn of Christmas morning. No stockings hung at the fireplace, and for a moment she felt as much disa…
"THREE THE LAURENCE BOY "Jo! Jo! Where are you?" cried Meg at the foot of the garret stairs. "Here!" answered a husky voice from above, and, running up, Meg foun…
"FOUR BURDENS "Oh, dear, how hard it does seem to take up our packs and go on," sighed Meg the morning after the party, for now the holidays were over, the week …
"FIVE BEING NEIGHBORLY "What in the world are you going to do now, Jo?" asked Meg one snowy afternoon, as her sister came tramping through the hall, in rubber bo…
…
"FORTY-THREE SURPRISES Jo was alone in the twilight, lying on the old sofa, looking at the fire, and thinking. It was her favorite way of spending the hour of du…
"FORTY-FOUR MY LORD AND LADY "Please, Madam Mother, could you lend me my wife for half an hour? The luggage has come, and I've been making hay of Amy's Paris fin…
"FORTY-FIVE DAISY AND DEMI I cannot feel that I have done my duty as humble historian of the March family, without devoting at least one chapter to the two most …
"FORTY-SIX UNDER THE UMBRELLA While Laurie and Amy were taking conjugal strolls over velvet carpets, as they set their house in order, and planned a blissful fut…
"FORTY-SEVEN HARVEST TIME For a year Jo and her Professor worked and waited, hoped and loved, met occasionally, and wrote such voluminous letters that the rise i…
" ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "# The chapters of Little Women, in a table\n", + "# The chapters of Little Women, in a DataFrame\n", "\n", - "Table().with_column('Chapters', little_women_chapters)" + "# POLARS_CHANGE: show enough of each chapter string to include the opening sentence\n", + "with pl.Config(fmt_str_lengths=160):\n", + " display(pl.DataFrame([pl.Series(\"Chapters\", little_women_chapters)]))" ] }, { @@ -195,39 +182,40 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "scrolled": false }, "outputs": [ { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAj8AAAHECAYAAADWEUtwAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAACniUlEQVR4nOzdd3iTVfvA8W9mRzrpnsxSNggyZMlQBEHZggMVB4oTXxUH/kBRQXGiLwIKKgJOwIHiFhARCq8CRUAoq9BSutORJmnG8/ujNBDaQoHu3p/r6tX2POdJznOy7pypMhqNCkIIIYQQjYS6tgsghBBCCFGTJPgRQgghRKMiwY8QQgghGhUJfoQQQgjRqEjwI4QQQohGRYIfIYQQQjQqEvycZe7cuQQEBLBp06ZqvZ/hw4cTEBBQrffRmJTWZ3Jycm0XpcrYbDZeeuklunXrRlhYGAEBAaxcubJK7yMgIIDhw4dX6W2KspKTk6WuhahDLij4OXjwIE8++SR9+vQhNjaWkJAQ4uLiGD16NO+++y75+fnVVc56p759GK9cuZKAgAACAgJ46qmnys1z4MABeQOvQf/973956aWX8PHx4f777+eJJ56gY8eO5eadOnWq6/GrzE9Dfww3bdpUqXowGo21XdSLUvr+0qRJE3bt2lVunmeffbZaAua6Kisri9DQUAICAnj00UdruziijtNWNuNrr73Giy++iNPppFu3bkyYMAE/Pz+ysrLYsmUL06dP56WXXuLw4cPVWd4GY9GiRZjN5touRrmWLFnC3XffTYsWLWq7KI3ajz/+CMDnn39OWFjYOfMOHz6c2NhYt7Tdu3ezbt06OnToUCbYKc27bds2vLy8qrDUdUtMTAw33XRThcc9PT1rsDRVz+l08swzz7B27draLkqtW7lyJcXFxahUKr744gtmz56NwWCo7WKJOqpSwc+bb77J888/T1RUFO+//z49e/Ysk2fz5s1Mnz69ygvYUMXExNR2EcrVsmVLDh06xMyZM1mxYkVtF6dRS0tLAzhv4AMwYsQIRowY4Za2cuVK1q1bR8eOHStszWvduvWlF7QOi42NrfDaG4KWLVuyadMm1q1bx7XXXlvbxak1iqKwbNkyvLy8uOOOO1iwYAGrV6/m1ltvre2iiTrqvN1ex44d48UXX0Sn0/Hpp5+WG/gA9OnTh99++831f2kf99SpU8vNX9pMf2a30Jn94hkZGdx///3ExcURGRnJkCFD2Lx5MwCFhYU8/fTTdOjQgdDQUHr27MlXX31V5j7ON37nQpr/v/32W+6++266du1KZGQkUVFR9O/fn3feeQeHw1HmdkvL2rlzZ1cT+5ldFmeP+Vm9ejUBAQE8/vjj5d6/0+mkbdu2REZGUlBQ4Hbs66+/ZuTIkTRr1ozQ0FC6du3Ks88+e1HdkCNGjODyyy/n22+/5c8//6zUORdTz6XnrFy5kvXr1zNs2DCioqJo2bIl9913n6s7YseOHYwfP56mTZsSFRXFxIkTz9mVqCgK//3vf+nevTthYWG0b9+eGTNmlKmzUunp6Tz55JN07dqVsLAwmjZtyujRo9m4cWOZvKVdg3PnziUhIYExY8bQtGnTSnefpKen8/jjj9O5c2dCQ0Np3rw5N9xwA3/88YdbvrNfG+U9f6pKTT02eXl5vPjii1xxxRVEREQQHR3N0KFDy33dKorCihUrGDJkCC1btiQsLIx27dpx3XXXsWzZsqquApeDBw/y7LPPMmDAAFq2bEloaCgdOnTgoYce4vjx4xWet3HjRm666SZat25NSEgIbdq0YfTo0Xz55Zfl5s/Ozubhhx8mPj6e0NBQevXqxUcffXRRZZ45cyYajYZZs2Zht9srdc7OnTuZPn06vXv3pmnTpoSFhdG1a1eefvppcnNzy+Q/83m/Y8cOxo4dS2xsLLGxsUyaNImUlBQADh8+zO23307Lli0JDw9n+PDh7N69u9wyWCwW3n77ba688kqioqKIjIxkwIABvP/++yjKhe+49Pvvv3P48GGuu+467rnnHlQqFR9++GGF+UtfT3l5eTz++OO0bduWsLAwevXqxXvvvVemDGd+NqWlpTFlyhTXdQ4YMIA1a9acs2wTJ06kZcuWhISE0KFDBx599FHS09PL5L2Ux6ai96RNmzYxYcIE2rdvT2hoKK1atWLAgAHMmDHjouq6oThv8LNy5UpsNhsjRow475uvh4dHlRQqLy+Pa665hn379jF+/HiGDBnC9u3bGTt2LImJiVx//fX89ttvXHvttYwdO5YjR44wefJktm/fXiX3X57nnnuOxMRELr/8cqZMmcINN9zgCsLuuecet7xPPPGEq2Xn3nvv5YknnuCJJ56oMBCEkmDI39+f1atXU1xcXOb4+vXrSUtLY8SIEfj6+rrSH330UW677TYOHjzIiBEjmDJlCqGhobz55psMHTq0wg/9iqhUKl588UWAGnlxfP/990ycOJGwsDBuv/12IiIi+Pjjj7nppptISEjg2muvRa1WM2nSJDp16sQPP/zAhAkTcDqd5d7eU089xauvvkrfvn2599578ff3Z8GCBYwaNQqr1eqWd8+ePfTr14/FixfTvHlz7r77boYPH87ff//NqFGjWL58ebn3sW3bNkaMGIHD4eDWW29l3LhxaDSac15ncnIyAwcO5L333iM6Opr777+foUOHsmnTJq6//nq3D7/hw4fzxBNP4OfnB1Cp5091qKrH5sSJEwwaNIhXXnmFgIAAbr/9dsaOHUtycjK33347c+fOdcv/7LPP8sADD3Dy5ElGjRrF/fffz8CBA8nPz+fTTz+ttutdu3Yt77//PlFRUYwdO5YpU6YQHx/P8uXLGTRoEKmpqWXOefnllxk5ciTr16+nX79+PPjgg1x11VWkp6ezZMmSMvlL39u2b9/O9ddfz8SJE0lLS+Ohhx66qJbWtm3bcsstt5CUlMT7779fqXOWLVvGl19+SevWrbnllluYPHkyoaGhvPPOOwwZMqTC94wdO3Zw7bXXotVqufXWW2nfvj1r165l5MiR/PvvvwwaNIjs7GxuvPFG+vXrx+bNmxk9ejSFhYVut1NQUMDw4cP5v//7PxRF4aabbuLmm28mPz+f//znP9x3330XXA8ffPABADfffDOxsbH079+fv//+u8LxUFAyoWDUqFH89ttvjB07lltvvZWcnBwef/xxnnzyyXLPMRqNrs+mW265hQkTJnD48GFXa9PZ3nzzTa6//noSEhK46qqrmDp1KvHx8SxdupSBAweWeU5d7GNT0XvSTz/9xPXXX8+WLVvo27cvDzzwANdffz3+/v4sXry4zBf3RsVoNCrn+unfv78CKG+99dY58539s2vXLgVQbrzxxnKP33jjjQqg7Nq1q8w5gHLPPfcoubm5rmMzZ85UAMXPz08ZOXKkkpmZ6Tr23nvvKYAyfPhwt/t44oknFEBZu3ZtuWUAlD59+lTqnB07dpQ5PycnR7nhhhsUQPn555/djvXp06fM9ZV3/My0O+64QwGUZcuWlck/btw4BVC+/vprV9rixYsVQBkxYoSSlpbmln/GjBkKoNx3332VerwWLFigAMq0adMUo9GojBw5UgGUxYsXu/Js27btguqsMvWs0+nc6i4jI0Np166d67Fevny561hubq4yePBgBVBWrlxZbn02adJE2b17tys9OztbufbaaxVAmTlzplt6q1atFA8PD+Xbb791u61///1XiYqKUjw9PZUDBw6UqSNAefPNNy/o9TBo0CAFUJ588km39M2bNyteXl6Kh4eH8s8//7gdi4mJKfMcuZCf0vJW9BqsqcfmyiuvVFQqlbJkyRK39GPHjimdOnVSVCqV8vvvv7vSAwIClIiICCU1NbVMeQ8dOlSpa1+7dq0CKDExMcoTTzxR7s+CBQvcztm7d6+Snp5e5ra++OILRa1WK5MnT3ZLX7NmjQIokZGRys6dO8ucd+bjeeZ72+23365kZ2e7jm3dulXRaDRK69atK/3Ylj7ft23bphw4cEDx8fFRgoKClKNHj7ryTJs2TQHKXGdiYqLb/Zf+vPHGGwqgzJo1q9zn0dnvTWc+5n5+fsqcOXPczrvtttsUQJk7d65b+qRJkxRAefbZZ93S09PTlSFDhiiA8vHHH1e6LpKSkhS9Xq/ExMS4PjPeffddBVDuuOOOCp/3gNKrVy+3x/zQoUNKbGysAig//vhjuY/f6NGjlZycHNexHTt2KH5+foper1cSExNd6d99952iUqmU7t27uz0uRqNRWbRokeu9u6oem/Lek0aMGKEAysaNG8scO3z4cKXruCH+nLflp7RpLjIyslLBVFUwGAzMnDkTlUrlSrvhhhsAyM/P54UXXkCn07mOjRkzBp1OV2ETa1Vo3rx5mTS1Wu36lnJml9/FKh2Y+cknn7il5+fn89133xEdHU2/fv1c6e+88w4ajYa33367zKDV//znPwQFBfH5559fVFmee+459Ho9zz//fLUOzB4/fjzdu3d3/a/X6xk1ahRQ0mV43XXXuY6pVCrGjx8PUOFjfe+997qNp9JoNDz33HOoVCq3b9Y//fQTBw8e5M4776Rv375utxEeHs6DDz6IxWLh66+/LnMfHTp04Pbbb6/0NaampvLbb78RGRnJf/7zH7dj7du354477sBqtfLZZ59V+jZrQlU8Nnv27GHjxo0MHz6ccePGud2+n58fTz75JIqi8MUXX7jS1Wo1Op0OrbbskMSgoKALuobjx4/z8ssvl/vz8ccfu+WNjIwst/X66quvpk2bNmVe44sXLwbg+eefp1mz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1u2i0+lYsWIFY8aM4aabbuLyyy+nc+fOGAwGUlNTSUxMJCkpid9//71Kulhef/11hg4dyosvvsjvv/9O9+7dOXnyJF999RVms5n58+eXOzuoIViyZAkjR47k4YcfZvHixXTv3p3AwEBOnDjBv//+S2JiIitWrCAmJgaz2cyoUaOIjo6me/fuxMTEYLPZ+OOPP9i9ezeXX36569t8ZRw7dqzcgbWl7rjjDsLCwggLC2Ps2LGsXr2afv36udYVWr9+PZ6ennTs2LHMN/gBAwbw5JNP8tJLL9GrVy+uvfZamjZtSlZWFn///Td+fn6VHmxdlWbPns1PP/3EoUOHyhzr2rUrvXr1Yu3atQwZMoRevXqRkZHBL7/8QlxcHBEREdVevnnz5nH48GFefvllPvvsM3r37k1YWBjp6ekcPHiQ7du38+KLL55z9XFFUVxrY51r5mVQUBAjRoxgzZo1rF69mttuu811LDw8HKvVSu/evRk2bBhWq5VvvvmG9PR07rnnnnIHQ7dv356//vqLAQMGMGjQIHJzc/nyyy/Jz8/nxRdfdBtI3L9/f55//nlmzZpFt27duPrqq2nWrBkWi4Xjx4/z559/Ehsb63pfrY7H5plnnuHYsWOu/Tg9PT3Zs2cPv/76K02aNHGrj8am0nt7PfbYY4waNYolS5bw+++/8+mnn1JUVERAQADt2rXj5ZdfLrOHzoQJE1AUhbfeeotPP/0UHx8fBg0axPLly13Ns9Vt+fLlPPfcc3z77be89957xMbG8uCDD/LAAw+U249fnoiICL7//nueffZZtm7dym+//UZcXByvvfYaV155ZbnBzy233EJqaiqff/45CxYswGazERMTU6ngx8PDg3HjxvHee+8B5X8DKTVv3jyGDBnC0qVL+eOPP8jNzcXf35/IyEjuvPNOt28il+KFF15g4MCBFS56WBX1XBXmzJnD2rVrWbZsGceOHSM4OJj77ruPp556qsw05nbt2rF582YWLlzIunXr+OSTT1AUhbCwMNq0acODDz5Y7vihi9G0aVM2bNjAq6++yg8//MDWrVsxGAz06dOHhx56yG0Jg4YmIiKC9evX89577/H111+zevVqbDaba7XZl156yTXuwGAwMHv2bDZt2sT27dv5/vvv8fLyomnTprzwwgtMnjy53CnwFSmd6l6R0kGlAG+//TbNmjVjzZo1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", - "text/plain": [ - "" - ] - }, + "output_type": "display_data", "metadata": {}, - "output_type": "display_data" + "data": { + "image/png": "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emrH35MqKiq0UKYJEybII6ya5s2bF9JnfU1nnXWW2lavXr0CtnvzzTebvnfWrFmt1t93331N6zdt2qR98MEHWnZ2dtMyzyT7v27duqbPPfnkk1p6enqrdmPGjNFWrVrVofv8wgsvNK3//fffW61fuXKlNnXqVM1sNrfaP8/UvXt37emnn2712S+++MLvZ7wn2cdg9mffffdVy/v06aOVlZUF/N2vv/5603ZeffVVn22+/vprba+99vK5TzqdTh3j7du3t/u88v79jzzyiOrLpKQk9X7atGk+P3PHHXcE7K9YPFdbftcbb7yhZWZmttqGbNfXeRTJfvP1u7t169ZsG7fccku7+lv62NcxlCklJUVtt7S01O/152869NBD230OeqaRI0c2HeO22s6cObPpu999992A55a0nT17ttavX79W+z1gwIBm92fZVo8ePVq169u3r/bzzz8H3CfZziGHHOL3GB1++OF+zz+5V9x4442axWLx+3m5p7z00kvtOrbyvZ7tnHzyye3uo6KiIu2II45Q54q//ZT++8c//tHqPGo5zZ07V5s+fbrf7ch3XHPNNQH7dcGCBdqIESNafdZkMmm33XZbWOej9zG74oortMLCQi0vL0+9HzRokFZcXNzqM//73/+aPiOvO+L4xdq5Heok/wWe7b722mtN14ec/7LsjDPOCPj5lsdHJs9nvSe51v7+979r5eXlHbqdSBzDog46b+Q89t7Gaaed1in3pJAs1OXl5eppWRDLj8eyGW2IJeziiy9W+yjuKWKdkqfvr7/+WlmlTjvtNPXk/9///lf5fo8fP15ZxcRiJhaqH3/8UT3ZiFVz1qxZymLYFciTlTzxSYCgBHzKE59YOWpra5UlS57Id+/ejWuvvVY9YV111VXNUiGJe4Nk+fj888/VsptuuqlVUOKoUaOC2hc5jvIEKVZyOXaBrIiep0Wxfog1oSXiLyZWYnkqlmMr/vjSBzIMJt8hx1/aiFVC+iwUq5A/xEosT69PPvmkeiqV7xBrTyKdq9JWjoFYH84++2zVP2IZ+fLLL5XlW84jsYSJn7kvItlv8psk9kKsCbJPsi9yrrZnyFnOa0+KRNnO8ccfr7Yr14ZYf+ScfeSRR9S9S/yZPT7S3kG4MherilxnxxxzTNO2xaIYrYhlRUZKJAj8iiuuUPcJsTDJSIpYek4++WR1jojl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Ywc2b97cLKHesGFD43O8RUbNpdsIEREREXUMbBps59JLL1XXL774YpPFh5s2bcKaNWsQFhamdgIkIiIiIhIcobYzadIktYHLli1bMGrUKEyePFntlLh+/XpVbrFw4UJO7xMRERFRI45QO5CWlqaS6uLiYixfvlyNTEvHDtnsZf78+Y6+hYiIiIjOUByhdkAW/X377bfIyMhAdna26rkso9VaH2oiIiIiIg0TahcGDx6sLkREREREzrDkg4iIiIjIDUyoiYiIiIjcwISaiIiIiMgNTKiJiIiIiNzAhJqIiIiIyA1MqImIiIiI3MCEuoPQ6/Xefgn0NzBuvolx802Mm29i3OhMoCspKbF6+0UQEREREfkqjlATEREREbmBCTURERERkRuYUBMRERERuYEJNRERERGRG5hQExERERG5gQk1EREREZEbDO58M7mnoqICn332GX799Vf19eDBgzFr1iwEBwfzT9sBnDhxAmvXrsWPP/6I2tpa3HvvvSpGzlRXV2P58uVIT09HQ0MDUlJSMHv2bISFhbXr6z6TlZeXY/Xq1di9ezeOHTum/vajRo3CZZddhoCAAIffI7GV41DiZjabMXDgQFx99dUIDw9v99d/prJarfjpp5+wZcsWHDp0CAaDQcXhyiuvRFRUlMPvqa+vxxdffIFt27apGPbv31/FzdnzyfM2bdqEDz74QN1+4oknEB8f3+w58t64YsUKFW95zzznnHPU+2TPnj0ZIvJp7EPtJUeOHFEf8vLhYUvegL755hvExcV566URoD7I169frz7oNZ9++ikuuugip8m3xHPfvn1N7u/VqxdWrVqFxMRE/l097PPPP8ddd92lPqTtnXXWWerxhISEJvcXFxeruGVlZTW5Xz7cv/76a5x99tmMm4fV1NRg5MiRyMvLa/ZYSEgIlixZgkmTJjW5v7S0FNOmTcPOnTub3B8ZGYmvvvoKgwYNYtzaWVVVFVJTUxvjuHnzZjWoYKuyshIzZsxQJ0G25MRXBiPk/wGRr+IItZfMmzdPJdPnnnsubrzxRvj5+eGjjz5CRkaGekxG2ch7JMHq3r07LrjgAvUBISMvrtxxxx0qmU5OTsZNN90Eo9GITz75RI16Snw3btwInU7Xbq//TJSfn69GNq+66ioMGDAAPXr0QG5urhox279/P2699VasWbOmyfcsWLBAxVoSbjnuAgMDsWzZMvz888+4/vrr1YipHJvkOTIrILMJcqwNHz5cDSrIic6XX36JX375RR0/MuMQFBTU+D0LFy5UybScIElcZVZPZhkkiZO4bd++XR2D1H4WL16sTo7Gjx+v4uDIww8/rJLp2NhY3HbbbYiIiFAnQN9//72Km8S7S5cuDBv5JI5Qe8GOHTswZcoU9cGxdetWdO3atfEMf9y4cTh48KB6gxkxYoQ3Xh79mVBLcixJ8AMPPIB33nnH6Qh1dnY2Ro8ejejoaJWIaSUedXV1mDBhgvpZK1euVLfJswm1jFDafyBLUj127Fh1fOXk5DSWBMj9Q4YMUV9LAiYf7lqCJ8ennNy6mpWgtiElADLDExMT0+R+iYMk2VISJ8n15MmT1f3Hjx9X5R2SYEvctFIBi8WCSy65RB2DchIlI6HUPn777TdMnDhR/d0lQZZZOfsR6pKSEnXiKic6EiPbchCJlcwIvvbaa7juuusYNvJJHHrxgnXr1qlrGXnRkmlhMpkwd+5cdfu7777zxkujP8kHdktHlLV4XnvttU3qpf39/XHLLbeo24yn58mol6PRrT59+qiZICEjaPZxk7pbLZkWMsoto55CTmzJs/R6fbNkWouDozULGzZsUMnzzJkzm9TdykzC/Pnz1W0eb+17QiQzPXLyI2U4zsgsn9S9S4mVfW21zPAJxo18GUs+vGDv3r3q2tEItCygsn0OdXxarBzV/2n3MZ7eIzMFMhotH+KSdLfmOJTZB/LeOhMp0QkNDcWwYcMa7+f7Z8cis3cHDhzA0qVLXT6P75PU2TGh9oKioiJ17WhVs3af1BCSb8VTanbtSRmIYDy956mnnsLJkyfVGoXWHoe///57O71KkpIcmRmQhcASGymNk9poiZvtzI+ruMm6Bxnx5vHWfic9Tz/9NB5//HGHswwtfZ+UmVpZgMq4kS9jQu0FMu0lHC2akTIBbVSNfCueWuxsaTFmPL3jww8/xKuvvorbb78d06dPb/KYFhNXx6G0Y6P2IfGQ2luNJMbXXHONqnNv6fundj+Pt/Zx3333qXKqG264wa33SS1utiVZRL6GCbUXSK201kLInnaf9hzq+BjPjumNN97Agw8+iJtvvlmNUtvT1i84Og6lR7zgcdh+JB5paWmqPlpGM6XmVmIo7QtlgZs2Su3qeJOFjHISxLh5nvSSlu5F0k+6JetNXMVNm6Gw7eRC5GuYUHuBNjUmdZ3S1N6W3Kf1Lybfi6dtrad2n2A829eTTz6JF154QZUQPPPMM6eNm3QBcRQ325pr8iwZobziiisav5YToeeee061Y3vvvfdw//33N4ubPWlFKiUjPN4875FHHlGbH8kGLrakVEdrkSdlHM8++6wqfXMVN2mbKP3j2fedfBm7fHiBNoUpq9Xtaauc7ac5qePSYiVtn+xpXSIYz/Yho5v33HOPSqalc4CzZPp0x6EWN1c7Y5LnDR06tFkSxvfPjkHa4EkLQynTsb0cPXpUPS6j1/K17F4q+D5JnR0Tai+4+OKLGzf+0M7mhWxU8PHHH6vHpJ8q+YYLL7xQtWuTbZBlm3KN9J9+9913VTuvyy+/3Kuv8UwgNZqyqY4sYpOkWkapXZG+xjLFLCUFtkm1bALz5ptvqmls2xFT8gwp7bA9bjRS9vHyyy83tj7UyMYhMjIqgw+yq6zt6PQrr7yibrtq30Zt191DSnTsL1rXHBm5lq+1hdmyi6IsJJXNkmRXRI0k4DITwbiRr+PGLl7y0EMP4fXXX1e9VmVTEPnwlmb3khTceeedzabRqH3JFLP2IS+7tMlmO/KBIF0EhPS7la81MhIqF1lIJS3XZOGNxFPqOaXf+EsvvcQQepiUBsgHsyTJ9ltVa6SmOikpqfFrScAeffRRddIjcZOdEiVusjhK+lO/9dZbjJuHyfugvB9K4iU7H0qZgCTTmZmZqiZaNt6RDbC0Y09oJSDyvikJnHQDkbhJHa6cBEkiR94hG7M42thFyC6kWq9wKY+T/u8SN1mzIJspyaAEka9iDbWXyIe4JFuys5SWuEkyJnWD8hh5l+zOZttxQMiWuRr7kctFixapGkBJwOTDX0iSNmfOHJdlB9R2ysrK1LV8ONvHTiPbHdu6++671fNlhzb5YBeSpM2aNYsnQe3k/PPPV7M8stGO1NJq5PiRJEuOH9tkWsj7pMT7+eefV7slaqSTiyxkpI5JTlKlVERmj2SbcdtZ27fffturr43IXRyh9rLCwkK1bauQ9kP2HxzkHVJ+k5eX5/Tx4cOHO1z4JH2LZctq2T1s4MCBjdOd5Hm7du1SMwmunHfeeU12RdScOnVKxU1GRGWXTC5qa38Sg3379qnRadnMReLgKFa2SktL1bEqbfJkgXfv3r3b7fWSY+np6aqMY8KECSqOjkhdtQxayEyQLESUmQkiX8eEmoiIiIjIDVyUSERERETkBibURERERERuYEJNREREROQGJtRERERERG5gQk1ERERE5AYm1EREREREbmBCTURERETkBibURERERERuYEJNREREROQGJtRERERERG5gQk1ERERE5AYm1EREREREbmBCTURERESEv+//AZmdARDBmus5AAAAAElFTkSuQmCC" + } } ], "source": [ "# Get the cumulative counts of the names in the chapters of Little Women\n", "\n", - "counts = Table().with_columns([\n", - " 'Amy', np.cumsum(np.char.count(little_women_chapters, 'Amy')),\n", - " 'Beth', np.cumsum(np.char.count(little_women_chapters, 'Beth')),\n", - " 'Jo', np.cumsum(np.char.count(little_women_chapters, 'Jo')),\n", - " 'Meg', np.cumsum(np.char.count(little_women_chapters, 'Meg')),\n", - " 'Laurie', np.cumsum(np.char.count(little_women_chapters, 'Laurie')),\n", - "\n", - " ])\n", + "# POLARS_CHANGE: count_matches treats the pattern as a regular expression unless literal=True\n", + "little_women = pl.Series(\"chapter\", little_women_chapters)\n", + "counts = pl.DataFrame([\n", + " little_women.str.count_matches(\"Amy\", literal=True).cum_sum().alias(\"Amy\"),\n", + " little_women.str.count_matches(\"Beth\", literal=True).cum_sum().alias(\"Beth\"),\n", + " little_women.str.count_matches(\"Jo\", literal=True).cum_sum().alias(\"Jo\"),\n", + " little_women.str.count_matches(\"Meg\", literal=True).cum_sum().alias(\"Meg\"),\n", + " little_women.str.count_matches(\"Laurie\", literal=True).cum_sum().alias(\"Laurie\"),\n", + "])\n", "\n", "# Plot the cumulative counts.\n", "\n", - "cum_counts = counts.with_column('Chapter', np.arange(1, 48, 1))\n", - "cum_counts.plot(column_for_xticks=5)\n", - "plots.title('Cumulative Number of Times Each Name Appears', y=1.08);" + "cum_counts = counts.with_columns(pl.Series(\"Chapter\", range(1, 48)))\n", + "# POLARS_CHANGE: Polars does not plot, so each name is drawn against Chapter\n", + "for name in [\"Amy\", \"Beth\", \"Jo\", \"Meg\", \"Laurie\"]:\n", + " plots.plot(cum_counts.get_column(\"Chapter\"), cum_counts.get_column(name), label=name)\n", + "plots.legend()\n", + "plots.title(\"Cumulative Number of Times Each Name Appears\", y=1.08);" ] }, { From fc9fd3c6e3e2c6ae587549da3f16e3331a5ec7c2 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 02:55:30 -0700 Subject: [PATCH 11/17] Ch. 1.3.2 to polars - `np.char.count(chapters, '.')` counts periods. `count_matches('.')` without `literal=True` counts every character, because `.` matches any character in a regular expression. - `Table().with_columns([name, values, ...])` is again a DataFrame built from named Series. - `table.column(index)` is `DataFrame.to_series(index)`. The scatter still uses position 1 for the period counts and position 0 for the chapter lengths. POLARS_CHANGE: - Comment on `literal=True` for `'.'`: `count_matches` treats `'.'` as a regular expression unless `literal=True`. --- .../01/3/2/Another_Kind_Of_Character.ipynb | 223 +++++++----------- 1 file changed, 85 insertions(+), 138 deletions(-) diff --git a/chapters/01/3/2/Another_Kind_Of_Character.ipynb b/chapters/01/3/2/Another_Kind_Of_Character.ipynb index 7fce32338..0fdc1f823 100644 --- a/chapters/01/3/2/Another_Kind_Of_Character.ipynb +++ b/chapters/01/3/2/Another_Kind_Of_Character.ipynb @@ -19,8 +19,7 @@ }, "outputs": [], "source": [ - "from datascience import *\n", - "import numpy as np\n", + "import polars as pl\n", "path_data = '../../../../data/'\n", "import matplotlib\n", "matplotlib.use('Agg')\n", @@ -76,21 +75,24 @@ "# call this the \"length\" of the chapter.\n", "# Also count the number of periods.\n", "\n", - "chars_periods_huck_finn = Table().with_columns([\n", - " 'Huck Finn Chapter Length', [len(s) for s in huck_finn_chapters],\n", - " 'Number of Periods', np.char.count(huck_finn_chapters, '.')\n", - " ])\n", - "chars_periods_little_women = Table().with_columns([\n", - " 'Little Women Chapter Length', [len(s) for s in little_women_chapters],\n", - " 'Number of Periods', np.char.count(little_women_chapters, '.')\n", - " ])" + "# POLARS_CHANGE: count_matches treats '.' as a regular expression unless literal=True\n", + "huck_finn = pl.Series(\"chapter\", huck_finn_chapters)\n", + "chars_periods_huck_finn = pl.DataFrame([\n", + " pl.Series(\"Huck Finn Chapter Length\", [len(s) for s in huck_finn_chapters]),\n", + " huck_finn.str.count_matches(\".\", literal=True).alias(\"Number of Periods\"),\n", + "])\n", + "little_women = pl.Series(\"chapter\", little_women_chapters)\n", + "chars_periods_little_women = pl.DataFrame([\n", + " pl.Series(\"Little Women Chapter Length\", [len(s) for s in little_women_chapters]),\n", + " little_women.str.count_matches(\".\", literal=True).alias(\"Number of Periods\"),\n", + "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Here are the data for *Huckleberry Finn*. Each row of the table corresponds to one chapter of the novel and displays the number of characters as well as the number of periods in the chapter. Not surprisingly, chapters with fewer characters also tend to have fewer periods, in general: the shorter the chapter, the fewer sentences there tend to be, and vice versa. The relation is not entirely predictable, however, as sentences are of varying lengths and can involve other punctuation such as question marks. " + "Here are the data for *Huckleberry Finn*. Each row of the DataFrame corresponds to one chapter of the novel and displays the number of characters as well as the number of periods in the chapter. Not surprisingly, chapters with fewer characters also tend to have fewer periods, in general: the shorter the chapter, the fewer sentences there tend to be, and vice versa. The relation is not entirely predictable, however, as sentences are of varying lengths and can involve other punctuation such as question marks. " ] }, { @@ -99,67 +101,41 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 4, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Huck Finn Chapter Length Number of Periods
7026 66
11982 117
8529 72
6799 84
8166 91
14550 125
13218 127
22208 249
8081 71
7036 70
\n", - "

... (33 rows omitted)

" - ], "text/plain": [ - "Huck Finn Chapter Length | Number of Periods\n", - "7026 | 66\n", - "11982 | 117\n", - "8529 | 72\n", - "6799 | 84\n", - "8166 | 91\n", - "14550 | 125\n", - "13218 | 127\n", - "22208 | 249\n", - "8081 | 71\n", - "7036 | 70\n", - "... (33 rows omitted)" + "shape: (43, 2)\n", + "┌──────────────────────────┬───────────────────┐\n", + "│ Huck Finn Chapter Length ┆ Number of Periods │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ u32 │\n", + "╞══════════════════════════╪═══════════════════╡\n", + "│ 7026 ┆ 66 │\n", + "│ 11982 ┆ 117 │\n", + "│ 8529 ┆ 72 │\n", + "│ 6799 ┆ 84 │\n", + "│ 8166 ┆ 91 │\n", + "│ … ┆ … │\n", + "│ 10864 ┆ 96 │\n", + "│ 11534 ┆ 60 │\n", + "│ 13430 ┆ 77 │\n", + "│ 15754 ┆ 92 │\n", + "│ 21798 ┆ 228 │\n", + "└──────────────────────────┴───────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (43, 2)
Huck Finn Chapter LengthNumber of Periods
i64u32
702666
11982117
852972
679984
816691
……
1086496
1153460
1343077
1575492
21798228
" ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -179,67 +155,41 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 5, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Little Women Chapter Length Number of Periods
21759 189
22148 188
20558 231
25526 195
23395 255
14622 140
14431 131
22476 214
33767 337
18508 185
\n", - "

... (37 rows omitted)

" - ], "text/plain": [ - "Little Women Chapter Length | Number of Periods\n", - "21759 | 189\n", - "22148 | 188\n", - "20558 | 231\n", - "25526 | 195\n", - "23395 | 255\n", - "14622 | 140\n", - "14431 | 131\n", - "22476 | 214\n", - "33767 | 337\n", - "18508 | 185\n", - "... (37 rows omitted)" + "shape: (47, 2)\n", + "┌─────────────────────────────┬───────────────────┐\n", + "│ Little Women Chapter Length ┆ Number of Periods │\n", + "│ --- ┆ --- │\n", + "│ i64 ┆ u32 │\n", + "╞═════════════════════════════╪═══════════════════╡\n", + "│ 21759 ┆ 189 │\n", + "│ 22148 ┆ 188 │\n", + "│ 20558 ┆ 231 │\n", + "│ 25526 ┆ 195 │\n", + "│ 23395 ┆ 255 │\n", + "│ … ┆ … │\n", + "│ 33202 ┆ 305 │\n", + "│ 10289 ┆ 95 │\n", + "│ 12558 ┆ 96 │\n", + "│ 27094 ┆ 234 │\n", + "│ 40935 ┆ 392 │\n", + "└─────────────────────────────┴───────────────────┘" + ], + "text/html": [ + "
\n", + "shape: (47, 2)
Little Women Chapter LengthNumber of Periods
i64u32
21759189
22148188
20558231
25526195
23395255
……
33202305
1028995
1255896
27094234
40935392
" ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -261,23 +211,20 @@ "metadata": {}, "outputs": [ { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAcwAAAGTCAYAAAClAyKkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAABlbklEQVR4nO3de1xU1fr48c84KiiKIDdFLqIgKlGYhqZHSjEvR817ZKZleaPOSS3UTKI0UjOtLM0LespSyyOaQXlJf2qpqWiFlhqHvKDihUBAIEAc5veHX3aOMLjBGRiG5/16+Ur2XjPz7CXxsPZe61marKwsPUIIIYQoV53qDkAIIYSoCSRhCiGEECpIwhRCCCFUkIQphBBCqCAJUwghhFBBEqYQQgihgiRMIYQQQgVJmMKkkpOTqzsEqyV9a17Sv+ZjLX0rCVMIIYRQQRKmEEIIoYIkTCGEEEIFSZhCCCGECpIwhRBCCBUkYQohhBAqSMIUQgghVJCEKYQQQqggCVMIIYRQQRKmEEIIoULd6g5ACCFEzaW5mYJtTjR1dJcp1janoHEk+rre1R2WWUjCFEIIUSmamynYXRuMVnf21oEi0BYdJa/pFqtMmnJLVgghRKXY5kT/nSz/j1Z3Ftuc6GqKyLwkYQohhKiUOrrLRo5fqeJIqoYkTCGEEJVSrG1u5HizKo6kakjCFEIIUSkFjSPRaX0Mjum0PhQ0jqymiMxLJv0IIYSoFH1db/Kabvm/WbJXKNY2k1myQgghRFn0db3Jd4yp7jCqhMXckl20aBEODg5MmzZNOabX65k3bx5t27alWbNm9O/fn1OnThm8rrCwkGnTptGqVSvc3d158sknSU1NNWiTlZXFhAkT8PLywsvLiwkTJpCVlWXQ5sKFC4SFheHu7k6rVq2YPn06N27cMNv1CiGEqFksImEeOXKENWvWEBAQYHB88eLFLF26lHfeeYfdu3fj4uLCkCFDyMnJUdrMnDmT+Ph4Vq9ezdatW8nJySEsLAydTqe0GTduHMePH2fjxo3ExsZy/PhxJk6cqJzX6XSEhYWRm5vL1q1bWb16NXFxccyaNcv8Fy+EEKJGqPaEmZ2dzfjx4/noo49wcHBQjuv1epYtW8aUKVMYNGgQ7du3Z9myZeTm5hIbG6u89vPPP2fOnDn06NGDoKAgVqxYwYkTJ9i7dy8ASUlJ7Nq1iw8++IDOnTsTHBzM+++/z44dO0hOTgZg9+7dnDp1ihUrVhAUFESPHj2YPXs2n332GdevX6/qLhFCCGGBqj1hliTERx55xOB4SkoKV69epWfPnsqxBg0a0LVrVw4fPgxAYmIiRUVFBm08PDzw9/dX2iQkJNCoUSM6d+6stOnSpQt2dnYGbfz9/fHw8FDahIaGUlhYSGJiosmvWQghRM1TrZN+1qxZw5kzZ1ixYkWpc1evXgXAxcXF4LiLiwuXL99aLJuWloZWq8XJyalUm7S0NKWNk5MTGo1GOa/RaHB2djZoc+fnODk5odVqlTZlKRmhCkPSL+YjfWte0r/mUxP61s/Pr9zz1ZYwk5OTmTNnDtu2baN+/fpG292e6ODWrdo7j93pzjZltVfTprzjcPfOrY2Sk5OlX8xE+ta8pH/Nx1r6ttpuySYkJJCRkcHDDz+Mk5MTTk5OHDhwgFWrVuHk5ETTpk0BSo3w0tPTldGgq6srOp2OjIyMctukp6ej1+uV83q9noyMDIM2d35ORkYGOp2u1MhTCCFE7VRtCbN///78+OOP7Nu3T/nToUMHhg0bxr59+/D19cXNzY09e/YorykoKODgwYPK88igoCDq1atn0CY1NZWkpCSlTXBwMLm5uSQkJChtEhISyMvLM2iTlJRksBxlz5492NjYEBQUZM5uEEIIcY80N1NokDkeu/QBNMgcj+Zmilk+p9puyTo4OBjMigVo2LAhjo6OtG/fHoDw8HAWLVqEn58fvr6+LFy4EDs7O4YPHw5AkyZNGD16NFFRUbi4uODo6MisWbMICAjg0UcfBcDf359evXoxdepUFi9ejF6vZ+rUqfTp00e5RdCzZ0/atWvHpEmTiI6OJjMzk6ioKMaMGYO9vX2V9YkQQoiKqcotxiy60s/kyZPJz89n2rRpZGVl0bFjRzZv3kzjxo2VNnPnzkWr1TJ27FgKCgoICQlh+fLlaLVapU1MTAwzZsxg6NChAPTr148FCxYo57VaLRs2bCAiIoK+fftia2vL8OHDiY62zi1qhBDCWpS3xZipKxBpsrKy9HdvJoQ61vJw3xJJ35qX9K/5mLNv7dIHULdof6njN+t1J8853qSfVe3rMIUQQojKqsotxiRhCiGEqLGqcosxi36GKYQQQpSnKrcYk4QphBCiRquqLcbklqwQQgihgiRMIYQQQgVJmEIIIYQKqhJmUVERBw4c4PTp0+aORwghhLBIqhKmVqtl8ODB7N6929zxCCGEEBZJVcKsU6cOXl5e5ObmmjseIYQQwiKpfob5wgsv8Omnn/Lnn3+aMx4hhBDCIqleh5mbm4udnR0PPvgg/fv3p2XLljRo0MCgjUaj4aWXXjJ5kEIIIUR1U50w33zzTeXvGzZsKLONJEwhhBDWSnXCPHbsmDnjEEIIISya6oTp5eVlzjiEEEIIi1bhWrIXLlzgwIED/PnnnwwZMgQPDw9u3rxJZmYmjo6O1K0r5WmFEEJYnwplt9dee42VK1ei0+nQaDTcf//9eHh48Ndff/Hggw/y6quv8uKLL5orViGEEKLaqF5W8uGHH7Js2TJefPFFtmzZgl6vV87Z29vTv39/vvnmG7MEKYQQQlQ31QlzzZo1PPHEE8yePZvAwMBS5wMCAqR0nhBCCKulOmFevHiRrl27Gj3fuHFjsrOzTRKUEEIIYWlUJ8ymTZty5coVo+dPnDhB8+bNTRKUEEIIYWlUJ8zevXuzZs0aMjIySp07duwYa9eupX///iYNTgghhLAUqhPma6+9Rp06dejatStvvvkmGo2GdevW8dxzz/HYY4/h7u7OtGnTzBmrEEIIUW1UJ0w3Nzf27t1L3759iY+PR6/Xs3HjRnbt2kVYWBjfffcdDg4OZgxVCCGEqD4VWofp7OzM4sWLWbx4Menp6RQXF+Ps7EydOqrzrhBCCFEjqc50L774IkePHlW+dnZ2xtXVVUmWP/30kxQtEEIIYbVUJ8z169dz9uxZo+dTUlL44osvTBKUEEIIYWlMdi/12rVr2NjYmOrthBBCCItS7jPMAwcOsH//fuXr+Ph4zpw5U6pdVlYWmzdv5r777jN9hEIIIYQFKDdh7tu3j3feeQe4tTl0fHw88fHxZbb18/Nj3rx5po9QCCGEsADlJsx///vfPPfcc+j1etq2bcvChQsZOHCgQRuNRkPDhg2xs7Mza6BCCCFEdSo3YdrZ2SmJ8NixYzg7O9OwYcMqCUwIIYSwJKrXYXp5eQGQk5PDvn37uHDhAgCenp784x//wN7e3jwRCiGEEBagQoUL3n//fRYuXEh+fr7BfpgNGjTglVde4ZVXXjF5gEIIIYQlUJ0wFy9ezJw5c/jHP/7BuHHj8PX1Ra/Xc/r0aVatWsXbb79N3bp1mTx5sjnjFUIIIaqF6nWYMTEx9OjRg/j4eAYNGkRAQAD33XcfgwYNIi4ujpCQEGJiYlR/cExMDF27dsXT0xNPT08ee+wxduzYoZwPDw/HwcHB4E+vXr0M3qOwsJBp06bRqlUr3N3defLJJ0lNTTVok5WVxYQJE/Dy8sLLy4sJEyaQlZVl0ObChQuEhYXh7u5Oq1atmD59Ojdu3FB9LUIIIayf6oR57do1/vnPf5Z5TqPRMGDAAK5du6b6g93d3Zk9ezbff/89e/bsISQkhFGjRvHbb78pbR599FGSkpKUPxs3bjR4j5kzZxIfH8/q1avZunUrOTk5hIWFodPplDbjxo3j+PHjbNy4kdjYWI4fP87EiROV8zqdjrCwMHJzc9m6dSurV68mLi6OWbNmqb4WIYQQ1k/1LdkHHniA33//3ej5U6dOERQUpPqD79w78/XXX2f16tUcOXJEKYBgY2ODm5tbma/Pzs7m888/Z+nSpfTo0QOAFStWEBgYyN69ewkNDSUpKYldu3axfft2OnfuDNx6DtuvXz+Sk5Px8/Nj9+7dnDp1il9//RUPDw8AZs+ezUsvvcTrr78uk5mEEEIAFRhhvvvuu8THx7N48WJyc3OV47m5uXzwwQd8++23vPvuu5UKQqfTsWnTJvLy8ggODlaOHzx4EF9fXzp27MhLL73En3/+qZxLTEykqKiInj17Ksc8PDzw9/fn8OHDACQkJNCoUSMlWQJ06dIFOzs7gzb+/v5KsgQIDQ2lsLCQxMTESl2PEEII66N6hPn888+j0WiYPXs2b731Fq6urmg0Gq5evUpxcTFubm4899xzBq/RaDQcOnTI6HueOHGC3r17U1BQgJ2dHWvXriUgIACAXr16MXDgQLy9vTl//jzR0dE8/vjj7N27FxsbG9LS0tBqtTg5ORm8p4uLC2lpaQCkpaXh5OSERqMxiMnZ2dmgjYuLi8F7ODk5odVqlTbGJCcn36XXaifpF/ORvjUv6V/zqQl96+fnV+551QnT2dkZFxcXfH19DY77+PhULjJuBbdv3z6ys7OJi4sjPDycb775hvbt2zNs2DClXUBAAEFBQQQGBrJjxw4ef/xxo++p1+tLJcjKtCnv+O3xC0Mlt7qF6Unfmpf0r/lYS9+qTpjffvutyT+8fv36tGrVCoAOHTrw888/8/HHH7NkyZJSbZs3b467u7tS/N3V1RWdTkdGRgbOzs5Ku/T0dLp27aq0SU9PN0iQer2ejIwMZVTp6uqq3J4tkZGRgU6nKzXyFEIIUXuZbHsvUyguLja6nCMjI4PLly8rk4CCgoKoV68ee/bsUdqkpqaSlJSkPLMMDg4mNzeXhIQEpU1CQgJ5eXkGbZKSkgyWo+zZswcbG5sKTWISQghh3SpU6QegqKiI5ORksrOzKS4uLnW+W7duqt7nzTffpHfv3rRo0YLc3FxiY2PZv38///3vf8nNzWX+/Pk8/vjjuLm5cf78eebMmYOLiwsDBgwAoEmTJowePZqoqChcXFxwdHRk1qxZBAQE8OijjwLg7+9Pr169mDp1KosXL0av1zN16lT69Omj3B7o2bMn7dq1Y9KkSURHR5OZmUlUVBRjxoyRGbJCCCEUqhOmXq/n7bffZsWKFeTl5Rltp3Yt5tWrV5kwYQJpaWnY29sTEBBAbGwsoaGh5Ofnc/LkSb788kuys7Nxc3Oje/fufPLJJzRu3Fh5j7lz56LVahk7diwFBQWEhISwfPlytFqt0iYmJoYZM2YwdOhQAPr168eCBQuU81qtlg0bNhAREUHfvn2xtbVl+PDhREdHq+0aIYQQtYAmKytLf/dmt0rjvfnmm4wePZpu3boxadIkZs+eTZMmTVi5ciV169Zlzpw5PPLII+aOWVgwa3m4b4mkb81L+td8rKVvVT/D/PzzzxkwYAAffvghjz32GHCrmMEzzzzD7t270el07N+/32yBCiGEENVJdcK8cOGCUlGnTp1bLyuZoGNjY0NYWBhffPGFGUIUQgjrpbmZQoPM8dilD6BB5ng0N1OqOyRhhOpnmA4ODvz1118A2NvbU79+fYOZpTY2NhWqJSuEELWd5mYKdtcGo9WdvXWgCLRFR8lrugV9Xe/qDU6UonqE2a5dO44fP37rRXXq8OCDD7Jq1SpSU1O5cOECn376qVXcoxZCiKpimxP9d7L8P1rdWWxzZNKhJVKdMEeMGEFycjIFBQUAREVFcfr0aQIDA3nggQc4ffo0UVFRZgtUCCGsTR3dZSPHr1RxJEIN1bdkR40axahRo5SvH374YQ4ePMi2bdvQarWEhobSunVrswQphBDWqFjbHIrKOt6s6oMRd1XhwgW3a9myJeHh4aaKRQghqp3mZgq2OdHU0V2mWNucgsaRZnueWNA4Em3RUYPbsjqtDwWNI83yeeLeVCph5uXlkZmZiV5fegmnp6fnPQclhBDVoaon4ejrepPXdMv/JegrFGubmTVBi3ujOmHeuHGDBQsWsGbNGjIyMoy2k5myQoiaqrxJOPmOMWb5TH1db7O9tzAt1Qlz+vTpfPbZZ/Tr149u3brh4OBgxrCEEKLqySQcUR7VCXPLli089dRTZW69JYQQ1kAm4YjyqF5WUlxcTKdOncwZixBCVKuCxpHotD4Gx2QSjiihOmGGhoZy6NAhc8YihLBiNaEEXMkknBu2I7hZrzs3bEdI1R2hUH1LdsGCBQwZMoS5c+fy/PPPKxs5CyHE3dSkEnAyCUcYYzRhNmvWDI1GY3BMp9Nx8uRJFi5cSL169ZQi7CU0Gg2XLl0yT6RCiBqrOmafCmFqRhPmkCFDSiVMIYSoDJl9KqyB0YS5bNmyqoxDCGHFZPapsAaqJ/0IIURlyexTYQ1UJ8z333+fPn36GD3ft29fPvroI5MEJYSwLjL7VFgD1Qlz48aNPPTQQ0bPBwcH8+WXX5okKCGE9SmZfZrnHE++Y4wkS1HjqE6Y586dK3eD6NatW5OSYnnrqoQQQghTUJ0wbWxsuHy57JluAJcuXSq1zEQIIYSwFqozXHBwMJ9//jmZmZmlzmVmZrJu3To6d+5s0uCEEEIIS6G60s+rr76q7FQSHh5O+/bt0Wg0nDhxguXLl5Oens6nn35qxlCFEEKI6qM6YXbo0IENGzYwefJkoqKilKIGer2eli1bsmHDBinOLoQQwmqpTpgAjzzyCL/88gvHjh3j7Nmz6PV6WrVqxQMPPCBVgYQQQli1CiVMuFUvNigoiKCgIDOEI4QQt2hupmCbE00d3WWKtc0paBwpS1FEtapwwhRCCHOrSbubiNpD1oEIISxOebubCFFdJGEKISyO7G4iLJEkTCGExSnWNjdyXHY3EdVHEqYQwuLI7ibCEsmkHyGExSnZ3eTWLNkrFGubySxZUe0qlDA/++wz1qxZw7lz58oskafRaMjIyDBZcEKI2qtkdxMhLIXqhDlnzhw++OADAgICGDFiBA4ODmYMSwghhLAsqhPm2rVr+ec//8natWtN8sExMTF88sknXLhwAYC2bdsSERGhbFKt1+uZP38+a9asISsri44dO7Jw4ULatWunvEdhYSGRkZFs2rSJgoICQkJCWLRoES1atFDaZGVlMX36dLZv3w7c2uh6wYIFBgn/woULREREsG/fPmxtbRk+fDjR0dHUr1/fJNcqhBCi5lM96ScvL49evXqZ7IPd3d2ZPXs233//PXv27CEkJIRRo0bx22+/AbB48WKWLl3KO++8w+7du3FxcWHIkCHk5OQo7zFz5kzi4+NZvXo1W7duJScnh7CwMHQ6ndJm3LhxHD9+nI0bNxIbG8vx48eZOHGicl6n0xEWFkZubi5bt25l9erVxMXFMWvWLJNdqxBCiJpPdcLs0qULJ06cMNkH9+/fn8cee4xWrVrh6+vL66+/TqNGjThy5Ah6vZ5ly5YxZcoUBg0aRPv27Vm2bBm5ubnExsYCkJ2dzeeff86cOXPo0aMHQUFBrFixghMnTrB3714AkpKS2LVrFx988AGdO3cmODiY999/nx07dpCcnAzA7t27OXXqFCtWrCAoKIgePXowe/ZsPvvsM65fv26y6xVCCFGzqb4l++677zJ48GAeeOABRo0aZdJi6zqdji1btpCXl0dwcDApKSlcvXqVnj17Km0aNGhA165dOXz4MGPHjiUxMZGioiKDNh4eHvj7+3P48GFCQ0NJSEigUaNGBvt0dunSBTs7Ow4fPoyfnx8JCQn4+/vj4eGhtAkNDaWwsJDExERCQkKMxl2SdIUh6Rfzkb41L+lf86kJfevn51fuedUJc+TIkdy4cYOXXnqJ6dOn4+7ujlarNWij0Wg4dOiQ6uBOnDhB7969KSgowM7OjrVr1xIQEMDhw4cBcHFxMWjv4uLC5cu3KoCkpaWh1WpxcnIq1SYtLU1p4+TkZJDcNRoNzs7OBm3u/BwnJye0Wq3Sxpi7dW5tlJycLP1iJtK35iX9az7W0reqE6azszMuLi74+vqa7MP9/PzYt28f2dnZxMXFER4ezjfffKOcv3MUq9fr7zqyvbNNWe3VtCnvuBBCiNpHdcL89ttvTf7h9evXp1WrVsCtDap//vlnPv74YyIiIoBbo7/bb5Wmp6cro0FXV1d0Oh0ZGRk4OzsbtOnatavSJj093SBB6vV6MjIyDN6nZERbIiMjA51OV2rkKYQQovayqNJ4xcXF3LhxA29vb9zc3NizZ49yrqCggIMHDyrPI4OCgqhXr55Bm9TUVJKSkpQ2wcHB5ObmkpCQoLRJSEggLy/PoE1SUhKpqalKmz179mBjYyN7fgohhFAYHWGWrI/09PQ0+PpuStrfzZtvvknv3r1p0aKFMvt1//79/Pe//0Wj0RAeHs6iRYvw8/PD19eXhQsXYmdnx/DhwwFo0qQJo0ePJioqChcXFxwdHZk1axYBAQE8+uijAPj7+9OrVy+mTp3K4sWL0ev1TJ06lT59+ij303v27Em7du2YNGkS0dHRZGZmEhUVxZgxY7C3t1d1LUIIIayf0YR5//33o9FouHLlCvXr11e+vptr166p+uCrV68yYcIE0tLSsLe3JyAggNjYWEJDQwGYPHky+fn5TJs2TSlcsHnzZho3bqy8x9y5c9FqtYwdO1YpXLB8+XKDyUgxMTHMmDGDoUOHAtCvXz8WLFignNdqtWzYsIGIiAj69u1rULhACCGEKKHJysrSl3Vi3bp1aDQaRo4ciUajUb6+m6eeesrkQYqaw1pmw1ki6Vvzkv41H2vpW6MjzFGjRpX7tRBCCFGbWNSkHyGEEMJSScIUQgghVJCEKYQQQqggCVMIIYRQQRKmEEIIoYIkTCGEEEIF1Qnz1KlTxMXFGRz74YcfGDp0KD179mTp0qUmD04IIYSwFKqLr7/55psAPP744wBcvHiRp556ChsbG1xcXHj99ddxdHSUwgVCCCGskuoR5vHjx5VdQAD++9//UlxczL59+zh06BB9+vRh1apVZglSCCGEqG6qE+a1a9cMNmveuXMn3bt3x93dHYA+ffrwxx9/mD5CIYQQwgKoTpguLi6cP38egKysLI4ePUqPHj2U84WFhaaPTgghhLAQqp9h9ujRg5UrV2Jvb8/+/fsB+Oc//6mc//3332nRooXpIxRCWC3NzRRsc6Kpo7tMsbY5BY0j0df1ru6whCiT6oQZFRXFH3/8weuvv069evV488038fLyAm5t7rxlyxaeeOIJswUqhLAumpsp2F0bjFZ39taBItAWHSWv6RZJmsIiqU6YLi4ubNu2jevXr2Nra0v9+vWVc3q9nri4ODw8PMwSpBDC+tjmRP+dLP+PVncW25xo8h1jqikqIYxT9QwzPz+fgQMHsnbtWuzt7Q2SJUCDBg0IDAzE0dHRLEEKIaxPHd1lI8evVHEkQqijKmE2aNCAY8eOodPpzB2PEMJCaG6m0CBzPHbpA2iQOR7NzRSTvn+xtrmR481M+jlCmIrqWbL/+Mc/+PHHH80ZixDCQpQ8X6xfsJG6RfupX7ARu2uDTZo0CxpHotP6GBzTaX0oaBxpss8QwpRUJ8x33nmHn3/+mddff51z585RXFxszriEENWovOeLpqKv601e0y3csB3BzXrduWE7Qib8CIumetLPQw89hF6vZ+nSpSxdupQ6depQr149gzYajYZLly6ZPEghRNWqqueL+rreMsFH1BiqE+aQIUPQaDTmjEUIYSGKtc2hqKzj8nxR1F6qE+ayZcvMGYcQwoIUNI5EW3TU4LasPF8UtZ3qhCmEMB1Lr3BT8nzxVoxXKNY2s7gYhahqFdpA+vz587z00ksEBQXh6emplMjLyMjglVdeITEx0RwxCmFVqmIG6r0yTOiSLIWACowwk5KS6Nu3L8XFxXTq1Inz588r6zKdnJw4cuQIhYWFLFmyxGzBCmENLL3CjZSsE6JsqkeYb7zxBo0bN+bIkSOsXLkSvV5vcL53794cOnTI5AEKYW1MMQPVnEUFqmJJiRA1keoR5o8//khERASurq5cu3at1HlPT08uXy77B4EQ4m/3OgPV3CNAKVknRNlUjzBv3ryJnZ2d0fOZmZlotVqTBCWENbvXCjfmHgFKyTohyqY6YbZv3559+/aVeU6v1xMfH09QUJCp4hLCat1rhRtzjwALGzxLscbwl2NZUiJEBW7JhoeHM27cOBYsWMDQoUMBKC4u5n//+x/z5s3jl19+YcOGDWYLVAhrci8VbsxZVEBzM4WG1/9FHX2eckyPHX/ZL5EJP6LWU50whw0bxoULF3j77beZP3++cgxAq9USHR3NY489Zp4ohahF7rZG05xFBcq63ashD5v8T8m37XbP7y9ETVahwgVTpkxh+PDhxMXFcebMGYqLi/Hx8eHxxx/H21t++xTiXpU3oaeEOYsKyIQfIYxTnTAvXLiAs7MzHh4evPDCC6XO5+fnk56ejqenp0kDFKI2KX9Cz3TlmLmKlksNWSGMUz3p54EHHuCbb74xen7btm088MADJglKiNqqukd4skelEMapTph3Fiq4082bNyu0m8l7771Hjx498PT0pHXr1oSFhXHy5EmDNuHh4Tg4OBj86dWrl0GbwsJCpk2bRqtWrXB3d+fJJ58kNTXVoE1WVhYTJkzAy8sLLy8vJkyYQFZWlkGbCxcuEBYWhru7O61atWL69OncuHFD9fUIYQrVvaRD9qgUwrgK1ZI1lhCzs7PZtWsXLi4uqt9r//79PP/88+zYsYO4uDjq1q3L4MGDyczMNGj36KOPkpSUpPzZuHGjwfmZM2cSHx/P6tWr2bp1Kzk5OYSFhSll+wDGjRvH8ePH2bhxI7GxsRw/fpyJEycq53U6HWFhYeTm5rJ161ZWr15NXFwcs2bNUn09QpiCJYzwSm735jnHk+8YI8lSiP+jycrKMjp0nD9/PgsWLFD9ZhMnTmTevHmVCiQ3NxcvLy/WrVtHv379gFsjzGvXrhldrpKdnY2vry9Lly7liSeeAODixYsEBgYSGxtLaGgoSUlJdO7cme3bt9OlSxcADh48SL9+/Thy5Ah+fn7s3LmTJ554gl9//RUPDw8ANmzYwEsvvURycjL29vaVuqbaKDk5GT8/v+oOo0b7e5as4YQe6Vvzkv41H2vp23In/XTo0IFnn30WvV7Pp59+SkhICK1btzZoo9FoaNiwIR06dGDw4MGVDiQ3N5fi4mIcHBwMjh88eBBfX1+aNGlCt27deP3115WRbGJiIkVFRfTs2VNp7+Hhgb+/P4cPHyY0NJSEhAQaNWpE586dlTZdunTBzs6Ow4cP4+fnR0JCAv7+/kqyBAgNDaWwsJDExERCQkIqfV1CVJS5JvQIIe5NuQmzT58+9OnTB7j1rHDs2LE89NBDZgnk1VdfJTAwkODgYOVYr169GDhwIN7e3pw/f57o6Ggef/xx9u7di42NDWlpaWi1WpycnAzey8XFhbS0NADS0tJwcnIyuJ2s0WhwdnY2aHPn7WQnJye0Wq3SpizJycn3fN3WSPrFfKRvzUv613xqQt/ebRSselnJxx9/fM/BGPPaa69x6NAhtm/fblCPtqQwAkBAQABBQUEEBgayY8cOHn/8caPvp9frSyXIyrQp7zjcvXNrI2u59WKJpG/NS/rXfKylb1VP+nn//feV0WZZ+vXrx0cffVThAGbOnMmmTZuIi4ujZcuW5bZt3rw57u7unDlzBgBXV1d0Oh0ZGRkG7dLT05URo6urK+np6QazfPV6PRkZGQZt7hxJZmRkoNPpKjSRSQghhPVSnTA3btxY7u3Yhx56iC+//LJCHz5jxgxiY2OJi4ujTZs2d22fkZHB5cuXcXNzAyAoKIh69eqxZ88epU1qaqoy0QcgODiY3NxcEhISlDYJCQnk5eUZtElKSjJYjrJnzx5sbGykoLwQQgigAgnz3Llz5Q6pW7duTUqK+k1sIyIiWL9+PatWrcLBwYGrV69y9epVcnNzgVuTgCIjI0lISCAlJYV9+/bx5JNP4uLiwoABAwBo0qQJo0ePJioqir1793Ls2DEmTpxIQEAAjz76KAD+/v706tWLqVOncuTIERISEpg6dSp9+vRRrqdnz560a9eOSZMmcezYMfbu3UtUVBRjxoyRGbLinplzs2chRNVR/QzTxsam3A2iL126RJ066pd1rlq1CoBBgwYZHJ8xYwYzZ85Eq9Vy8uRJvvzyS7Kzs3Fzc6N79+588sknNG7cWGk/d+5ctFotY8eOpaCggJCQEJYvX27wLDQmJoYZM2You6z069fPYLmMVqtlw4YNRERE0LdvX2xtbRk+fDjR0bLDvLg35t7sWW0M5RVzF0KoU+46zNuFhYXx22+/sX//fhwdHQ3OZWZm0r17d9q1a1eqsICoXazl4b6pNMgcT/2C0v9P3LAdUeGlI3v3HmfdunQuX/6L5s0bEhnZCW/v8u+AlErY3CqEINV7SpPvXfOxlr5VPcJ89dVX6devH926dSM8PJz27duj0Wg4ceIEy5cvJz09nU8//dSMoQpR85iqNmxKynX+9a9jXLxYoBw7evRPtmzpV27SLK+Yu6z1FKJiVCfMDh06sGHDBiZPnkxUVJSy3EKv19OyZUs2bNhAp06dzBaoEDWRqXb/iI4+apAsAc6evU509FFiYnoaeVX1F3MXwppUaD/MRx55hF9++YVjx45x9uxZ9Ho9rVq14oEHHqhQ4XUhagtTbfZ8+fJfZR6/cqXs4yVkuy4hTKdCCRNuLeQPCgqS5RbCKpl6goypNntu3rxhmcebNSv7eAlTJeyqJhOVhCWqcMIsKioiOTmZ7OxsiouLS53v1q2bSQIToqqZa0arKWrDRkZ24uDBVIPbsj4+9kRGlv8YxFQJuypZwsxiIcqiOmHq9XrefvttVqxYQV5entF2165dM0lgQlQ1S54g4+1tz5IlD7BuXTpXrvxFs2bqZslC9Rdzr+ho0ZL/HUTtpjphfvjhhyxatIjRo0fTrVs3Jk2axOzZs2nSpAkrV66kbt26zJkzx5yxCmFWlj5BpkWLBuVO8LFElRktWvq/g6i9VFca+PzzzxkwYAAffvghjz32GAAPPPAAzzzzDLt370an07F//36zBSqEuRVrmxs5bn0TZKqq+lB5o0VjatO/g6hZVCfMCxcu0KNHj1sv+r+KPjdu3ABuVQEKCwvjiy++MEOIQlSNgsaR6LQ+BseqcoJMVSWxklFf/YKN1C3aT/2CjdhdG3xPn2cs9sqMFqv730EIY1TfknVwcOCvv25NYbe3t6d+/foGxcptbGzk+aWo0apzgkxVTnQx9TPC8mKvzLKWmjhRSdQOqhNmu3btOH78OHBrhPnggw+yatUqHnvsMYqLi/n000+tovSRqN2qa4JMVU50MfUzwvJir+yyluqeqCREWVQnzBEjRrBq1SoKCgqwtbUlKiqKoUOHEhgYCEC9evVYv3692QIVwppV5UQXUxczKC92GS0Ka6I6YY4aNYpRo0YpXz/88MMcPHiQbdu2odVqCQ0NpXXr1mYJUghrV5UVeUxdzOBusctoUVgLVQmzsLCQzZs306ZNGzp27Kgcb9myJeHh4WYLTojawpRJ7G7rHk096qup1YSEqChVCdPGxobJkyezYMECg4QphDANUyUxtZOHTDnqk9uuorZQfUvWz8+Pq1evmjMWIWo1UySx6qqSUxJ7SsqtHVQuX/6V5s1Pq65GJERNoDphTp8+nVdeeYUBAwYQEBBgzpiEqBXMUWC8OqvkpKRcZ/DgbZw9e105pmbPTiFqCtUJ84cffsDFxYWQkBCCg4Px8fGhQYMGBm00Gg0LFy40eZBCWBtzrbuszu28oqOPGiRLULdnpxA1heqE+Z///Ef5+6FDhzh06FCpNpIwhVDHXLdOq3MCTmX37BSiplCdMDMzM80ZhxC1itFbpzfP3dP7VnYCzt/PHv+ieXP1O6HcrrJ7dgpRU1R4P0whajpL2JzY2K3TOrqTaG6mVOn+m6Z69hgZ2YmjR/80eB81e3YKUVOoLr4uhDUwR+HxyihoHIkeu1LH6+jzyt3JwxzKe/ZYEd7e9mzZ0o8RI1rTvXtzRoxoLRN+hFWp0Ahzz549fPTRRyQmJpKdnY1ery/VRgqwC0tmKZsT6+t6o9O2pa7up1LnqnrfR1M+e/T2tpcJPsJqqR5hbtu2jeHDh3Pp0iWGDBlCcXExw4cPZ9iwYdja2nLfffcxffp0c8YqxD2zpM2Ji+u1Kvt4Fe/7KM8ehVBHdcJctGgRgYGB7N+/n9deew24VV82JiaGH3/8kUuXLkktWWHxLGlz4ors+6i5mYKPzetm2SszMrITPj6Gt03l2aMQpalOmCdOnGDEiBHUrVsXrVYLgE6nA27VlH3uued4//33zROlECZiSZsTl8xovWE7gpv1unPDdkSZ6zBLnrs61dtulueu8uxRCHVUP8O0sbFRChXY2dmh0Wj4888/lfMtWrTg7Nmzxl4uhEWwtLqnama0VsVzV3n2KMTdqU6YPj4+JCUlAbf2vvT39yc+Pp6wsDAAtm7dSrNmVX9bS4iKqmnbTVnSc1chajPVt2R79erFV199RVHRrcVj4eHhfPvttzz44IM8+OCDfPfddzz33HNmC1SI2sqSnrsKUZtpsrKySq8NKUNRURE5OTk4Ojqi0WgAiI2N5auvvkKr1dKvXz9Gjhxp1mCF5UtOTsbPz6+6w6h2piyOUKruLLeeu95r3VlhSL53zcda+lb1Ldl69erRtGlTg2PDhw9n+PDhJg9KiJrM1IXVS567Fl2aQZOGeWZ97moJVZCEsFRSGk8IEzPHJB19XW/OFr6Fn5f5fks31w4qQliLCiXMvXv3smbNGs6dO0dmZmapSj8ajYbExERTxidEjVNTJ+lYShUkISyV6oS5bNkyZs2ahbOzM506daJdu3bmjEuIGqs696S8FzU10QtRVVQnzKVLl9KtWzc2bdpE/fr1zRmTEDVade5JeS9qaqIXoqqoXlaSkZHB0KFDTZYs33vvPXr06IGnpyetW7cmLCyMkydPGrTR6/XMmzePtm3b0qxZM/r378+pU6cM2hQWFjJt2jRatWqFu7s7Tz75JKmpqQZtsrKymDBhAl5eXnh5eTFhwgSysrIM2ly4cIGwsDDc3d1p1aoV06dP58aNGya5VlG7qK3gY2ksqQqSEJZIdcIMCgri/PnzJvvg/fv38/zzz7Njxw7i4uKoW7cugwcPNtioevHixSxdupR33nmH3bt34+LiwpAhQ8jJyVHazJw5k/j4eFavXs3WrVvJyckhLCxMKdsHMG7cOI4fP87GjRuJjY3l+PHjTJw4UTmv0+kICwsjNzeXrVu3snr1auLi4pg1a5bJrlfULiXFEfKc48l3jLH4ZAk1N9ELUVVUr8P8+eefGTlyJDExMYSEhJg8kNzcXLy8vFi3bh39+vVDr9fTtm1bxo8fT0REBAD5+fn4+fnx1ltvMXbsWLKzs/H19WXp0qU88cQTAFy8eJHAwEBiY2MJDQ0lKSmJzp07s337drp06QLAwYMH6devH0eOHMHPz4+dO3fyxBNP8Ouvv+Lh4QHAhg0beOmll0hOTsbeXmpqqmUt660skfSteUn/mo+19K3RZ5gjRowodcze3p7BgwfTunVrPD09lSLsJTQaDf/9738rFUhubi7FxcU4ODgAkJKSwtWrV+nZ8+/6lg0aNKBr164cPnyYsWPHkpiYSFFRkUEbDw8P/P39OXz4MKGhoSQkJNCoUSM6d+6stOnSpQt2dnYcPnwYPz8/EhIS8Pf3V5IlQGhoKIWFhSQmJprlFwQhhBA1i9GE+fvvvysVfW7n4eFBYWEhf/zxR6lzZbVX69VXXyUwMJDg4GAArl69CoCLi4tBOxcXFy5fvjWbLy0tDa1Wi5OTU6k2aWlpShsnJyeD2DQaDc7OzgZt7vwcJycntFqt0qYsycnJlblUqyf9Yj7St+Yl/Ws+NaFv7zYKNpowf/31V5MHY8xrr73GoUOH2L59e5mj1tvp9fq7JuY725TVXk2b8o7D3Tu3NrKWWy+WSPrWvKR/zcda+lb1pB9zmTlzJps2bSIuLo6WLVsqx93c3ABKjfDS09OV0aCrqys6nY6MjIxy26SnpxsUWdDr9WRkZBi0ufNzMjIy0Ol0pUaeQgghaifVCXPr1q1MmzbN6Plp06axffv2Cn34jBkziI2NJS4ujjZt2hic8/b2xs3NjT179ijHCgoKOHjwoPI8MigoiHr16hm0SU1NVSb6AAQHB5Obm0tCQoLSJiEhgby8PIM2SUlJBstR9uzZg42NDUFBQRW6JiGEENZJdcL86KOP+Ouvv4yeLygoYPHixao/OCIigvXr17Nq1SocHBy4evUqV69eJTc3F7h1KzQ8PJwPPviAuLg4Tp48yQsvvICdnZ1S8L1JkyaMHj2aqKgo9u7dy7Fjx5g4cSIBAQE8+uijAPj7+9OrVy+mTp3KkSNHSEhIYOrUqfTp00e5RdCzZ0/atWvHpEmTOHbsGHv37iUqKooxY8bIDFkhLERKynXGj9/NgAHfMH78blJSrld3SKKWUV3p5+TJkwwdOtTo+QceeIBvvvlG9QevWrUKgEGDBhkcnzFjBjNnzgRg8uTJ5OfnM23aNLKysujYsSObN2+mcePGSvu5c+ei1WoZO3YsBQUFhISEsHz5coNnoTExMcyYMUOJv1+/fixYsEA5r9Vq2bBhAxEREfTt2xdbW1uGDx9OdHS06usR5pOScp3o6KNcvvwXzZs3JDKyE97e8otMbZKScp3Bg7dx9uzfSfLo0T/ZsqWffC+IKqM6Yd68eZP8/Hyj5/Pz8yksLFT9wXdW2imLRqNh5syZSgIti62tLe+++y7vvvuu0TaOjo6sXLmy3M/y9PRkw4YNd41JVC35QSkAoqOPGnwPAJw9e+sXqZiYnkZeJYRpqb4l2759e+Li4iguLi51rri4mLi4ONq2bWvS4IQo7welqD0uXy77cdCVK8YfEwlhaqoT5qRJk/jpp58YOXIkiYmJFBYWKgv7n3rqKX766SeDcnNCmIL8oBQAzZs3LPN4s2ZlHxfCHFTfkh02bBhnz55l3rx57Ny5E7h1y7RkPeOMGTMICwszW6CidqpJPyg1N1OwzYmmju4yxdrmFDSOlDqsJhIZ2YmjR/80uNvg42NPZGSnaoxK1DYV2kA6IiKC4cOHEx8fz7lz59Dr9fj4+DBw4ECDNZRCmEp1/qCsyGQjzc0U7K4N/ntLryLQFh0tVbxckmrleHvbs2VLP6Kjj3Llyl80ayaTv0TVU118XQg1zFHRoyRxVeUPyrImG/n42BudbNQgczz1CzaWOn7DdgT5jjFAGUmVW9tnqd0RxFqqpVgq6V/zsZa+rdAIU4iqUNbIrqpnQs6cebBCszLr6C6X+T51dFeUv9vmRBskSwCt7iy2OdFKUhVCWC5JmMKiWMIykpSU6/y//5da5jljk42Ktc2hqKzjzZS/q0mqQgjLVe21ZIW4nSUsI4mOPkphoa7Mc8YmGxU0jkSn9TE4ptP6UNA4Uvm6WNu8zNfenlSFEJZLEqawKJawjMRYDLa2WqOTjfR1vclruoUbtiO4Wa87N2xHlHo2qSapCiEsl9Fbsl988QVdu3bF21tm8ImqYwnLSIzF0KOHe7m3hfV1vUs9i7xzVuxf9kuwyf+UOrorFGubySxZIWoQoyPMF1980WCHj6ZNm7JxY+lZgEKYUmRkJ3x8DJNSVa+3MxbD/PldK/Q+JbNi6xdspG7RfuoXbKTh9X9R0DiSPOd48h1jJFkKUYMYHWHa29uTmZmpfH37fpJCmIslrLczVQwyK1YI62I0YXbq1IkFCxaQkpKibHEVHx/PmTNnjL6ZRqNh+vTppo9S1Cre3vbVXlDbFDHIrFghrIvRhLlw4UL+9a9/sWLFCnQ6HRqNhvj4eOLj442+mSRMYWmqs7KO0aUmmkZV8vlCCNMymjBbtmzJN998Q3FxMRkZGbRp04aFCxcycODAqoxP1DKmTHBqy9WZS0HjSLSFB9HqLxoc1978Fc3NFHl+KUQNc9fCBXXq1MHFxYUZM2bw8MMP4+rqWhVxiRquMps+mzrBGXuGqLvyBnU8Pq3w+1WUvq43uvr3oy28I2EWX5TnmELUQKor/bz66qvK37Ozs7l48dYPAQ8PD5o0aWL6yESNVdlqPaaeJGPsGeKpX0/RSHe9SiYS1Sm+XvZxeY4pRI1TocIFP//8M/369aNVq1Z0796d7t2706pVK/75z3/y888/mytGUcNUtlqPqSfJGKusc+ZCwyqrHGQshpwCpyr5fCGE6ageYf7000/079+fevXqMWbMGPz9/dHr9fzvf/8jNjaW/v378+233/Lggw+aM15RA1S2Wo+aeqwVUdA4krTz3+PhmqYc+yOlKZGL++DVqmoqBxU0jkSfn4CNJsUghrFvdGLpyqoZ5QohTEN1woyOjsbFxYXvvvuO5s0Nf2uePn06vXv3Jjo6ms2bN5s8SFGzVLRajzLR5+ZZijV21NHnKefupXScvq4389bO5mG/lbi7XOfSn/ZELu5DSqoTwV2rpnKQvq43L7//ahkx2Bjd+UQIYZlUJ8yjR4/y8ssvl0qWAM2bN+e5557jvffeM2lwomaqyKbPZe0RqccOnbYdxfV87nkZyMR/9Wfw4DrVsgF1ieOnGvNxzFOljldlfVwhxL1TnTD1ej1ardbo+Tp16kg1IAFUrFJOWRN9NORRXM/HJLNILaFykCXUxxVC3DvVCbNDhw58+umnjB49GkdHR4NzmZmZrFmzRp5fCoXaSjlVUQ2nuisHVWTELYSwXKoT5muvvcbgwYPp1KkTTz31FH5+fgD873//48svvyQnJ4ePP/7YbIEK62TqiT6WyBJGuUKIe6c6YT788MNs3ryZWbNmsWTJEoNzQUFBvP3223Tp0sXkAQrrVtA4Em3RUYPbsta4R2R1j3KFEPdOdcIE6NatG3v37iUtLY3z588D4OXlJdV/RKWVbLx8qxye7BEphLBcFUqYJVxdXSVJCpMpa+NlIYSwNBWq9COEEELUVpUaYYraqTIF1aF6t9gSQghTkYQpVKlsQfXq3mJLCCFMRW7JClUqW1C9vB1IhBCiJlGVMAsLC/niiy/46aefzB2PsFCVLaheFYUJhBCiKqhKmDY2NkyePJlff/3V3PEIC1XZ8m7GtreypsIEmpspNMgcj136ABpkjkdzM+XuLxJC1Diqb8n6+flx9epVc8YiLFhkZCd8fAyfVaop71bQOBKd1sfgmDUVJih5Rlu/YCN1i/ZTv2AjdtcGS9IUwgqpTpjTp08nJiaGEydOmDMeYaFKyruNGNGa7t2bM2JE67tO+IG/CxPcsB3BzXrduWE7wqom/MgzWiFqD9WzZH/44QdcXFwICQkhODgYHx8fGjRoYNBGo9GwcOFC1R9+4MABPvroI44dO8bly5dZunQpo0aNUs6Hh4fzxRdfGLymU6dO7Nq1S/m6sLCQyMhINm3aREFBASEhISxatIgWLVoobbKyspg+fTrbt28HoG/fvixYsAAHBwelzYULF4iIiGDfvn3Y2toyfPhwoqOjqV+/vurrsXaVLe9mzYUJ5BmtELWH6oT5n//8R/n7oUOHOHToUKk2FU2YeXl5tG/fnpEjRzJp0qQy2zz66KOsWLFC+frOBDZz5ky2bt3K6tWrcXR0ZNasWYSFhfH9998r25GNGzeOixcvsnHjRjQaDS+99BITJ05kw4YNAOh0OsLCwnB0dGTr1q1kZmYSHh6OXq/n3XffVX09orTKrt2sKWpD8XghxC2qE2ZmZqbJP7x379707t0bgBdeeKHMNjY2Nri5uZV5Ljs7m88//5ylS5fSo0cPAFasWEFgYCB79+4lNDSUpKQkdu3axfbt2+ncuTMA77//Pv369SM5ORk/Pz92797NqVOn+PXXX/Hw8ABg9uzZvPTSS7z++uvY21vPD/iqVNm1mzVJbSkeL4SoAYULDh48iK+vL02aNKFbt268/vrruLi4AJCYmEhRURE9e/59m9DDwwN/f38OHz5MaGgoCQkJNGrUSEmWAF26dMHOzo7Dhw/j5+dHQkIC/v7+SrIECA0NpbCwkMTEREJCQsqMLTk52UxXXbOV9Mvrr58sc+3mjBl7eOut9hV+39TUfJYvP8uffxbi4mLDpEk+tGjRwGyvU6u+5n1a1F9OPc2fFOldSM2bxI3sG4Dpvz/ke868pH/Npyb0bcm2lcZUOGEeOnSIH374gT///JOJEyfi6+tLXl4ev//+O35+fiYdjfXq1YuBAwfi7e3N+fPniY6O5vHHH2fv3r3Y2NiQlpaGVqvFycnJ4HUuLi6kpaUBkJaWhpOTExqNRjmv0WhwdnY2aFOShEs4OTmh1WqVNmW5W+fWRiWjdoDc3KQy2+TlaVX3Xckt3TNnrvP775nk5d1UziUlFZQ5Wr29FF9OgTNT53Vi/2Gbu76u8vyAR9Fz638oc01nur1vhelJ/5qPtfSt6oR548YNnnvuObZu3Yper0ej0TBgwAB8fX3RarUMHz6cF198kYiICJMFN2zYMOXvAQEBBAUFERgYyI4dO3j88ceNvq4kvhK3/70ibco7Lu6usms3S5R1SxfAu0UG0ZN34O56nexTa9G0WKLMur2zFJ+jFj6Z/QO9np9ASuqtX6xKKhRVdn9Ka38uK4Qom+plJfPmzWPHjh28++67HDlyBL1er5yztbVl8ODBbNu2zSxBlmjevDnu7u6cOXMGuLXNmE6nIyMjw6Bdenq6MmJ0dXUlPT3dIF69Xk9GRoZBmztHkhkZGeh0ulIjT6FeZdduliirHJ93iwx2rV7J0wN/oWfn03R/YJ/Buseylnn4el8jevIOg2N3q1BkTEkS37jxNPv3X2bjxtMMHryNlJTrd3+xEKJGU50wN27cyLPPPsvzzz9P06ZNS5338/Pj3LlzpoytlIyMDC5fvqxMAgoKCqJevXrs2bNHaZOamkpSUpLyzDI4OJjc3FwSEhKUNgkJCeTl5Rm0SUpKIjU1VWmzZ88ebGxsCAoKMus1WbPKrt0sUVY5vujJO/D1vmZw7PZ1j8aWefTqksz/+3Q5ny9Yj3eLDNWj3FKfX8maukKImk/1Ldk///yTwMBAo+dtbGzIy8ur0Ifn5uYqo8Xi4mIuXrzI8ePHcXR0xNHRkfnz5/P444/j5ubG+fPnmTNnDi4uLgwYMACAJk2aMHr0aKKionBxcVGWlQQEBPDoo48C4O/vT69evZg6dSqLFy9Gr9czdepU+vTpo9xT79mzJ+3atWPSpElER0eTmZlJVFQUY8aMkRmy96iyazeh7Fu67q5lj+RK1j0aW+bRzCWXZi65APyj40XynQdUKqbK1tQVQtR8qkeYbm5u5Y4gf/rpJ7y9Kzbd4ZdffiEkJISQkBDy8/OZN28eISEhzJ07F61Wy8mTJ3nqqafo1KkT4eHh+Pr68t1339G4cWPlPebOncuAAQMYO3Ysffv2xc7Oji+//FJZgwkQExPDfffdx9ChQxk2bBj33XefwdpOrVbLhg0baNiwIX379mXs2LEMGDCA6Gip1lKdyrqlm3atSZltS9Y9llWK704t3f+ktf3iSsV0r89lhRA1lyYrK0t/92YQGRnJunXr2LlzJ02bNqV169Z8/fXXhISEsG3bNsaMGUNERAQzZswwd8zCgpl6NlzJBJsrV/6iWbOGzI50pU2D0aXWPd5ebu/vWbJXqHPzd+ro/yz1vjfrdSfPOV75Wu0m12VNRPLxsa+StaXWMtPQUkn/mo+19K3qhJmTk0P//v05ffo0nTt3Zu/evYSEhJCbm8vPP/9Mx44diY+Px9bW1twxCwtWFf9j3J4Qi7XNjCY3gAaZ46lfsLHU8Ru2I5RyfaU2uaZ0Er7dnUm8qmbJWssPHUsl/Ws+1tK3qhMmQEFBAUuXLmXLli2cPn2a4uJifHx8GDp0KP/+978lWYp7+h9D7SjvTuUt81CTDNUkVUtgLT90LJX0r/lYS99WqHCBra0tr7zyCq+88oq54hE10O0Jq1EjHe+841bhEVepxFYE2qKjd93Z5G7l90p2SylvRCoF1IUQalSqNF52djYXL14EbpWia9Kk7IkYwnoYG/2VlbCSkrapeqZ3e6Kd+68VdH+g7G2yyhvllbfMo2R27t12S5EC6kIINSqUMA8ePMjs2bMN1jTCrXWMUVFRdO3a1aTBCfOoaKWa8kZ/0dGn75qwjMVwe6ItGnepzHZ3G+WZYpmHFFAXQqihOmF+9913jBo1ikaNGvH888/j6+uLXq/n9OnTxMbGMmjQINatW6fsPiIsU2V2EClvk+TLlweV+Zq7Jaw7R4aX0sr+7LuN8kyxzEPNbVshhFCdMGfPno2Pjw87duzA0dHR4NzMmTPp3bs3s2fPloRp4dTcwrxTec/4Kpuw7hwZRi7uQ5f7Uwyq+JSM8sobEUdGduLo0T9LLfNQW36vhDVvci2EMA3VhQtOnz7NM888UypZAjRt2pRnnnmG06dPmzQ4YXoVuYWZknKd8eN3s3tfcZmvKdY2q3S92DsTbUqqE72en8C+Y925Wa87N2xHkNd0C+dSHcut3Xqv5feEEEIt1SPMli1bllv6Li8vr8KVfkTVUzsivP3WbcKPIexa/XuZoz9vx1sJq2Rdop2djnfe6XHXhFXWyLBOfR+atHuBPOe/XxsdvfuuI+J7Kb8nhBBqqU6YM2bM4JVXXqFnz5506mQ4ejhy5AgxMTEsWrTI5AEK01J7C/P2W7clo7/oyTt4IKAI//btDJ7x3Z6wkpOTVY3uSkaGdysAILVbhRCWwmjCLGutZbNmzejduzcdOnSgdevWwK1btb/88gvt2rVj//79DB482GzBintX2USVkurE6OlP0b17c+LjK1e4vKxY7jYyLG9ELPtSCiGqktGE+Z///Mfoi37++Wd+/vlng2MnT57k1KlTLFy40HTRCbO410RVlYyNiJ99tm2FZ/sKIcS9MJowMzMzqzIOYWHuduu2smXsKsrYiLgys32FEOJeVKrSj7B+5d26La+QgbliuTMJyrNNIURVq3TCLCoqQq8vXbe9fv369xSQsBzGbt2WV8gApldJbJZyy1gIUXuoTpjFxcWsXLmSzz//nHPnzpGfn1+qjUajISMjw6QBCstjCcXKTVWwQAgh1KrQspLVq1fTpk0bBg8ejL29TKyorYwVKz94FE5mZbJgwW6zz1xVO9tXCCFMRXXC3LBhA4MGDeKTTz4xZzyiBiirWPkfKU0Z/Uo3Ll45hk73d9u7zVy9l6UhUrBACFGVVCfMevXqERISYs5YRA1RUqz82K5/UZR/iUt/2hO5uA8pqU6l2pY3c7UyheCFEKK6qE6YAwcO5Pvvv2fs2LHmjEdYoLJHgd68tmQi+/eX/TzzdsZmrsrSECFETaI6Yc6dO5dnn32W8PBwnn76aVq0aIFWqy3VztPT06QBiupV3ijQ2EzVOxmbuSpLQ4QQNYnqhFm3bl1atmzJqlWr2LBhg9F2165dM3pOmFZVlIYrbxRY1kxVrRaDZ5jlzVyVpSFCiJpEdcJ8+eWXWb9+Pf/4xz/o1KmTzJKtZikp13lxwmdMHLYJd9frXEqz58UJw1i6coxJk2Z5o8DbZ6pSdI5Jwzdh3yCdcxcbM29Vf5p5tmfevIeNxiNLQ4QQNYnqhBkXF8eoUaP46KOPzBmPUGnFkm/5ZPZ7Bltudbk/hfeXODH33ZEm+5y7jQK9ve1Ztaw1NmlTsdGkANCpPQT5n2HsGy8DDxt9b1kaIoSoSVQnTBsbG4KCgswYiqiIQV0/N0iWAL7e1xjU9XPAdAlTzSjQNiea+v+XLG+PZeKwTURHty93Ao8sDRFC1BR11DYcMWIEW7duNWcsogLcXa+Xeby5keOVVTIKHDGiNd27N2fEiNalln0Yq/zj7nJdJvAIIayG6hFm//792b9/P8OGDWPUqFF4eHiUOUu2Y8eOJg1QlK2Fty/wW6njHt6+Jv+su40CjVX+ufSnvUzgEUJYDdUJc8CAvzcN3rNnT6nzer0ejUYjs2SriLbZbArTflGeGwIU6r3RNptN6ZL4pnf7DN372/VkbvhBmjS4qJz/I6Upby7py4fL2lZBNEIIYX6qE+bSpUvNGYeoIH1dbwpd49DkRFNHd4VibTMKTbAnpZqlKneuzdy/H/bseYbXJmzF3eX6bZV/mvLpp7/TrZv7PcUkhBCWQHXCfOqpp8wZh6gEfV1v8h1jTPZ+akvVlbU289QfDoyeXvp7RJ5hCiGshepJP8L6lVek4HbG1maWRZ5hCiGsheoR5osvvnjXNhqNhiVLltxTQMJ0KloJSG2pOmNrM+3s6pKXd1P5WooQCCGsieqE+cMPP6DRaAyOFRcXc+XKFXQ6Hc7OzjRsKKMJS1GZnUDUlqqbHenKU4/Ox94ug0tpt55X1qnvw5Il3fnooyPk5WmlCIEQwuqoTpi//vprmcdv3LjB6tWrWblyJVu2bDFVXOIeVWYnkGefbcvWrSnljhI1N1No02A07Xr+vRdmr66XyGy8CXdvd1xd2+Pn52fiqxFCiOp3z88w69evT3h4OCEhIcyYMaNCrz1w4ABPPvkk7dq1w8HBgXXr1hmc1+v1zJs3j7Zt29KsWTP69+/PqVOnDNoUFhYybdo0WrVqhbu7O08++SSpqakGbbKyspgwYQJeXl54eXkxYcIEsrKyDNpcuHCBsLAw3N3dadWqFdOnT+fGjRsVuh5LUtGdQFJSrvOvf+0zSJZ2dnVZsqS7wSjRNifaYONogGZOV2ltv9gEUQshhOUy2aSfDh06sH///gq9Ji8vj/bt2zN//nwaNGhQ6vzixYtZunQp77zzDrt378bFxYUhQ4aQk5OjtJk5cybx8fGsXr2arVu3kpOTQ1hYGLrbtswYN24cx48fZ+PGjcTGxnL8+HEmTpyonNfpdISFhZGbm8vWrVtZvXo1cXFxzJo1qxI9YRkquhNIWSPSvLybfPrp7wbHjFX1qaO7UokohRCi5jBZwjxy5Aj169ev0Gt69+5NVFQUgwYNok4dw1D0ej3Lli1jypQpDBo0iPbt27Ns2TJyc3OJjY0FIDs7m88//5w5c+bQo0cPgoKCWLFiBSdOnGDv3r0AJCUlsWvXLj744AM6d+5McHAw77//Pjt27CA5ORmA3bt3c+rUKVasWEFQUBA9evRg9uzZfPbZZ1y/btpSc1UlMrITPj6Gzw/Lm4SjdkRarG1eZrtibbNKRCmEEDWH6meYX3zxRZnHs7Oz2bdvH1u3buX55583WWApKSlcvXqVnj3/ft7WoEEDunbtyuHDhxk7diyJiYkUFRUZtPHw8MDf35/Dhw8TGhpKQkICjRo1onPnzkqbLl26YGdnx+HDh/Hz8yMhIQF/f388PDyUNqGhoRQWFpKYmEhISIjJrquqVHQnELUj0oLGkWiLjhrcltVpfShoHGm64IUQwgKpTpgvvPCC0XPOzs5EREQQERFhkqAArl69CoCLi4vBcRcXFy5fvnVbMC0tDa1Wi5OTU6k2aWlpShsnJyeDGb4ajQZnZ2eDNnd+jpOTE1qtVmlTlpIRqiWbPt1T+fuNG1dJTr5aZrtRo5w5eDCVixcLlGMeHraMGuVc6jrra96nRf3l1NP8SZHehdS8SdzIvgHcalcT+qWmkr41L+lf86kJfXu3CYuqE+axY8dKHdNoNDg6OtKoUaOKR6bSnUtZSmrWlufONmW1V9OmvONw986tSfz84NtvW6ockfoBj6Ln1jfQ7cX4kpOTrapfLIn0rXlJ/5qPtfSt6oTp5eVlzjhKcXNzA26N/m6/VZqenq6MBl1dXdHpdGRkZODs7GzQpmvXrkqb9PR0gwSp1+vJyMgweJ/Dhw8bfH5GRgY6na7UyNOayd6UQghhnMWWxvP29sbNzc1gZ5SCggIOHjyoPI8MCgqiXr16Bm1SU1NJSkpS2gQHB5Obm0tCQoLSJiEhgby8PIM2SUlJBstR9uzZI5tmCyGEUJQ7wnzggQcq9GYajYbExETV7XNzczlz5gxwq2rQxYsXOX78OI6Ojnh6ehIeHs6iRYvw8/PD19eXhQsXYmdnx/DhwwFo0qQJo0ePJioqChcXFxwdHZk1axYBAQE8+uijAPj7+9OrVy+mTp3K4sWL0ev1TJ06lT59+ii3CHr27Em7du2YNGkS0dHRZGZmEhUVxZgxY7C3l0o1Qggh7pIwfX197/q8EG6N6n7//XdVbW/3yy+/MHDgQOXrefPmMW/ePEaOHMmyZcuYPHky+fn5TJs2jaysLDp27MjmzZtp3Lix8pq5c+ei1WoZO3YsBQUFhISEsHz5coPNrWNiYpgxYwZDhw4FoF+/fixYsEA5r9Vq2bBhAxEREfTt2xdbW1uGDx9OdHR0ha5HCCGE9dJkZWVVer/h1NRU3nvvPdauXQvAqFGjeO+990wWnKh5rOXhviWSvjUv6V/zsZa+VT3p53aXLl1SEqVer+epp57ilVdeMZicI4QQQliTCiVMSZRCCCFqK1UJUxKlEEKI2q7chCmJ0jpUdCNpIYQQpZWbMDt06EBRURGBgYG8/PLLeHh4cPXqVaVsXVk6duxo8iBF5VVmI2khhBCllZswS/aDPH78OGPHji33jUoq6Vy7ds100Yl7VpmNpIUQQpRWbsJcunRpVcUhzKSiG0kLIYQoW7kJ86mnnqqqOISZNG5c9j+xsY2kjZHnoEKI2q5S6zBFzZCScp1ffy19i9zDw87oRtLG3keegwohajuLLb4u7l109FEuXswrdfz++50qlOjKew4qhBC1hSRMK2bs+WVOTpFJ3keegwohahNJmFasefOyn1NW9Pmlqd5HCCFqMkmYViwyshM+Poa3Xn187Cv8/DIvrwgbG63B8Yq+jxBC1HQy6ceKeXvbs2VLP6Kjj3Llyl80a1ax2a1lTfaxtdXSo4c78+d3lQk/QohaRRKmlfP2tq90gYKyJvsUFOho1Ki+JEshRK0jt2SFUTLZRwgh/iYJUxglk32EEOJvckvWytxekadx47poNBquXy+qVHWeyMhOHD36p8FtWZnsI4SorSRhWpGyJuncrqLVee510pAQQlgTSZhWpKxJOrdTs0tJWTVjZVcTIYSQhGlVjE3SuV15E3akZqwQQhgnk36siLFJOrcrb8KO1IwVQgjjJGFakbIq+9zubhN2ZBmJEEIYJ7dkrcidk3QaNbo1SzYnp0jVhB1ZRiKEEMZJwrQy91LZR5aRCCGEcZIwq1hZs1AtZUKNLCMRQgjjJGFWoZowC/VeRqhCCGHNZNJPFZJZqEIIUXNJwqxCMgtVCCFqLkmYVUhmoQohRM0lCbMKlbVOUmahCiFEzSCTfqqQzEIVQoiaSxJmFZNZqEIIUTPJLVkhhBBCBUmYQgghhAoWnTDnzZuHg4ODwZ82bdoo5/V6PfPmzaNt27Y0a9aM/v37c+rUKYP3KCwsZNq0abRq1Qp3d3eefPJJUlNTDdpkZWUxYcIEvLy88PLyYsKECWRlZVXFJQohhKghLDphAvj5+ZGUlKT8+fHHH5VzixcvZunSpbzzzjvs3r0bFxcXhgwZQk5OjtJm5syZxMfHs3r1arZu3UpOTg5hYWHodDqlzbhx4zh+/DgbN24kNjaW48ePM3HixCq9TiGEEJbN4if91K1bFzc3t1LH9Xo9y5YtY8qUKQwaNAiAZcuW4efnR2xsLGPHjiU7O5vPP/+cpUuX0qNHDwBWrFhBYGAge/fuJTQ0lKSkJHbt2sX27dvp3LkzAO+//z79+vUjOTkZPz+/qrtYIYQQFsviR5jnzp2jXbt23H///Tz33HOcO3cOgJSUFK5evUrPnn/POG3QoAFdu3bl8OHDACQmJlJUVGTQxsPDA39/f6VNQkICjRo1UpIlQJcuXbCzs1PaCCGEEBY9wuzUqRMff/wxfn5+pKen8+6779K7d28OHTrE1atXAXBxcTF4jYuLC5cvXwYgLS0NrVaLk5NTqTZpaWlKGycnJzQajXJeo9Hg7OystDEmOTn5nq/RGkm/mI/0rXlJ/5pPTejbu91RtOiE+dhjjxl83alTJ4KCgli/fj0PPfQQgEGig1u3au88dqc725TVXs37yO3a0uQ2tvlI35qX9K/5WEvfWvwt2ds1atSItm3bcubMGeW55p2jwPT0dGXU6erqik6nIyMjo9w26enp6PV65bxerycjI6PU6FUIIUTtVaMSZkFBAcnJybi5ueHt7Y2bmxt79uwxOH/w4EHleWRQUBD16tUzaJOamkpSUpLSJjg4mNzcXBISEpQ2CQkJ5OXlGTzXFEIIUbtpsrKy9HdvVj0iIyPp27cvHh4eyjPMH3/8kQMHDuDl5cUHH3zAokWLWLp0Kb6+vixcuJAff/yRI0eO0LhxYwBefvlltm3bxrJly3B0dGTWrFlkZWXx/fffo9VqARg+fDiXLl1i8eLF6PV6pkyZgqenJxs2bKjOyxdCCGFBLPoZ5qVLlxg3bhwZGRk4OzvTqVMndu7ciZeXFwCTJ08mPz+fadOmkZWVRceOHdm8ebOSLAHmzp2LVqtl7NixFBQUEBISwvLly5VkCRATE8OMGTMYOnQoAP369WPBggVVe7FCCCEsmkWPMIUQQghLUaOeYQohhBDVRRKmEEIIoYIkTCGEEEIFSZhCCCGECpIwRbkOHDjAk08+Sbt27XBwcGDdunUG5021xVpt9N5779GjRw88PT1p3bo1YWFhnDx50qCN9G/lxcTE0LVrVzw9PfH09OSxxx5jx44dynnpW9NZtGgRDg4OTJs2TTlmjf0rCVOUKy8vj/bt2zN//nwaNGhQ6ryptlirjfbv38/zzz/Pjh07iIuLo27dugwePJjMzEyljfRv5bm7uzN79my+//579uzZQ0hICKNGjeK3334DpG9N5ciRI6xZs4aAgACD49bYv7KsRKjWokULFixYwKhRo4Bbv0G2bduW8ePHExERAUB+fj5+fn689dZbyhZrvr6+LF26lCeeeAKAixcvEhgYSGxsLKGhodV2PZYmNzcXLy8v1q1bR79+/aR/zaBly5a88cYbPPvss9K3JpCdnc0jjzzC4sWLWbBgAe3bt+fdd9+12u9dGWGKSjPVFmviltzcXIqLi3FwcACkf01Jp9OxadMm8vLyCA4Olr41kZL9iB955BGD49bavxZd6UdYNlNtsSZuefXVVwkMDCQ4OBiQ/jWFEydO0Lt3bwoKCrCzs2Pt2rUEBAQoP5ClbytvzZo1nDlzhhUrVpQ6Z63fu5IwxT0zxRZrtd1rr73GoUOH2L59u0HZRpD+vRd+fn7s27eP7Oxs4uLiCA8P55tvvlHOS99WTnJyMnPmzGHbtm3Ur1/faDtr61+5JSsqzVRbrNV2M2fOZNOmTcTFxdGyZUvluPTvvatfvz6tWrWiQ4cOvPHGGwQGBvLxxx9L396jhIQEMjIyePjhh3FycsLJyYkDBw6watUqnJycaNq0KWB9/SsJU1SaqbZYq81mzJhBbGwscXFxtGnTxuCc9K/pFRcXc+PGDenbe9S/f39+/PFH9u3bp/zp0KEDw4YNY9++ffj6+lpl/8otWVGu3Nxczpw5A9z6YXPx4kWOHz+Oo6Mjnp6ehIeHs2jRIvz8/JQt1uzs7Bg+fDgATZo0YfTo0URFReHi4qJssRYQEMCjjz5ajVdW/SIiItiwYQNr167FwcFBee5jZ2dHo0aN0Gg00r/34M0336R37960aNGC3NxcYmNj2b9/P//973+lb++Rg4ODMjmtRMOGDXF0dKR9+/YAVtm/kjBFuX755RcGDhyofD1v3jzmzZvHyJEjWbZsmcm2WKuNVq1aBcCgQYMMjs+YMYOZM2cCptvCrja6evUqEyZMIC0tDXt7ewICAgyWK0jfmpc19q+swxRCCCFUkGeYQgghhAqSMIUQQggVJGEKIYQQKkjCFEIIIVSQhCmEEEKoIAlTCCGEUEESprBKDg4OTJ06tbrDUO3s2bMMHz4cb2/vMjfqrk6BgYGEh4db5HumpKRUS3+tW7cOBwcHjhw5UqWfK6qXJExRKSU/MFxdXbl48WKp88OGDSMwMLAaIquZ/v3vf/Pzzz/z6quvsmLFCrp161bdIQkLtnLlSov6paq2kEo/4p7cuHGD9957j/fee6+6Q6mxdDodBw8eZPz48SYfyZnC0aNHqVPHMn+39vLy4sqVK9SrV6+6Q6lSMTExuLq6Kpu5i6phmf8XiBojMDCQtWvXljnKtHZ6vZ6CgoJ7fp9r166h0+lo0qSJCaIyjduvzcbGxmITkkajwdbW1mJLqdU0+fn51R2CRZOEKe7Jyy+/DHDXEWZ5z5rufJ5Vcrt3//79vPbaa/j6+uLl5cWLL75IQUEBeXl5TJkyhVatWuHl5UVERAQ3b94s83M3b95M586dcXNzo2vXruzYsaNUm+vXrxMZGUlgYCCurq7cd999vPnmmxQWFhq0K3kuumXLFrp27YqrqyubNm0q97oPHjzIwIEDadGiBR4eHgwePJijR48q5+fNm4efnx8A77zzTplFre9UEkdVXVtZzxszMzN5+eWX8ff3x9XVleDgYJYsWYJeb1hp88aNG7zxxhu0adMGd3d3Bg0axP/+979Scd68eZN3332Xjh070qxZM1q1akXv3r35+uuvy+2Lsr6v5s2bh4ODA6dPn2bq1Kn4+PjQokULnnnmGa5du1bu+5W4cuUKU6ZMoX379ri6uhIYGMhLL71ETk6OQbuioiLmzJmDv78/zZo1Y8iQIZw7d86gzY8//sizzz7Lfffdh6urK23btmXKlClkZWUZtCuJ+/fff2f8+PF4eXnh7e3Nv//9b65fv660CwwMJDk5mQMHDijfL7c//rhx4wYLFiygU6dOuLq60qZNG6ZOnVrq8wIDAxk2bBg//PADvXr1ws3NjQ8++EBV/9RWcktW3BMPDw+eeuop1q5dy8svv4yHh4fJ3nvmzJk4OzszY8YMEhMTWbduHQ0bNuTcuXM0aNCAWbNm8cMPP7Bq1SpatWrFCy+8YPD6w4cP89VXXzFx4kQaNWrEmjVrGDVqFF9//bXyjDA/P58BAwaQkpLCs88+i4+PD7/++itLlizhf//7H+vXrzd4z4MHD/L1118zfvx43NzcSm3JdbsDBw4wZMgQ3N3diYiIoLi4mE8++YT+/fvz7bff0qlTJwYOHIizszPTpk1jwIABBoXuy1Od11ZYWMjAgQM5deoUzz33HG3atOG7774jMjKS1NRU5s2bp7SdMmUK69evZ9CgQXTv3p2ff/6ZIUOGlBqZz58/n0WLFjF69Gg6duxIXl4ex48f5+jRo6WK06v1/PPP4+bmxqxZszh9+jQrV66kXr16StF7Y65evUpoaCjp6emMGTOG9u3bc+XKFb755huuXbtmUDz8tddeo0GDBkydOpWMjAyWLFnChAkT+O6775Q2X331FZmZmYwZMwY3Nzd+++03PvvsM06dOlXmLznPPfcc7u7uvP766/z666989tlnXLx4ka+++gq4lVgjIiKwt7fnlVdeAW7tcAO37gw8/fTT/PDDD4wePZqAgADOnj1LTEwMiYmJfPfddwZ3C86cOcOYMWMYM2YMTz/9tEn//7VGkjDFPXvllVdYv369yZ9lOjk5sXnzZmX39fPnz7Nq1SpGjBjBypUrgVs/FDt37szatWtLJcyTJ0+yY8cOZW+9UaNG8eCDDzJ79mzlB9rHH39McnIye/fuxd/fX3ltu3btiIiI4Mcff6Rr167K8aSkJL7//nvuv//+u8Y/a9Ys7Ozs2LVrF87OzgCMHDmS4OBgIiMj2b59O/fddx8uLi5MmzaNgIAAwsLCVPVNdV7bmjVr+O233/jwww8ZM2YMAOPGjWP06NEsX76ccePG0bp1a06cOMH69et5+umnWbJkifL6OXPmlPo+2bFjB7179+bDDz9Udf1qtGnTRvk+gVvJJCYmhkWLFpV7+/vNN9/k0qVLfPvttwb9M3PmzFIj6IYNG/LNN98oz3gdHR157bXXOHXqFO3atQNg9uzZNGzY0OB1nTp1YuLEiRw6dIguXboYnHN3d2fjxo3K972bmxvvvvsuu3fvpmfPngwYMIDZs2fj4uJS6vslNjaWnTt38vXXXxMSEqIc79atG0888QSbNm3iySefVI6fPXuW9evX889//tN4RwqF3JIV98zT01MZZZryWebTTz+t/NCAWz9k9Ho9o0ePNmjXsWNHzp49W+r1HTp0MNiItmnTpowYMYKEhATl9tRXX31F586dcXZ2JiMjQ/lTsh/fDz/8YPCenTt3VpUsr169SmJiIiNHjlSSJdz6YTh8+HAOHz5c6hZZRVTnte3YsQMnJyeDCScajYaXXnoJvV6vJOyS0dOdt3Pv/MUGoHHjxpw6dYo//vjj7hev0vPPP2/wdbdu3dDpdOV+jxYXF/Ptt9/Sq1cvg2RZ4vbvR4CxY8caTIgqGd3fflu2JFnq9XquX79ORkaG8m+XmJhY6jPGjx9v8DmTJk0CMBi1GvPVV1/h6+tLQECAwb95x44dadSoUal/8xYtWkiyrAAZYQqTMMco887bQ/b29kaP5+fnU1hYiI2NjXK8devWpd6z5NiFCxeU51y//fZbmW0B0tPTDb5u2bKlqtjPnz8PUOZtTX9/f/R6vRJDZVT3tbVu3brURJuSUWzJtV+4cAGNRoOvr69BO2dn51LXPXPmTJ5++mk6depE27Zt6dmzJ8OHD+fBBx9UFVNZPD09Db4u+czMzEyjr0lPT+f69evKJsim+IyLFy8SFRXFzp07Sz0Dzc7OLvWed/57OTk54eDgwIULF+4az+nTp0lOTlb9b+7t7X3X9xR/k4QpTOL2UWbJRKDb3fmb+e2Ki4vLPG5s5qOxJQ533i4r6zPvbFNcXExISEiZMcOtEeHtGjRoUGa7irgzhsqw1GsrL57yznXv3p1jx46xbds29uzZw5dffsmyZct4/fXXjcZ/N8a+f9TEVd73a0U+o7i4mKFDh5Kens7UqVNp06YNdnZ2FBcXM2zYsDK/99X82xpTXFxM27ZtmT9/fpnnmzZtavC1qf/NrZ0kTGEyt48y7+To6AiU/o26sLCQK1eumCWesm7vnTlzBvh7ZODj40Nubq5ym9JUvLy8AMqcEZqcnIxGoyk1OqmI6r62Y8eOodPpDBJGybWWXLuXlxd6vZ4//viDgIAApV16enqZIysHBwdGjhzJyJEjyc/PZ/jw4bzzzjtMnjy5ypaNuLi4YG9vz8mTJ03yfr/99hv/+9//+Pjjj3nqqaeU46dPnzb6mj/++MNghJiRkUF2drbB94uxhO7j40NiYiIhISEWu3a2JpMeFSZz+ygzNTXV4Fzjxo1xdnZm3759Bsf/85//oNPpzBLPL7/8QkJCgvL1tWvX2LhxIw899JBy62zo0KH8/PPPbN26tdTr8/Pzyc3NrdRnu7m5ERQUxJdffklGRoZy/PLly2zcuJHOnTtX+nYsVO+19enTh/T0dL744gvlmF6v56OPPkKj0dC7d28A5b/Lli0zeP3HH39c6j3vXO7RoEED/P39KSws5K+//qpUnJVRp04d+vfvz86dOzl8+HCp8xW9O1CS6O983UcffWT0NTExMQbtly9fDsBjjz2mHGvYsGGZz8CHDh1KWlqawWSnEjdv3ryn5+ZCRpjCxEpGmb///nupEdSzzz7LwoULeeGFF3jooYf45Zdf+P7773FycjJLLO3btycsLIwJEyYoSy9ycnKIiopS2vz73//mu+++Y/To0TzxxBN07NiRwsJC/vjjD7766islCVXG22+/zeDBg+nVqxfPPPMMer2e1atXU1RUxFtvvVVjr23MmDF89tlnTJkyhV9//RVfX1927tzJd999x6RJk5TR0X333UdYWBhr164lJydHWVayd+/eUv/mwcHBdO3alQcffJCmTZsqSy/69OljsIyjKrzxxhvs3buXQYMG8cwzz9CuXTvS0tKIj49n7dq1FXru16ZNG1q3bk1kZCSXLl3C0dGRnTt3cunSJaOvuXTpEiNGjKBPnz789ttvrFmzhkceeYTQ0FClTYcOHfj000+ZP38+vr6+2NnZ0a9fP5544gni4+N59dVXOXDgAN26dUOj0XDmzBni4uKIjo5m2LBh99Q/tZkkTGFSnp6ejBo1ik8++aTUuYiICK5du8bmzZvZsmUL//jHP/j6669Vrz2sqM6dO9O9e3fmz5/PuXPnaN26NWvXrqV79+5KmwYNGhAXF8fixYvZvHkzmzZtws7OjpYtWxIeHq4UFaiMbt268fXXXzN37lwWLFiARqOhU6dOfPLJJ5VOwpZwbba2tsTFxfHWW28pawy9vb156623+Ne//mXQ9qOPPsLV1ZUvvviCnTt38tBDD7Fly5ZSP7TDw8PZtm0bP/zwAwUFBbRo0YIpU6YwZcqUSsV4L5o1a8auXbt4++232bx5M9nZ2TRr1oyePXtW+Je7evXq8eWXX/Lqq6/y0UcfUadOHXr16sWmTZuMrnNdvXo1ixYtUn6pGjVqFHPnzjVo8+qrr3L58mU+/vhjrl+/jqenJ/369aNOnTp89tlnrFixgvXr17Nz507q16+Pp6cnTzzxBA8//HDlOkUAoMnKyrr3GQhCiCrj4ODA2LFjef/996s7FGFC8+bN45133iEpKQk3N7fqDkeUQZ5hCiGEECpIwhRCCCFUkIQphBBCqCDPMIUQQggVZIQphBBCqCAJUwghhFBBEqYQQgihgiRMIYQQQgVJmEIIIYQK/x8nfCZdd8Q5QAAAAABJRU5ErkJggg==", - "text/plain": [ - "Scatterplot with x axis labeled 'Number of periods in chapter' and y axis labeled 'Number of characters in chapter'. The points are dark blue or gold. The dark blue points are primarily in quadrant 3, and have a positive relationship where points with a higher number of periods tend to have a higher number of characters. The gold points extend from quadrant 3 to quadrant 1 and also have a positive relationship. There are gold points with higher x and y values than the highest x and y values for the blue points." - ] - }, + "output_type": "display_data", "metadata": {}, - "output_type": "display_data" + "data": { + "image/png": "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iIiIiPRiS1blVfLKD1XJGA5bqrrE9eyUjIiXXYnpBA0iIiIiQ7IlS26lCSL4iXAyhsfDiereiYiIiMwsLrqBHjDYIyIiIjIxBntEREREJsZgj4iIiMjEGOwRERERmRiDPSIiIiITY7BHREREZGJBB3tbtmyRe+65RyZNmqTvERERERFR9IO9o0ePyieffCJLly7V72iIiIiIyBjBXvXq1dXlmTNn9DweIiIiIjJCsJeWlqYCvo0bN0p2draex0RERERE0Q72bDabjB49Wk6fPi0jR46U3NxcvY6JiIiIiHRiD/aOhw8flqSkJGnfvr2au7dq1Sq55pprpGHDhlKhQgWP96lVq5Z07do1lOMlIiIiokgEe5s3b5Zhw4Y5r+/fv19ef/11n/dBoMdgj4iIiCgGgr2qVatKt27dArpPenp6sLsjIiIiokgGewjcZs2aFezdiYiIiCgCuIIGERERkYkF3bPnCTJyMzMzJSEhQVJSUvR8aCIiIiKKRs9efn6+vPHGG9KhQweVbXveeefJkCFDnLf//vvvcu+998q4ceNC3RURERERRbJnD6tnDBw4UFavXq2ux8XFSVFRUbE2NWvWlJUrV8qBAwdk6NChKiAkIiIiohjo2XvmmWdUoFevXj2ZM2eOfPrppyXaIADs06ePCgK//vrrUHZHRERERJEK9s6ePSvTp09Xwdy0adPk8ssvlzJlynhs27RpU3X5888/B7s7IiIiIopksLdlyxbJyclRK2ZcfPHFPtvWrl3bueoGEREREcVAsJedne2ck1ca9P65XhIRERGRwYM9rKABSLwozaZNm4r18BERERGRwYO95s2bS5UqVWTfvn2ydu1an7X3ZsyYoX7v3LlzsLsjIiIiokgGezabzVlP7/7775fdu3eXaHPw4EEZNGiQ7Nq1S+rUqSN9+/YNdndEREREFOk6eyNHjpTly5fLmjVrpG3btipZQ0ve6N69u6xfv17y8vJUlu4777wjZcuWDWV3RERERBTJOnvlypWTuXPnyp133ql6+rZv3+7MukUAiEAPw71ffvmldOnSJZRdEREREVE01satUKGCvPzyyzJ69GhZsWKF7NixQ83Tw3w+9Pa1b99eBYJEREREFIPBnqZ69epq6TQiIiIiMo6gu9xQTgUJGi+99JKubYmIiIjIAMHekSNHZPbs2bJy5Upd2xIRERGRfiIyma6wsFBdxsfHR2J3RERERBTJYE+rwVexYsVI7I6IiIiIAk3QQIHkhQsXOq9v3bpVXR46dEjee+89j/cpKipSZVimTZumrrdu3drf3RERERFRJIM9BHcPPfSQ39vd1a1bV2699dbAj5CIiIiIwh/sobRKv379nNePHj0q3333ndresWNHj/fBHD0M3V5wwQVy7bXXSuXKlYM/UiIiIiIKX7DXsmVL+eCDD5zXly1bJgMGDJAWLVoU205EREREJiiqjNUxsGJGcnKyvkdERERERNEP9pKSkiQ9PV2/IyEiIiIi4y6XtnfvXlm9erXs379fzp49q9bGxVw9zOez23XbDREREREFIOQobM+ePTJq1CjJyMhQpVbcpaamypgxY+Tmm28OaT/Hjx+XDRs2qGASQ8cXX3yx1KlTp0S7vLw8+fDDD70+To8ePaRevXpel3XDPhCc4vEbNmzo85jC3Z6IiIgoqsHetm3b5KqrrlKZudC0aVNp0qSJCsb27dunAhvU4bv//vtlx44d8q9//SvgfRw4cMAZTObn5zu322w2leH72muvSbly5Zzbc3JyfJaC+eSTT0oEe1lZWXLXXXfJokWLim2/44471Hq+7it/hLs9ERERkSGCvQceeEAFeo0aNZJXX31VLr/88mK3//HHH/Lcc8/Ju+++K6+88or07NlT2rdvH9A+du7cKfPnz5caNWpIq1atpGbNmiqQxJDxZ599ptpMmTKlxP1wTO7HA5569RCMIhBDmRj0/KF3cPHixfL+++9LSkqK6pmMZHsiIiIivcRlZmaWHHv1AwIuzMlDD9v3338vaWlpXttiCBcBG3q30JMVCCy1hp/LLrtM7Uvzv//9T/r06SMOh0MNJVeoUEFtz8zMVMOj11xzjdeVPVz9/PPPKihEvcBvvvlG6tevr7avW7dOevXqJXFxcWr4tWrVqhFpT8aTm5urXu/4opCYmBjtw6Ew4Dm2Bp5na+B51nFtXHz4AXrbfAV6MHDgwGL3CQQCNwRLroEetGvXTtX+KygoUMOkwfrqq6/U5X333ecMxKBNmzYyaNAg9aJxHX4Nd3siIiIiQwR7GJIE1/ly3mi9Idp99HDs2DE1xFurVi01tOsOQRTm+SFZA0Om6PHzBPMKoWvXriVuu+KKK9Tl+vXrI9aeiIiIyBBz9po3b67KqyCYQSDlayk0FF+GTp06Bbs7OXjwoCxcuFD15CFpY9asWXLmzBl566231FCou6+//lr9aBCUDh8+XB577LFivYR4XGjQoEGJx9C2IckkUu29QfBK0YE5lq6XZD48x9bA82wNVjnPiQFMKwo62EtISJBHH31URo8eLcOGDZN33nnHY8A3Z84claCBTN3rr78+2N3J1q1bi2XZopcQj4t5e54gQQNFnxHYbd68WbZs2SITJ06UwsLCYlnBCBi99VBq27Q2kWjvDYJGHDtFz+HDh/n0mxzPsTXwPFuDmc9zfHy8NG7cOPzBHp5E9Oxdcsklas4ZAivMzcPOUXoF9fCWLl0qa9eulbJly8ott9wiX375ZYnHwTCspyFOd7Vr11alSlB+5ffff5dvv/1WBg8erIJNBJ0a7Gv27NnOIVLN559/roLSN954Q2URa4FpmTJlnN8AypcvX+w+KA6tPaYm3O19/f0UHTh3eL1juoB2PslceI6tgefZGniedQz20FuG4Elz6tQpVUrEEwQ1Tz31lMfbEOj5E+whCQTlXVzLuvTr109eeOEFldXaunVrZ2+Ze6AHqMmHgA9DwZgjh+xeQJas1nPm3jOpDcFqbSLR3htmgUYfAj2eB3PjObYGnmdr4HnWIdhDqZBu3bpJqIJdXxf16dCTuHHjRtV7qAV7vmg9a5j3p2nRooUsX75clY/B766+++47Z5tItSciIiIyRLCHIA1JEuGGHkT06rmvMoHeQmTZQqVKlYq1b9asWYn1eJFIorVHcokGhZ7ffvtt9XPDDTc4A0IMFSOTF8kfV155ZcTaExERERlqbdxwQ1LFjz/+qFaeQPYqgjgMfyLTFsWWq1WrJt27d3e2x1Av5vOhvbb2LHr/5s6dq8bx+/fvX2xNXQwhX3TRRfLTTz+pnkokkaDdBx98ICdOnFC18FxX3Qh3eyIiIiJDrKARKVhmDfPyPKVQI5jDKhkIpjRYK/fZZ5/12B69bFOnTlUJJK6wAgdW3MD6va6wtNvMmTNL1AcMd3syFlZjNz+eY2vgebYGnucwBntFRUWqXhxq7rnOiXOFIAslUQJ1/PhxlViBYAmrZSChAQEees3ch2u1gsvIEN6+fbsqa4KePCRk+JrXh3bo/cNwL4aMsULHVVddVWL4OFLtyTj4xmF+PMfWwPNsDTzPYQj2UGLl+eefV8uCnTx50mdbBGcIeIhiCd84zI/n2Bp4nq2B51nnOXvbtm1TyQWYewYYjkQJFpSnwO9Hjhxxpj+jRpmnZc2IiIiIyIBr4wKKGSPQw5AkhieRdKDNRcOKF7/88ouaJ4dCyChkPGXKFL2Om4iIiIjCGexhbt6yZcvUnLPJkyd7zChF9uz06dNVIsXjjz+uAkAiIiIKQJGh8yjJzMEekh8cDodKuGjSpInahppx4LqGK4Z0hwwZonr3kHlKREREpXBkSeLJUZJ0OF2Sj7RQl7iO7UQRm7OnBXSuS31p64YiY9aVtljvb7/9FuzuiIiIrMGRJUl/9BBbwVaJE4dzsy1nqtjzVkh2ymIRW/ESYkRh6dnTChNjgXhNamqqukSxY5Ri0WhZusiQISIiIu8Ss8aVCPQA17E9MWs8nz6KTLBXu3ZtqVy5shw4cEAtXabN0atRo4YK7ubMmaO2oeYelgXTbiciIiLv7LkLSwR6Gmy35y7g00eRCfZsNpv07dtXBXqosafN2Rs8eLD6/Z577lGrRnTp0kVWr16tbsNSYURERORFUZHESb7Pp0fdzqQNilSdPQR0tWrVKraKxSOPPKLWol2wYIEsWbLk3E7sdnn66aelbdu2oeyOiIjI3OLipEgSfDZRt/+ZEEkU9mCvVatW6sdV2bJl5eOPP5Y1a9ao2ntI2rj00kulfv36oeyKiIgofNBTZpAAqiCxl0rG8DSUWyQ2KUjsHZXjIosGe76gF489eUREZOjyJlnj/pwjl696zBBo5SaPjWq2K/aPrFv3JA0Eeg57c8lNHhO1Y6PYFLZgj4iIyLCMXN7Elqz2j6xbJGP8FYj2PhfosewKBYjBHhERWY4/5U1yK02I2vEhoFP7x4+BhpjJosHesWPHZMaMGfLdd9/J0aNHnWVYPMEauq+++mqouyQiIgp/eZNoBnuuGOhRNIO9devWycCBA+X48eN+tU9JSQlld0RERJEtb8JAi6we7N17770q0EMQhzIsLVu2lORk73McUISZiIgoqljehCwm6GBv27ZtsmXLFlVDb968eSrQIyIiigUsb0JWEvQKGkeOHFGXaWlpDPSIiCimoLyJw56mypm4YnkTMqOgg72qVauqy/j4eD2Ph4iIjMSsy3L9Wd4kr/xQKbTVF4ctVV3ienZKBsubkKkEPYzbvHlzSU1Nle3bt8vJkyelUqVK+h4ZERFFh0GLDeuO5U3IIoLu2bPZbPLkk0/KmTNnZPTo0VJQUKDvkRERUdSKDZfJmSrxjr1icxxSl7iO7bjdlJh1Sybmd8/e4cOHZdmyZcW2xcXFSadOndRauOvXr5err75aGjRooAJBT2rVqiVdu3YN/aiJiMiaxYaJKHzB3ubNm2XYsGFeb9+4caP68QWBHoM9IiLjiqliw0Skb7CHhIxu3bpJKNLT00O6PxERhRGLDRNZO9hDoDZr1qzwHg0REUUPiw0TmVLQCRpERGQ+yLp1rz2nwfaCxN4RPyYiCg2DPSIicmKxYSLzCSnY27lzp7z33nuyfPlyr21OnDih2syZMyeUXRERUSSw2DCR6QRdVBmeffZZNY9v6tSpXtug2PKkSZNk//79ctFFF0n9+vVD2SUREYUbiw0TmUrQPXs5OTkyb948KV++vPTv39/7Dmw2GTRokDgcDvn888+D3R0REUUDiw0TWTfY2717t+Tn50vDhg0lISHBZ9u0tDR1iaXViIiIiCgGgr3MzEx16c+auBUrVlSXx44dC3Z3RERERBTJYK969erO3rqioiKfbbdt2+YszExEREREMRDsNW3aVKpVqyZHjx6VL774wmu73NxcmT59uvq9ffv2we6OiIiIiCIZ7MXFxckdd9yhfh8xYoQqreLew3fw4EG56aabVO9flSpVZODAgcHujoiIiIgiXXrloYcekiVLlsjatWvl9ttvl7p168oFF1wg5cqVkwMHDshPP/2kkjji4+Pl7bffds7dIyIiIqIYCPYQ1M2dO1dGjx4tn3zyiaqlhx/3TNyXX35ZLr300lCPlYiIiIgiGexBUlKSvPnmm/LEE0+olTT27NkjZ8+eVckYbdu2lUsuuUTV2iMiIovCFB/W6yOK3WBPk5qaKjfccINeD0dERLHMkSWJWePEnrtQ4iRfiiRBChJ7qbV3sUIHEcVgsEdERKQ4siTpjx5iK9gqceJwPim2nKliz1sh2SmLGfARRRDHV4mISFfo0XMP9ADXsT0xazyfcaIIYrBHRES6Ojd0WzzQ02C7PXcBn3GiCGKwR0RE+ikqUnP0fFG3l7LyEhHph8EeERHpJy5OJWP4om5ndi5RxDDYIyIiXSHrtsjLxwu2FyT25jNOFEEM9oiISFcor+Kwp5UI+HDdYW8uuclj+IwTRRCDPSIi0vmTJVmVV8krP1QKbfXFYUtVl7ienZLBsitEEcY6e0REpD9bsuRWmiCCH66gQRTbwd6xY8dkxowZ8t1338nRo0fVUmnetGvXTl599dWA9/H999+rtXfXrl0rBw4ckOTkZPVYw4cPlwsvvNDjfVasWCGvvfaabNiwQex2u1q67dFHH5WWLVvGRHsiItNgMgZRVMVlZmYGnf++bt06GThwoBw/ftyv9l27dpW5c+cGtI9Vq1ZJ3759Pd6GoGn69OnSp0+fYttnz54td955pxS5pfaXK1dOvvzySxVoGbk9GUtubq7s27dP6tWrJ4mJidE+HAoDnmNr4Hm2Bp5nnYO9Dh06yJYtWyQlJUXuuece1UuFXjdvKleuLBdccEFA+/j222/llVdekWuvvVbS09OlVq1a6oP3jTfekFmzZknt2rVl48aNEvfnN8eTJ0+q3r4TJ07IyJEjZciQIZKXlycvvfSSfPjhh9KiRQsVQNpsNkO2J+PhG4f58RxbA8+zNfA86ziMu23bNhXooXdt3rx5YRuO7Ny5s/pxheDyP//5j6xZs0b27Nkjhw4dUkEf4FgQWPXv31/GjPkr4+v1119XQ6i//PKL/PjjjypQNWJ7IiIiIj0F3Z105MgRdZmWlhaVeWfoCStfvrzq0UOPoWtPINxwww0l2l9//fXq95UrVxq2PREREZEhevaqVq2qLuPj4yXSkBQyefJk2bx5swwaNEgFfZqdO3eqSwyPumvVqpW63LFjh2HbExERERki2GvevLmkpqbK9u3b1by0SpUqSTih9wu9YwUFBSrjt0KFCnL33XfLM888U6wdjkUb6vUWoJ46dcqw7X3NQaDowBxL10syH55ja+B5tgarnOfEABIGgw72MAz55JNPqsSM0aNHq4QJzN8Ll8LCQjl9+rTzOgK+Xbt2qfl6jRo1KtFeS9hwP2ZwOByGb+/u4MGD6jmg6Dl8+DCffpPjObYGnmdrMPN5jo+Pl8aNG/vd3h7Kk4gAplOnTvLxxx/L+vXr5eqrr5YGDRp4zSxFJi3KrwTj0ksvlf3796uePQR4KOGCjNbevXurBIeKFSuqdklJSeoyMzNT9f65QqIEaG2N2N4bLQGFIg/fDvF6r1mzppQpU4anwIR4jq2B59kaeJ51DPYwX27YsGHO6yh/gh9fEOgFG+whitUCJyRknH/++ZKdnS1vvvmmLF68WNX7A/Tyofgyjq9OnToljllrozFae29Y3y36EOjxPJgbz7E18DxbA8+zTgka3bp1C+g+qJOnJ21oFL1mGpQw+fzzz1Uh4+7duxdrj7p8gN5Io7YnIiIiMkxR5Uh4+umnpVq1amq4tm7dumpeIIbUvvjiC3nqqadUd+3y5culdevWzkxd/J6TkyMvvvii3HbbbZKfn6+GfLFUW8OGDVV9Pm1+odHak/GwQKf58RxbA8+zNfA8x2CwhxUn0CsGmAuI3jzXRIWhQ4fKxIkTi91n6tSparUKbfgXCRBYqgy/z5w5U6644gpDtydj4RuH+fEcWwPPszXwPJdk+DW6UFpl1KhRqk4dxt8R6CGh4fLLL5f333+/RKAHd911l7z77ruq2LMWVLVv317mzJnjMbAyWnsiIiKiiPfsHThwQObPn69+R6IB1nvVrvsL9+vTp09wRyqiAiUMgQaSEYngEL2B/q49a7T2FH38lmh+PMfWwPNsDTzPJdkDWQsXPWyAjNoHH3zQed1fuF8owR6CpEBLXwS6wofR2hMRERFFJNhDjTEsTQYoe+J63V+4HxEREREZMNhDoDZlypRi29yvExEREZGxcOIYERERkYkx2CMiIiIyMQZ7RERERCbGYI+IiIjIxBjsEREREZkYgz0iIiIiE2OwR0RERGRiDPaIiIiITCzswR7WgiUiIiKiGAz29uzZIzNmzJBVq1YV23769GkZMWKE1K9fX2rUqKGWVTt06FCox0pEREREkQz2XnzxRbn//vtl7969xbaPHj1apk+fLqdOnVI9exkZGXL99dezl4+IiIgoVoK9/Px8+eKLL6Rs2bJyzTXXOLcfP35cPvnkE6lWrZosWLBA/aSkpMj69evl66+/1uu4iYiIiCicwd6BAwckJydH6tWrJ4mJic7tS5YsUYHg7bffLh07dlQ/d911l7ptxYoVwe6OiIiIiCIZ7B08eFBdVq9evdj2H374QV3+7W9/c25r2bKluty3b1+wuyMiIiKiSAZ7ZcqUUZcnTpwotv3bb78Vu90ubdq0cW6Lj48/tzMbK70QERERRVLQ0VfTpk1V8Pbbb7/Jzp071bYtW7bIpk2bVKBXvnz5YkO+ULduXT2OmYiIiIjCHexVrlxZunXrJkVFRdK/f38ZNWqUKrECyLx1hYDQdTiXiIhMoKgo2kdARH4IaVx14sSJqrcOc/GmTJmiSrBcccUVcttttznbOBwOmT9/vuoFvOqqq0LZHRERRZsjSxJPjpKkw+mSfKSFusR1bCciY7KHcueGDRuqhIyFCxfK0aNHJS0tTSVmxMXFOdscOXJEBgwYIKmpqSWSOYiIKIY4siTpjx5iK9gqceJwbrblTBV73grJTlksYkuO6iESkY7BHubnTZo0Sc477zz55z//6bVdrVq15IUXXgh2N0REZBCJWeNKBHqA69iemDVecitNiNrxEZHOw7joyUPx5KVLlwb7EEREFEPsuQtLBHoabLfnLoj4MRFRGIM9bUj2zJkzwT4EERHFSlJEUZHESb7PJup2Jm0QmWcYF/PzEPBt3LhRsrOzJSkpSd8jIyKiv5Iissb92bOWL0WSIAWJvSQ3eWzk5sjFxan9+qJud5mzTUQx3rOH7NrRo0fL6dOnZeTIkZKbm6vvkRERkTMpokzOVIl37BWb45C6xHVsj2QWLALMIi8fG9hekNibZ4zITD17hw8fVr157du3V3P3Vq1aJddcc43K0K1QoYLXZI2uXbuGcrxERJZipKQI9CQi69b9eBDoOezNJTd5TESOg4giFOxt3rxZhg0b5ry+f/9+ef31133eB4Eegz0iIp2TIiKVAWtLVuVVEGBiv38NKfc+F+ix7AqRuYK9qlWrqhU0ApGenh7s7oiIrCeQpIhIzZWzJZ/rScRPJPdLRJEP9hC4zZo1K/g9ExFRbCdFMNAjMv9yaUREFF5MiiAiQwV7yMj9/fff5Y8//tDzYYmI/GPCGm9IinDY00pkwTIpgogiFuzl5+fLG2+8IR06dFDZtlg+bciQIc7bEfzde++9Mm7cuFB3RUTkuQbdyVGSdDhdko+0UJe4HsmSJJFIisgrP1QKbfXFYUtVl7ienZLBpAgiCt+cPW31jIEDB8rq1avV9TjML3H7Zl2zZk1ZuXKlHDhwQIYOHaoCQiIiPWvQuZcCseVMVSVCECSZIkNUS4qo+Oc645wrR0SR6tl75plnVKBXr149mTNnjnz66acl2iAA7NOnjwoCv/7661B2R0QUcA060/VcHmltrp5LIjJusHf27FmZPn26CuamTZsml19+uZQpU8Zj26ZNm6rLn3/+OfgjJSIKpgZdLM8HNNDqGURkwWBvy5YtkpOTo1bMuPjii322rV27tnPVDSKiiNegi9H5gJbouSQi4wZ72dnZzjl5pUHvn+slEZHha9AZoFctoj2XRGRatlBW0AAkXpRm06ZNxXr4iIiMXoMu6r1qkei5JCJLCDrYa968uVSpUkX27dsna9eu9Vl7b8aMGer3zp07B7s7IqKI1qCLeq+a0VfPICLzB3s2m81ZT+/++++X3bt3l2hz8OBBGTRokOzatUvq1Kkjffv2De1oiYgiUYPOCL1qjiwpiksWb3sIteeSiKwjpDp7I0eOlOXLl8uaNWukbdu2KllDS97o3r27rF+/XvLy8lSW7jvvvCNly5bV67iJiIrXoMMPgi89erqi3aum1Q8sxDCyp33HhdxzSUTWEVKdvXLlysncuXPlzjvvVD1927dvd2bdIgBEoIfh3i+//FK6dOmi1zETEXnmT/DlZ29cNNek9TZf8Ny+RQrjW3L1DCKKTM8eVKhQQV5++WUZPXq0rFixQnbs2KHm6WE+H3r72rdvrwJBIqKoQQmVrHF/zsPLV71yCOYw58/bUC9uwyoc7kFXJNak9T1fUCSu6JQ5VgYhotgI9jTVq1dXS6cREcXckmqehmz/nA+IrFskY/wVJPY+F+iFK9gKZL4gkzOIyA9Bd7mhnAoSNF566SVd2xIR6SmkEip/zgfMrrlesmpsUpdqfmA4e9WiPV+QiEwn6GDvyJEjMnv2bFm5cqWubYmI9KRbCZUIBlfRnC9IROaj2zCuL4WFheoyPj4+qPs7HA6V8IEs36NHj0qNGjXk0ksvdWb/usJ8wVdffdXrY1133XXOtXrd94E5hxs2bFDH2a5dO/Xj65jC2Z6IdGCEEipBiOZ8QSIyn4gEe1oNvooVKwZ83w8//FCee+45VbPPFZZeu/3222XixIlit9uLBXsTJkzw+nht2rQpEewdO3ZMbrjhBhVQuurTp4+89957JUrGhLs9EVl8SDRa8wWJyNrBHoKthQsXOq9v3bpVXR46dEgFLJ4UFRWpMizTpk1T11u3bh3wAX777bfy+++/q6zeZs2aqWXafv31V1myZIm8//776vrYsWNL3O/888+Xfv36ldjuqVfvrrvuUoEYlnPr37+/5Ofny+effy7z58+XMWPGqIAyku2JSN8hUSRjeC5jYuAh0XDUDyQiS4rLzMz0a/xi2bJlMmDAgKB3VLduXfUY1apVCzjYa9SoUYl1ddHjN3z4cElNTZXNmzc7t2dmZqrh3WuuucZrEOrq+++/l169eqnjwzCrtuYvSsh07dpV9RRu3LhRatasGZH2ZDw4R1gWsF69epKYmBjtwyGdsnG1IVGstJGbl8BzbAH8X7YGnucQevZQWsW1pwxz57777ju1vWPHjh7vg7lpGLq94IIL5Nprr5XKlStLoLytp3vzzTfL448/LsePH5dQLFhwbnL2fffd5wzEoEmTJnLjjTfKf/7zH1m0aJEMHjw4Iu2JKBpDorl82onItPwO9lq2bCkffPCB87rW09eiRYti2yMlKytLRe/ehobRw/ff//63WEJHgwYNSrTDkDB4WuED90EwprWJRHsiCgMOiRKRhQWdoIHVMTAsmZwcnYnCSNrAcmyPPPKIx9sxpw8/Gqziceutt6r5cVirV4P5gIAhOnf169dXl5h3GKn23iCwpejA68z1ksyH59gaeJ6twSrnOTGAaUVBB3tJSUmSnp4u0YCEj8mTJ8s//vEPufLKK0vcjkxdJHRg+BhBHoo6o8bf9OnT1dDyK6+84mx79uxZdekpI1bb5hpohbu9rwQZrYQNRYc/QTnFNp5ja+B5tgYzn+f4+Hhp3LhxZEqv7Ny5Uw3nYv4Zkg08OXHihHzxxRdqvlooCR6aKVOmyKOPPqpW5HjmmWdK3F6uXDnV44hAz9Xy5ctl0KBBKlDEXD8tUUQLuBCUlS9fvth9tEDNNXoOd3tv3BNUKHLw7RBvGkiice0VJvPgObYGnmdr4HnWOdh79tlnZdasWTJ16lSvbSpVqiSTJk2S/fv3y0UXXeQcugzGiy++qIZvhw4dqn5HD547BFfugR4gGEUv4JdffqnmyF1++eVqe61atVQ2LLItq1SpUuw+e/fuVZeY86cJd3tvmAUafQj0eB7MjefYGnierYHnWYfl0nJycmTevHmqtwq147zBMCp61LCCBGrLBQP1+tCbh0Bv2LBhat6dp0AvGK1atVKXq1atKnGbtryba/AY7vZEREREhgj2sCoGigOjpl1Cgu8K9Wlpaepy+/btAe+noKBABXjvvPOOqqvna3UM+OGHH+TUqVMltmMYNyMjQwWfyCzW9O59rqDqW2+9VayMC+rgffzxx2p1jp49e0asPREREZEhhnFR2kQbpi2Ntkwalg0LFHr0PvvsMzVnrUKFCvL888+XaDNixAjnfLh3331X1bZDqRNt7VwMo2IeH6CeHWoDajp06KCGeBEM4j6uK1xkZ2erIWPXgsfhbk9EpeBqEkREkQn2tIAJvXUYZvU1rLpt2zZ16VpUONB1dZGN6q1X7+6773YGeyjwvHjxYmcxYw169G655RaPS5NhziHWrl27dq28/fbbzu1XXXWVjB8/PuLticiNI0sSs8aJPXehS1HkXpKbPNb468QyOCWiWA32sMYsMlpRtBjZtliezBOUFUHJE0A5lEBhvh9q+vmCDFzNHXfcoVamwBw5BJnYP3oF0atWp04dr4ErAkT0vm3YsEEFhpdccon6iUZ7Iip9uTOsd2vPW6FWx9A74CvtC6ypg1Misu7auN6ycdFThsLKb7zxhhqidH2DRG8c5tmhuDEyUX/55RfnkC5RrOA6i9GVeHKUlMmZWizQc13fNq/8UMmt5Hsurz/neMuWXfLf/x6VxYsPSH6+QxISbNKrVwMZO7atJCeX0Wkt3rSwBKfkH/4vWwPPs87B3pkzZ6Rv375qeBLq1q2rMkvR03bgwAH56aef1Pw0FP+bMWOG9OrVK9hdEUUN3ziiK+lwusQ7zpUp8qTQVl+ya64PaR/HjmXJlVfOk927c8ThElPabEgwqyKLF/fzO+CLRHBKweH/sjXwPOuYjQsI6ubOnavmwiGrFLX0MFdu9uzZKisWgR4ycefMmcNAj4gCh+FUyffZRN2OeXEheP75dSUCPcD1rVtPyPjxa/x+rHNDtw4vx+oQe27x+cRERIYuqqwtm/bmm2/KE088oeak7dmzR60MgWQMzLXDvDTMUSMiClhcnJrv5ou6PcS6mxkZ+0sEehpsX7Bgj0yY0Enf4FSnWqFERGEP9jSpqakq45SISE9IbLD5GBYtSDxXyzKUZAzM0fMFt/uVtBGh4JSIKBDsciMiQ0MGKxIbENi5Opfw0Fxyk8eE9PgI4JCM4Qtu9zc7F8Gp+7HqGZwSEUWtZw/feg8dOqSKLWPVC0+QtduoUSO9dklE0RSpoUhbsspgTcwar+a7/VXKpPe5QE+HzNYrr6wr77//m8ehXMxC6d27QUDBKUrCeM7GDT04jRkcqiYyT7CHpAysavHVV1/JyZMnfbbFShJI6CCiGBWt+nG25HMZrPgJQxDx2GNtZOnSfR6zcZs3ryJjxrQ1VHAadsE+x6wvSGS+YA9Fi6+88ko5ceKEuo4aeliXNjExUf1+5MgRtb1MmTJqSTAuC0YUw6JQ3NijMPQmJiUlyHvvXSQffnhUMjL+qrOHHj0EegHV2YtAcBoWoQZqRnl9EJG+c/awbi0CvXbt2qmVIT744APnShlbt25VRZR79uypSrA88MADMmXKlFB2R0RRhEDA/YMccB3b0ZMVyypUsMv48ZfI+vU3yqZNN6lLZOAGHOi5i5FAD4Ea6gOipqHNcUhd4jq243arvz6ILBnsYW7esmXLVMHkyZMnS7169Uq0adCggVoqrWHDhvL444+rAJCIYpOV6seFtFRaoEKsEagHPQI1K70+iCwT7G3fvl0cDodKuGjSpEmxN8jCwkJnOwzpDhkyRPXuzZw5U49jJiKTFje2DAyZnhylVgdJPtJCXeK6Pz1o4RByoMbXB5E55+xpAV316tWd2zA3D7Kyir9hNW7cWF3+9ttvwe6OiKLJDPXjjDJ3Ltpz29yfBz0KQZvh9UFkYkH37NWpU0ddHj58uFhhZdi9e7cqxaLRsnSxXh0RxaaYrB9nsB60qM1t8/U86BSoxeTrg8gigg72ateuLZUrV5YDBw6o5dG0OXo1atRQwR3WwwXU3Pvwww+dtxNRbAp3cWMjJh2EQ8TntvnxPOgRqMXc64PIQoIO9rDebd++fVWghxp72py9wYMHq9/vueceueaaa6RLly6yevVqddv111+v35ETUWT9WT8ur/xQKbTVF4ctVV3ienZKhuHKahgyOzQKc9v8eR50CdRi7PVBZCUh1dlDQFerVi2x2/96mEceeUQ2btwoCxYskCVLlpzbid0uTz/9tLRtG0BhUiIynhiqH+dXDxr+jkiKwtw2f58HXQpBx9Drg8hKQgr2WrVqpX5clS1bVj7++GNZs2aNqr2HpI1LL71U6tevH+qxEpGRGPmDXI+kgzDBkCmSMTwFYLrPbQvkedA7UDPy64PIYoIO9rZs2SKTJk2S8847T/75z3+WuB29eOzJI6KoMHB2aETXzg32eWCgRmQqQc/ZO3r0qHzyySeydOlSfY+IiEgHUckO9WeuXYTntjFLloiC7tnT6uudOXOGzyIRGU7EetCCWVM2gnPbItqTSETm6tlLS0tTAR+SMbKzs/U9KiKiUEWiB02P8i7hHjJlliyR5YVUemX06NFy+vRpGTlyJAsmE5Hx/NmDll1zvWTV2KQuVY+aTkOlhizvEoXngYhMOoyLlTOSkpKkffv2au7eqlWrVF29hg0bSoUKFTzeB2VaunbtGsrxEhH55m1YNAw9aIYs71KaP58HrHKkrWdOROYWdLC3efNmGTZsmPP6/v375fXXX/d5HwR6DPaISHfBzJszcXkXb7Ky8mTcuDWycOEeyc93SEKCTXr1aiBjx7aV5ORza5sTkfkEHexVrVpVunXrFtB90tPTg90dEZHPeXPuw6moZYfEBMzbC0vAZ+DyLt4CvR495snWrSfE4dIZOXXqRlmx4qAsXtyPAR+RSQUd7CFwmzVrlr5HQ0QUjuXAwjSUGtECySFCj557oAe4ju3jx6+RCRM6RevwiMiICRpEREbg17y5MNFlTdkIwdCte6CnwfYFC/ZE+pCIKEIY7BFR8AWCoy2QeXMxUtYEiRN6w2Nijp4vuD0c+yaiGF8b1xXeJA4dOiSZmZlSUFDgsU1ycrI0atRIr10SkRkSHcI+by4+vPPmdCiQHO7ECWTd4jF9we3MziUyp5CDPWThPv/88/LVV1/JyZMnfbZFJu7cuXND3SURmSnRIazz5kTiirLPFTeOxLEHGehFInECwSMe09NQrs0m0rt3g5D3QUQmHMbdtm2bXHrppTJjxgwV6FWsWFFtT0xMlBo1ajjblSlTRurVqyc1a9YM/YiJKCxipkCwG/Q6FsVVUoGdO4RecUUnDXvs/iZO6AG9hGlpVVRg5wrXmzevImPGtNVlP0RksmDv0UcflRMnTki7du1kw4YN8sEHH6jtKLS8detW+eWXX6Rnz56Sn58vDzzwgEyZMkWv4yYiEyU6hMSWLEVSQQV2nmCg17DHHsHECfQOopdw6NCWUr9+kqSmlleXuJ6RwbIrRGYW9DAu5uYtW7ZM4uPjZfLkyarnbseOHcXaNGjQQKZPny4dO3aUxx9/XA3jYk1dIjKYGCwQ7KRWgig8N2YbY8ceSOKEHvPpEPChvAp+uIIGkXUE3bO3fft2cTgcKuGiSZMmapv2ZlRYWOhshyHdIUOGqN69mTNn6nHMRGTxAsFhPfYIZqRGM3GCyRhE1hF0sKcFdNWrVy82Nw+ysrKKtW3cuLG6/O2334LdHRFFINHBvV6cUQsE633sSOKoV+YlSTnZTpKPtJCkw+mSeHLUucSOMEPihPs8Og0TJ4goqsFenTp11OXhw4ed21JTU9Xl7t27i9Vr0rJ0c3NzQzlWIgqjWCoQrOuxO7Kkyqk+UiNhptgd+8TmOCTxjr1SJmeqyk4Od8DHxAkiMmywV7t2balcubIcOHBAzp4965yjhyxcBHdz5sxR21Bz78MPP3TeTkQGFYYCwbFw7KquoGObxMVFJwuZiRNEFG5xmZmZQU9QGT58uArk3n33XRk4cKDaNn78eHnppZekbNmy0rlzZzl48KBs2bJFzQ9ZvHixtG3L9H6KLeiR3rdvn0pCwhxUyzBgQkM4jh1DtujJ8wZBY3bN9RIpTJwIH8v+L1sMz7PORZXvueceqVWrltjtfz3MI488Ihs3bpQFCxbIkiVLzu3Ebpenn36agR5RLInVQA8CSMYwWhYyEyeIyFDBXqtWrdSPK/Toffzxx7JmzRpVew9JGyi8XL9+/VCPlYhIX7GchUxEFOm1cd1huJZDtkQUsjD3qvlebs3YWchERGFfQYOIKCwcWar0CebThbsUCjJ5C2zNxFEUe1nIRERR7dkjIgqKI0uVPHFfpxe9b/a8FSrrVtfMYFuynKg4X4qOPCEpiavRl6eGbtGjpwK9aGchx3KiDBGZI9g7duyYzJgxQ7777js5evSoswyLJ1hD99VXXw11l0RkYiiF4h7ouZdCya00Qdd9FsUlyb68kSI160li2bLRD67Qs4mSMGq94vw/g89eqhcy6sEnEVkr2Fu3bp0quXL8+HG/2qekpISyOyKygHMBjuf1YrHdnrtAROdgr/hO4qzVs0lEphdSsHfvvfeqQA9BHMqwtGzZUpKTvb8JoQgzEVEslUKxQs8mEZlb0MHetm3bVLFk1NCbN2+eCvSIiELCUijR79kkItMJOhv3yJEj6jItLS2igV5eXl5A7QsLC4ut0xtr7YmsBnPT3Ne4tUwplEB6NomIwh3sVa1aVV3Gx8dLOP3+++/y73//W3r27Olce7dhw4Zy2223qZU6vJk9e7Z06dJFtcdPr169ZOXKlTHTnsiqkITgsKeVCPgsUQqFPZtEZKS1cR0Oh+rRy8zMVMO5lSpV0v/o/pwXiBU5NAgu0TsG5cqVkzlz5kj79u2L3Qdr9T788MPO9jhW9KZhyHnmzJnyt7/9zdDtyVi4zmK0slHHqyHLv7JRw1cKxUjnGPUEy/go8pxXfijn7JngPFP48Dzr2LNns9nkySeflDNnzsjo0aOloKBAwiE1NVXuv/9+ycjIkN27d6vyLt9++6107NhR7Xvs2LElSsHguLC+5MSJE+XQoUOyf/9+efDBB9UxapdGbU9E52rfIQkhu+Z6yaqxSV2qpAQLZKFaumeTiKKboHH48GFZtmxZsW0IYDp16qR63tavXy9XX321GmpFIOhJrVq1pGvXrgEd4L/+9a8S29CjiNp+zZo1k19++aXYbejpy87OlptuukmGDh2qtmF9XgRc33//vaoHiGBROw6jtSciNybNuvXKlqzKq0SyZ5OIzM3vYG/z5s0ybNgwr7dj/pyvOXSAgEavoAZzBjF0XBYFUF0ggIJrrrmmxH1QExDB1erVq53HYbT2RERaz6bKujVxmRkiMliwh+CqW7duIe0sPT1d9LJkyRJV42/48OHFtu/atUtdnn/++SXuo23T2hixPRFRMQz0iChSwR4CtVmzZokRYN7bP/7xD2ncuLGMGjWq2G0YMvVWwLlKlSrq8tSpU4Zt72vCKUWHVu4n0LI/FDt4jq2B59karHKeEwNIMgp5bdxoBHoDBgxQGbnIZK1YsaLHdp5q2SELFjzNKTRae3cHDx50ZiFTdGDeKpkbz7E18Dxbg5nPc3x8vOrwMmWwh2zc/v37q2j9q6++kiZNmpRoo5WA+eOPPyQpKanYbdoavq4BotHae1O7du1S21B44PWGN42aNWuq5BoyH55ja+B5tgaeZ52DvZ07d6oMXQRd3hIMTpw4IV988YWa84ceuWD9+uuvKqEBtenmz5/vNaLF9h9//FEliyAz2P0xwDVINFp7b1gTKvoQ6PE8mBvPsTXwPFsDz7MOdfbg2WeflYceekjVvvMGPVuTJk2SIUOGyN69e4PaDzJa+/TpIwkJCT4DPejcubO6/PTTT0sMmWrbsJKFUdsTERERGSLYy8nJkXnz5kn58uXV0KrXHdhsMmjQIBXcfP7550Fl3aJsSYUKFdQcvWrVqqmkB9cfV/369VPJEHPnzpXx48eruW4Y/n3ggQdUTb4WLVoUW3HDaO2JiIiIDLFc2qZNm1RBZQQrqBPny2effSZ33323Kiz81ltvBbQfDN1+8803Ptvs2LFDUlJSnNeRNXzXXXeVSIrAEBzm+rVt27bYdqO1J2Ph0jvmx3MceXg/RGH+SOJ5tgaeZx3n7GFNXPBnTVwtAQFLhwUKARF69Xxxf8NAgFi9enU1fLxhwwaVtdKuXTu1rBtW33BntPZERGaUlZUn48atkYUL90h+vkMSEmzSq1cDGTu2rSQnM/mJyHDBHoIX2L59e6nf0LZt26YukaQRKCyLFozLLrtM/cRqeyIj9IQQ6Rno9egxT7ZuPSF/Vp1Spk7dKCtWHJTFi/sx4CMy2py9pk2bqvlzSM5Atq2v7tTp06er3zk3jSjwD8hRo1ZLevrH0qLFR+oS17GdKJagR8890ANcx/bx49dE69CITC/oYA89DHfccYf6fcSIETJnzpwSc9KQjIB5euj9w2oRGM4kosB6QtDzsXdvthw6lKMucR3bGfBRLMHQrXugp8H2BQv2RPqQiCwjpDp7KLuCbNm1a9fK7bffLnXr1pULLrhAypUrJwcOHJCffvpJ8vPz1Ry1t99+26/iwUTkf0/IhAmd+HSR4aEjAHP0fMHtnKpAZMA6ewjqUFLklltuUcWO9+/fLwsWLJDZs2fLDz/8oAK9tLQ01evXq1cv/Y6ayAIs2xPiYWlBim0YCUIyhi+4nXNSicIj5OXSsATYm2++KU888YQsX75c9uzZI2fPnlXJGCgpcskll/i19isRWbgnxJEliVnjxJ67UOIkX4okQQoSe0lu8lgRW3K0j450gKxbTEHw9AUGHxG9exdfYYiI9KPb2ripqalyww036PVwRJYWqz0hQQWfjixJ+qOH2Aq2Spz8FQnYcqaKPW+FZKcs9h3woSfQYM8DlYTyKsi6dZ+agECvefMqMmYM640ShQu73IgM3BPirVPcSD0hoWYMo0fPPdADXMf2xKzxnnsCT46SpMPpknykhbrEdWwnY0IdPZRXGTq0pdSvnySpqeXVJa5nZLDsCpEhV9AgsopoVWP3VpdM6wkxwgekr2NMS6viV+00BGrxDu/rZhfa6kt2zfWl9gQWiU0c9rTSewI9YMX9yOMKGhQu/H8uiT17RAbiWr4oFnpCQq6dhmFfyffZRN3u8rwE1RNIhmO0KQhEZqbbnD0iCs8SUiivgh8jJmN8/fXuUjOGfZaHiYtTyRi+qNtd/u5zSRyed4rt9twFIpUm+PkXEBGZH4M9ohhZQspogd6pU2fl999zQs4YRtYtkjE8BXAYmi1I7B1cT6DBni8iomjhMC5RFMXyElLjx6+VgoKikDOGUV4Fc+0Q2Lk6NwevueQmjwmpJ5CIyOr8DvbWr1+vljt7+umn1fXTp0/Lpk2bVF09IrJe4WQce2n8yhi2JaukirzyQ1UyhsOWqi5xPTslo0SyBXoC3QNDrz2BRETk/zDu8ePH5ZtvvpGCggJ1/X//+58MGDBAunbtqlbRICLrFE7259jt9jh54omL/XtAW7LkYp4dfrwNwf65HT2BqL/nORvXrSeQiIj8D/awvi1gCTQism7hZH+PvVat8lKxYtlgHrzUlTWyq3whiacnqWSMv7b3PhfoccUNIqLggr0aNWqoyx07dqjl0IjI2ktIlXbsffo0DG0H/qys4asnkIiIAgv2mjVrJnXq1JEDBw7IxRdfLBUrVlTb161bJ7169fLrMdq0aSPPP/+8v7skMr1YXkIq3MfuTz09NfTLQI+ISJ9gz2azydtvvy133XWX7N+/37n91KlT8v333/v1GGXLBjGkQ2RiWuFkZN0iGUOrs4cePQRLRiicHK1jZz09IqIoLZeWk5MjW7ZskcWLF6teupYtW8pjjz3m132rV68u7du3D/ZYiUy/9I4RkzGicuxFRWrNW5vjkNcmyNrNqrFJl549Lq9kDTzP1sDzrENR5fLly8tFF12kevSgWrVq0rdv30Afhog8iGigp/NcN12PnfX0iIiiv4JGenq6fP7555KSkqLf0RBZWSQSDbxkt6KcidGyWANaWYOIiPQP9qpWrSrdu3cP9u5EphDy0GUkgy9/slsNFPD9VU/vN8G6GRr8VhRXSXIr/DOqx0dEZKnl0jCH75FHHpEOHTqoeU2Ym9e8eXO57rrr5KOPPnIWYiYyy3q2o0atlvT0j6VFi4/UJa5jezDBV5mcqRLv2Kvmp+ES17Edt+vJn+xWQ8HKGlW+kKK4yi6hHo5XJK7opCSd+LvuzxERkRmFHOy9+eab0qVLF/nPf/6jgr6srCxVePnw4cMqieO+++6TK6+8Uo4cOaLPERNFEQK6Hj3mqfpye/dmy6FDOeoS17E9kIAv0sFXadmt8WcWiNEknn5VBXbufaeGDVCJiMwW7H3xxRcyZswY1XPXuHFjee6552TmzJmyaNEiFfwNGjRIlWz56aef5MYbbxSHt0VAiWLEuHFrStSVA1zHdpQh0bW0iF4w3Cy+V785dvSUZJ0yVsH0iD5HREQmFVKwN27cOHV56623qrVy0YvXo0cPVV4FQ7hTpkyRjIwMqVChgqxdu1bmz5+v13ETRcXChXs8rhgB2I56c3oFX+p2JG1EKLv1TG6cjH92rRiGH8/RkcOnZNSobwMfQicispCgg73du3fLzp071UoaL774onPtXHdt27aVe++9V/3+zTffBH+kRAZIxkDhYF9wO9oZsbQIEj8KCj0/XkFBnMxd0tL/YDUS/HiOcs/GydSpmwIeQicispKgg72DBw+qSxRVLleunM+2CPjg0CHvBVKJjA5Zt1ghwhfc7m92LoIvlBDxJBylRc4kjZHte2upwK7YcRTEyeadNWTsaz39D1YjxNdzpAWowQyhExFZSdDBnraSwMmTJ0ttq7UJ9+oDROHWq1cDtfarJ9iOpcICKS3iiG9WIpjBdYe9ueQmjxE9xcVXlGseHCVvftRZdu6vIvt/r6gucb3TjcMlOycxoGA1EtRzZE8r8Ry5BqgBD6ETEVlM0HX2mjVrJgkJCbJp0yZZt26dtGnTxmvbTz/9VF22aNEi2N0RGcLYsW1lxYqDJZI0EOg1b15FrQkbWG29PCmKK39ual5cBSmKK6t69FSgF4aad5d2bS4PT+gvDz7f/8+KdXFBB6sRK7+SslgST42Xwzs/F1tcvuQVxMu8JS1VoIcAVaP1ShopWCUiiulgLzk5WS2Thozcm266SSZMmCBXX311sTdaDPU+88wzsmTJErHb7SppgyiWJSeXkcWL+6khQ/QkIcBAbxiCJAR6uD2YwsaqNy++btgLGxcPVuOCC1YjzZYsuZUnyKW3Xyh796Kunudgzmi9kkREMR/swfjx4+WHH35QQd3gwYOlbt260rRpU0lKSpL9+/fL5s2b5ezZc6Uc/vWvf6nyLESxDgHdhAmd1E+gPUn+1NbLrTRBDBusRnkIHfUMPWVDG7JXkojIIOIyMzNDmo2NoO6hhx5SJVY8qVmzpjz55JOq948oFuXm5sq+ffvU6jChzjtNOpyuVsnwptBWX7JrrpdIiaVhT62gtbch9IyMfkEHq3qeYzIunmdr4HnWuWcP0Jv32Wefya5du2TVqlUq+MvLy1Nr56anp0vHjh2lTBnj9hYQRUwgtfUiFIDFSqAX672SREQxHexpGjVqpH6IyDi19cwmlCF0IiKrCnltXCLyX6Rr65kZAz0iIv8w2CMyQN24cNXWIyIiYrBHFIW6cXnlh6pkDIctVV3ienZKRljLrhARkTXpNmePiAKoG4fyKviJYDIGERFZE3v2iKKJgR4REYUZgz2yNGR0huFB9X9MIiKiSA/jbtmyRSZNmiTnnXee/POf/wz2YYiiUpx33Lg1snDhX7XasDoDlhILulZbsfVu81UJFWTeIiGD8/CIiCgme/aOHj0qn3zyiSxdulTfIyKKwCoMWHZr795sOXQoR13iOrbj9oD9ud5tmZypanUMm+OQusR1bMftREREMRfsVa9eXV2eOXNGz+MhCiv06LkvtwW4ju1YnSFQ/qx3S0REFHPBXlpamgr4Nm7cKNnZ2foeFVGYYOjWPdDTYDuW4QrUuaFbzw+K7fbcBQE/JhERUdSDPZvNJqNHj5bTp0/LyJEj1cLDREZPxsAcPV9we0BJG4Gsd0tERBRLCRqHDx+WpKQkad++vZq7t2rVKrnmmmukYcOGUqFCBY/3qVWrlnTt2jWU4yUKaXktJGP4gtsDWoaL692GjrUGiYiMGext3rxZhg0b5ry+f/9+ef31133eB4Eegz2KJmTdIhnD01CuzSbSu3eDgB8TWbe2nKkeh3K53q0XzF4mIjJ+sFe1alXp1q1bQPdJT08PdneSmZkpixcvlh9//FEKCgpk1KhRkpqaWqIdEkYef/xxr49z1113ScuWLT3eb968ebJhwwax2+3Stm1b6d27t8THx3t8nHC3p/BAeZUVKw6WSNJAoNe8eRUZM6ZtwI+J8ir2vBUlkjS43q3v7GX35wsBM55HLCfHcjVERAYI9hC4zZo1S8LN4XBIv3795Pvvv1dBnmbo0KEeg72zZ8/K+++/7/XxevbsWSLY27t3r/z973+XHTt2FNveoUMHmTlzpiQnJ0e0PYUP6ugtXtxPZd0iGUOrs4cePQR6QdXZ+3O9W2TdIhnjrzp7vSU3eQwDlyCyl9VyckREpIu4zMxMQ88cR4BXrVo1qVSpknTv3l02bdqkhpBXr14tLVq08NgDiHmDbdq0kVtvvbXE7T169JB69eo5r2MyPh537dq1qkD0DTfcIHl5efLBBx+ooenrr79e3nnnnYi1p8jC+Sltjh6Sj/bt26deN4mJiaU/Dueg+ZR0OF3VIfSm0FZfsmuul0jy5xxT7ON5tgaeZx179rw9wQi2EhISJCUlRZfHxDDnl19+KR07dlTDnzfddJMK9krTqFEjGTJkSKntli9frgKxZs2ayZIlS6R8+fJq++DBg9U+P/vsMxkzZowzQAx3e4qsgJIxIrESh9kFkr3MdYOJiIyxNm5+fr688cYbakgS2bbovXINsn7//Xe59957Zdy4cUF/GF966aUq0AuHRYsWqUscoxaIAf6WW265RfXYZGRkRKw9WXglDitg9jIRUWwFe0g66N+/v4wdO1atleupl6RmzZqycuVKeeWVV1TgFynY18svvyyPPvqo2jd61zzBsDAgWHWHnjfXNpFoT9ZdicMqkL2M5BVPmL1MRKS/kLrLnnnmGTV3DkOQ6N3DXLRBgwYVa4MAsE+fPmpe2tdff+3X0KoecFz4cdWrVy959913i9UBxBq/ULt27RKPoW3T2kSivTcsWh09eF27XsKCBbt9rsTx9de75emnL4raPMNoPJa/zpYZJVVyl4vdsa1E9nKBrZmcLPOIFEW4SLunc0zmw/NsDVY5z4HMLw462EPW6/Tp09UHxbRp0+Tiiy+WZcuWeWzbtGlTdfnzzz9LJJQtW1Zl3SJjGCt9oOcMZU8WLlwoDzzwgAr4NNqLoUyZMh4fR/tbI9Xem4MHD0phYWGp7Sh8UEhcC5Byc33PO8PtyMLWK5A6fbpA3n57l6xYcUwKCorEbo+Tyy6rJvfe20gqVPDn3xh5WHE6PVbo9ss7UqfM21LZvtKZvZxZcKkcyLtXHKdOiAh+oneOydx4nq3BzOc5Pj5eGjdu7Hf7oN/ZMWybk5OjEiEQ6Pmi9WBF4onHvLg1a9aUSHhAfburrrpKlYvB/EHtmMqVK+ccknadU6dtc20TifbeeOoZpMhAwI7XLqYkaEF7YiKGab1/a0xMTJD69euHvG8ElgjObrllgWzbdrJYb+LMmQfk55+zZf783pKUlFDivnFF2VIh53kpW5AhcUX5UhSXINlF3aXbXW3k5w1nA3qs8HhNMnHhkoxRR4xzjsl8eJ6tgedZx2AvOztbXeLNsTRa70YkhovwRu0ps/WCCy5QZVdmz56tAlUteMIlAsE9e/aUyCDGNnCt5xfu9t6wHET04bWlnYfevRv6XInjqqsaBn3O3LN8cT07+68akxqHo0gFgBMnbpAJEzp5KFzct3g9uyKR5MLpMn3c19LxhuGSnfPX8eHv8PpYOorGsHGw55jMi+fZGniedUjQwAoacODAgVLbagkI0e6dQk8kuGb2IgjUSqS4Q6kU95U/wt2eYgPKq6SlVVGBnatQVuLwluXrGugllc+VSY/NkZ2Ln5N9S8fL9kXPySUNXlTBnT+Fi+PjHXJeoyMybsS5LHFXCPhQaFpv+JtGjVot6ekfS4sWH6lLXGfGMhGRwYO95s2bS5UqVVQhUm+ZrlpiwYwZM9TvnTt3lnBDGRNPAejnn3+ulltDoOcaXPXt21ddvvXWW2qOlWbdunWqBh6+5WP+X6TaU2ytxDF0aEupXz9JUlPLq0tcz8joF3SdPW9Zvlqg993Hb8rwm1dLo7onpG6tU+pycL/lavkx14DPnrvQ41q96jZ7kfS7YqPH29CTiN43vbBEDRFRDA/jIvEBmbUob3L//ffLJ5984jGp4J577pFdu3ZJnTp1nIFPoN58803nUmO//vqrupw4caJUrlxZ/T5ixAi1aoYW1KHwcuvWrZ3bNm7cqIZuAQka2v3gwgsvVMuxIYGjS5cuaqgX4/0IDJE4MXLkSGcvZiTaU+xAQIchT/zoNTyJoVtvWb7jRyyU85sckfj44sGYPb5IilyXGfOjcHEZO5J9tMf567hRGFrPYVZ/StSEc9iYiIhCXC4NCQZXX321SohAjxmCq+3bt6t5fJg3t379ehXYYNwcc+UQ7AQDpVu+/fZbr7cjcGrXrp36HQkY48ePVwGmK5RbQWHjxx9/XAWqrrKysuSuu+5yFkDW3H777SqYRdZLJNuTNZfeQcCIYU4M3XqCoVv05PmzzFhpS5KdzCojx09WkAR7oeQXxMu8JS3kX2/0khtvvljX4AtDthiO9ga9oevX3yjRxuWVrIHn2Rp4nsOwNu7p06flX//6l/z3v//1WNMGw72vv/66tG/fPuh9oD6fr4LMCDirV69e7EMTSREIPBGQolexbdu2kpSU5HM/6AHE/RB8IXjUegaj1Z6s98bhPTgqUnP0MHTrjcOWKlk1NqnM1sSTo6RMzlSPQ7kYpcWP63eegoI42XUwVcqfv0qSKlaNSPAKGP7etOmmqCdt8MPBGnierYHnOQzBngaFgVesWKGGW/FEYz4fAiwEee49aUSxJJJvHEhc8JblG0jP3rls3B4lkjRKDtxKsaLGeeWHnhsK1gl79shIGARYA89zSbpVUEXP2sCBA/V6OCLLZvmuWHGwxDw3fF9a9XMbaVh3mefeOqw+kdjb5Q7Jkp2yWM3js+cucBYujis6LrYiz8OqeFy0ldKCPZe6eKXp1auBzxI1vXs38OtxiIgoeOxyI4qRLN8rrp8qDntaiXVlcd1hby65yWOKP5gtWfXSobcPw7vZNX4RiUv2uX+V2OEpG9eRpYaGMRcw+UgLdYnr7iVfIlWihoiIotCzh7IiWIt2//79KssUw7ioMdexY8dide2IyHdvma8s32xHyd469OipQM/2VyBXIjv4z9/R3hd1u3uvnZchYVvOVLHnrVA9iK779hS8IusWNfxQ2gUZv+jRQ6AXbIkaIiLyX8hRGFaBGDVqlKpv56k+F1aHGDNmjNx8882h7orIXNBbljXuz5p4WuDWS3KTxzqDpxKJC3/21qmhVrfhVPeVNxBUYRgVvWtaUIXHR5Dm11BwKQWacd3mWvIlgiVqiIgoQsHetm3b1HqzSM6Apk2bSpMmTSQ5OVlNaEfm6aFDh1QdPiRuIGuXKJboWWBYr94yJ7dADytvuM/1w3w5zAFE7xqCLgSSePySiRtehoJLKdDs9zw/5yEz0CMiiqk5eyhQjECvUaNGMmfOHFVv79NPP5WpU6eqmnII9u68807V9pVXXpEffvhBr+MmCp2XQM59ea927WbLSy9tk+zsfB12WeR3b5nexYtdEzeQdYvsXZRrwSWuZ6dklAww/SjQ7HWeHxERxXbPHnruvvvuO1VWBQFeWlpaiTYpKSmqaDBq5M2fP19mzpwZUr09Ik3Qw4GlDJ166yGbOfO0/PzzAvm//xsQ8DwzT8Oraz+bK9Uq6dNbVtrKG9qat85iyT6GgkseTFxw8/yIiCj2e/YQ7EGrVq08BnqutJIs2n2IguHe44ZLXMf2QIZOUWwYq0vYHIfUJa5ra8v66iHbtu3kXz1kARwzgkcMp6JYMgoM792bJbm5Z3TrLUPgiyDSF69r3voRpCEYds8ALm2eHxERmSDYq1ixorosV65cqW21QrTafYgC5TloylbXsd2fgM+foVN/esgC4Tl4jJP8/HjdesvQw4neQl9CWfMWvZ4BlXwhIiJzBHtYBg3lVTAvLzMz02dbrKwBnTpxwXMKjt9z0nzwJ9Eg6B4yL7wFj1iLFkuUBdJb5mu/yLr1tlBNyMWLA53nR0RE5gj2EhIS5NFHH5WcnBwZNmyY14APiRvvvvuuytS9/vrrQzlWsrCQe9z8TDRISIjTrYfM1/DqmNd6yZadNaSgMM5nb5m/Q9dhL17sXqC55vpz8/4Y6BERmSdB4/Dhw7Js2bJi29Czd8kll6jM2/T0dDU3r3Hjxqr0CoorL126VNauXStly5aVW265Rf73v/9J165dw/F3kIkFMifNPRBzTY5YOe2s1E/1sR9JkF69Guq2vJev4dXsnETpeONweW3MErlt4A6PBZL9LacS8eLFTMYgIjJnsLd582bVg+fNqVOn5P333/d4G1bUeOqpp1Sgx2CPAhXsnDT3YOmLxefL/TetFru9yOvQqa+1aZs1qxRwD5mvtWFzchPlxz2PyMCanTxmxfozdO3MsGXxYiIiCjXYq1q1qnTr1k1Cgd4/omD4Cpq89bi5B0sYOu3WYbuc1/hIsYDPdeg02Vayh8xuj5NOnSrLs89eGnAPma/gsdjwqofesoDKqbhh8WIiItLEZWZmshoqGZ63IU0taMrI+GtIU4P5bcjYdZVUPlfGjVgk/a7YKOXKFkmNmhU9ri2rwdAweqZRNqhevXrOzPJAjz3Q4VXsF3P0kHXsTWpqedm06SYV2HEZstDk5uaGdI4pNvA8WwPPc0kM9ihmBBI0+RcslZNNm24utRdMzzeOQIIyT8Gqq7p1K8hVVzX0uRYu+YcfDtbA82wNPM86r41LFEkIYDBsiZ/Sgib/5vnFR3y4M5D9+Rq6xsOcPl1Q4nZPyRtERGRtIQd7hYWFsmTJEvn+++9Vxm5envfitueff748+OCDoe6SyK+gKZh5fkppS4hFiK/5fpUqlZGTJ8/6nbxBRETWFVKwt3fvXrnxxhtl48aNfrVHJi6DPYoUv5MjSlszt5S1YcPFVzmV+fN3y4kTeUElbxARkbWEFOzdcccdKtArU6aM9OvXT62Rm5SU5LV93bp1Q9kdUUD8rj3355q57kup2XKmij1vhZxN+spQQ9e4nDdvV1B1B4mIyHqCDva2b9+uCibHx8fLvHnzpEOHDvoeGVGE5vmVtmZuhZwXRMR7jclI0Y493GvhEhGRuQS9XNqRI0eca+Qy0KNY4C34KW3N3LIFi8RowroWLhERmUrQwV7NmjXVJXr2iGKWP2vmFuF2Y5WjDPtauEREZBpBB3tNmjSRpk2bytatW+WPP/7Q96iIIgVz4EpJwCiKw+1xhpyPOHRoS6lfP0kVWMYlrnsqME1ERNYVdLAHL7zwguTn58s//vEPyc72XvyVyMiQdYsl0zzB9rP2nsW3oTRLiPR4DG0+4vr1N6qVNHCJ6wz0iIhIt2zc7t27y4cffihDhgyRtm3byuWXX65WGbB5mUzUsGFDVaqFyEhQXgVZt+5JGgWFcbJjX015fW536dsvVyZP/lEWLz4Q9GoVWAEE6/WGY8ULJmMQEVFYlks7fvy43HbbbbJy5Uq/6+zNnTs32N0RhY8jS2x/PCMnD8wWKcqXvIJ4mbekpYx9raecPpModnucFBYWlajXh3lz/qxW4WttX38fg8KHyytZA8+zNfA869yzN3ToUGegd/HFF5daZ69Zs2ah7I5INyXKsNiSZeTEv8vUqWnicBSVmKOXn1/yO1Egq1WgR8890Av0MYiIiCIa7B04cEC++eYb9fvUqVPl2muvDfahiCKitGFUbD8XjPmfjOHvahV/PXbwj0FERBTRYA9LpQEychnokdF5G0bF2rlYUi0j42oVAAajtNUqcFtpj80VL4iIyHDZuBUrVix2SRTOzNNQlTaM+uyza0tdlSLY1Sq44gUREcVksHfeeedJtWrV5LfffpOcnBx9j4pM0ZM2atRqSU//WFq0+Ehd4jq2R4M/w6i+VqXwVlTZ39UquOIFERHFXLCHlTOeeOIJOX36tDz++OPi8PZJSpYdMsUQ6d692XLoUI7s3ZulrmN7pAM+f4dRx4y5uNiqFEnlc2XSY3Nk5+LnZN+y8eoS17E90NUquOIFERHF3Jy9w4cPS/ny5dW6uNOmTZOffvpJ+vTpI/Xr1/daZ69WrVqq/AqZmzZkWj4xV8aPWCj9rtgkCfZCyS+Ily+XtpCJEyrLM+O7R+x4/B1GrVixrCqBgszYFct+k9mvviXN6v8u8fF/9erdf9Nq6dZhu3S8cbjYy1SU2bN7+1UyRVvxAo+NXkQtQQS9gggWWXaFiIgMV2dv2bJlMmDAgIDuwzp71oAh2+PHjsl3H78p5zc5UixYKiiIkx37a0mt9j+qcieRgiFk9Cx66oDGdxMsM+aaDZt4cpSUyZlarMiy69/w5ked5eEJ/Uvcz1++Ejoo8liXyxp4nq2B51nHnr2qVatKt27dArpPenp6sLujGKENmaJHzz3QA7u9SJrU+10KT42X3MoTInZcGEZF1q2nosaehmLtuQs9BnrqNnuR9Ltiozz4fP+gS6Yw0CMiIsMHewjcZs2ape/RUMzThkwxdOse6Gns8UUSd3aBiEQu2AtoGBW9bpLv8/HK2AtV0gZLphARkalX0CDypFev+pKQgGDIOxVMoSRLBIcyEdChFw4/PodR4+KkSBJ8PhbmH+KvKK3sChERUcxm4xJ5M3ZsO6Q8+HyCVDAVxSCptACtILGXFHn598CcvblLWqrD96fsChERUTQx2KOw9KBVqvN3KSz0/PJCEFWQ2NuwxZxxv9zkseKwp5UI+BDobd5ZQ8a+1lP16v3zn611OloiIiKDDeNu3LhRJkwIbM5Vy5Yt5dFHHw12lxRDHClPivyxSooKthZLdEDw5LA3l9zkMVFZ/zaQ+/W/erz07TBdmtVapUrH5BXEy7wlLVWgl52TKDabQyZN+oVr2hIRkTmDvaNHj8q8efMCus/JkyeD3R3FGluyZKcslsSs8WLPXaDm6GHoFj16KtALQ9mV0ta/RYKGp4DP2/3+/Xa2vP1OVykouOzPFTTiPK68EUw2LhERkeGDvebNm8vrr7/uM7D7+eef5YsvvpAyZcrIY489Ji1atAh2dxSLbMmSW2mCCH4ikIxR2vq3yMT1FJj5up/DoQ0Fez52ZuMSEZFpg73U1FQZPHhwqe3uvPNO6d+/v+oFHD58eLC7o1gXgWQMf9a/9RTs+bpfaZiNS0REYvUEjU6dOsntt98ua9euZV0+Cltihb/r37o/tj/38wYFmZmNS0RERheRbNxLLrlEXS5ZsiQSu6MYhHlzWNIMS621aPGRusR1bNdz/Vv3kiv+3M9uj1OBnStvK28QERFZMtjTPmD/+OOPSOyOYoyWIIFEir17s+XQoRx1ievY7m/Ah6xb96DMn1644vcr3vOH7Tff3FSuu66O1KtXQVJTy0v9+klqTdyMDM8JH0RERJZbQePLL79Ul9WrVw/pcTDktmvXLikoKJCGDRuqxA9fHA6HHDp0SOx2u9SoUaPUQrpGa28VwSZWuEJAmJdXKDZbnEtShX+9cP8ac550bvaSXHrhOlViBatjzFvSQv71Ri+pUy9Vxo69WE6c+F3q1asnZcuW5XkjIiJrBHtZWVmyfft2r7cXFhbKgQMH1Dw9rURLnz59gtrX/PnzZeHChbJo0SI5cuSI2rZ69Wqv2b0ICt98802VLYwSMVC/fn158sknZeDAgYZvbzXBJlaUVjoFMER7661p8vTT7T33wjmypNbZq+TWvsXrAd5/82q59qr9Ig2Wir1Mgpw4cW47A3QiIrJMsIeEiwEDBvjd/tZbbw0q2EMv3s033+z8oE1MTJTc3Fyf90Gx5xdeeEH9XrNmTcnPz5e9e/eqzGBwD7CM1t5KAkms8BZoeesZhMJCFEiO9zrcmpg1TmxuhZ/BHl8ktavtk7yiCZIpTwfyJxEREZljzl65cuWkUaNGXn+aNGkirVu3lkGDBslnn30mb7zxRlD7wQf8VVddpXrFtmzZIldccYXP9uhNfOWVVyQhIUFmzJghv/32m+zYsUMmTpyobn/88cfl7Nmzhm1vNcEmVgTaM+iNPXdhiUDPeWziUAWhiYiILNmz1759e1m3bp2EW3x8vHz00Ud+t0cR57y8PLn77rudPYkIFIYOHSoZGRmyePFiWbp0qfTq1cuQ7a0ICRJIxvAUsJVW3iSknkFsk3yf91W3B7nGLhERkWWycSNpzZo16tLTkPHVV19drI0R21sR1q1NS6sSVHmTkHoG4+LUEm6+qNuZSENERDEsItm4kbRnz7khu7S0tBK3adt2795t2PbelDZPMZYlJIh89VVPeeGFdbJo0X7VE4cArWfPujJ6dBtJSHD4/Pt79Kgj77//m9eewSuvrOP1/nZ7Dymf977HodwisUmu/UrVMwvaJZkPz7E18Dxbg1XOc2Jiov7B3pkzZ1TZkFBgnh+WWQun06dPq8uKFSuWuK1SpUrOTGKjtvfm4MGDKsPZzIYNS1U/rkOuKHmiZcJ6c+ut1WXp0n2ye3dOsYAPgV7DhuXllluqy759+zze1ya3yvnllkpZ226xxf11Z0eRTc46Gspvx28RhxxW2w4fPndJ5sVzbA08z9Zg5vMcHx8vjRs31j/Y++GHHwLKvvWka9euMnfuXAkn259jgahp5ymzF1Dnzqjtvaldu3apbawsI6Ou157BpCTfQ7VZRRniyHlByhYskriifCmKS5Cz9p5yuvxoqROXpL4d4k0DmdSl1Xak2MRzbA08z9bA82yBYdzKlSury2PHjklycnKx27QVPLQ2RmyvR3etFeH5eemly+Sll84lbQRWDy9RCsq9JAWi7uyco1fWrRUCPZ4Hc+M5tgaeZ2vgeQ4iQaNLly5qblkgP1999ZV07Njxr515W8tKR82aNVOXv/zyS4nbfv755xLz54zWnkIXUuFjJmMQEZHJ+B19YagRPVD+/KDH6uGHH1bZpt99951aYgqlR6ZMmRLev0ZELrvsMnU5ffr0Et26qHOnDScbtT0RERGRYYdx9+/fLy+++KKqi4f5aJhAeMMNN8jo0aPVuqLBwuR6JIi4Jjwgy1Wb64alx7Thtb59+6okENSuu++++2TIkCEqsJo0aZJs27ZN2rVrJxdeeKHzsY3WnoiIiEhPcZmZmSFXjMV8tJdfflnee+89tRoEhtGQzPHEE09I06ZNQz5I1Kj79ttvvd6OwsQImjTLli2T66+/vsTKFFWqVFHr67oPmxqtPRkLyrbgCwe+sHDOnjnxHFsDz7M18Dzr3LN38uRJtQza5MmTJTs7W2278sorZcyYMZKeni56qVu3rnPumyfuH8CXX365CrD+/e9/y4YNG1QPI4LBESNGeMxqNVp7IiIioqj27OXk5Mg777wjr732mmRmZqptnTt3lrFjx0qHDh10OzgiI+C3RPPjObYGnmdr4HkOsWcPc82mTZumhmy1YoVt2rRRPXndunUL5KGIiIiIyEjB3vbt2+Xvf/+7cyWC8847Tx577DHp379/OI+PiIiIiCIR7CHTVgv0sPRXq1atZP78+erHX+eff748+OCDwR0pEREREUUmQePUqVPy+eefB3w/1JNjsEdERERkwGAPGbH33HNPSDvzlVFLRERERFEM9lAv74UXXgjDIRB5F/g6t0RERBS2FTSI9JCVlSfjxq2RhQv3SH6+QxISbNKrVwMZO7atJCeX4ZNMREQUAAZ7ZLhAr0ePebJ16wlxOP7aPnXqRlmx4qAsXtyPAR8REVEAbIE0Jgo39Oi5B3qA69g+fvwangQiIqIAMNgjQ8HQrXugp8H2BQv2RPqQiIiIYhqDPTJUMgbm6PmC29FOr/0RERGZHefskWEg6xbJGL7g9lCyc5n8QUREVsNgjwwDgZivbFubTaR37wYhPT6TP4iIyGo4jEuGoAVimzcf93g7OvOaN68iY8a0DXofTP4gIiIrYrBHhuAtENO0bFlVMjJCK7vC5A8iIrIiBntkCL4CMTh1yvcQr9GSP4iIiIyCwR5FXSQCsUgkfxARERkRgz2KukgFYlhyzdtDhJr8QUREZFQM9sgQEIgh4ApXFu6oUavl6693S3x8nMfHDzX5g4iIyKhYeoUMYezYtmrtW/ckjVADMW/lVsBuj5NatcpLnz4N1eOHMieQiIjIqNizR4aAQGvx4n4ydGhLqV8/SVJTy6tLXA8lC9dXlq/DUaQCvQkTOjHQIyIi02LPHhkGAjoEXvhBMoYeyRL+lFvB/oiIiMyKPXtkSHoEeiy3QkRExGCPTIzlVoiIiBjsUZR5qp2nZ2HjcGb5EhERxQLO2aOIQ4YsEicwnw7FklFD74or6qoaeN98s9+5DYEasnRDyZINV5YvERFRrGCwRxHlrRTKtGlbSrSdOnWjCtSQpRtswKdl+Y4fv0YlY2iBJHr0WG6FiIisgMEeRZSvUiju0AZtEagFmjHrms0bjixfIiKiWMFsXIooX6VQfJVHCWSljPT0j6VFi4/UJa5ju4aBHhERWQ179ihi/CmF4gnuU1qPnLfhYT2GgomIiGIZe/bIUKVQPMF9SuuR8zY87DoUTEREZEUM9iiifJVCCaU8ij8rZRAREVkRgz2KKJRCSUur4lfA5295FK6UQURE5B3n7FFEeSuF0q3buTp7//d/+wMuj8KVMoiIiLxjsEcRV1oplGDKo2B4GMkYnoZyuVIGERFZGYdxKao8BXXBlEfxNjzMlTKIiMjqGOxZmJ5r0BpleHjo0JZSv36SpKaWV5e4npHBsitERGRdHMa1GE/r0uqxBq0RcKUMIiKikhjsWYiVCg9zpQwiIqJzOIxrISw8TEREZD0M9iyEhYeJiIish8GeRbDwMBERkTUx2LMIFh4mIiKyJgZ7FuJrXVoWHiYiIjInBnsWwsLDRERE1sNgz0JYeJiIiMh6WGfPYlh4mIiIyFrYs2dhLDxMRERkfqbr2Tt9+rQMGTLE6+2PPvqoXHTRRSW2Hzt2TP773//Khg0bxG63S9u2beXmm2+WChUqeHyccLcnIiIi0kNcZmZmkZhIZmamNGzY0Ovtn3zyifTq1avYtl9//VUGDBigAjJXTZs2la+//lpq1KgR0fZkLLm5ubJv3z6pV6+eJCYmRvtwKAx4jq2B59kaeJ4t0LOn6dixo4wYMaLE9osvvrjY9cLCQtUTiECsS5cuMnjwYMnLy5PJkyerIO0f//iHfPrppxFrT0RERKQn0wZ7qampJXrwPMnIyJCtW7fKhRdeKHPmzFFDrHD11VdLhw4dZNGiRbJt2zZp1qxZRNoTERER6cnyCRrffPONeiLuvvtuZyAGlSpVkltuuUX9/n//938Ra09ERESkJ9P27O3atUsefvhhOXLkiNSsWVMuu+wy6dOnj8THxxdrt2XLFnWJhAl37dq1K9YmEu2JiIiI9GTaYG/dunXqRzN16lSVhfvZZ59JtWrVnNuPHz+uLhEQuqtVq1axNpFo72vCKUUH5li6XpL58BxbA8+zNVjlPCcGkDBoymAvJSVFrrvuOklPTxebzSabNm1SZU9++uknNZw6e/ZsZ9v8/Hx1mZCQUOJxtG2uL5hwt/fm4MGDKtmDoufw4cN8+k2O59gaeJ6twcznOT4+Xho3bmzdYC8pKUkFdZgT5+rOO++Uv/3tb7JkyRLZvXu3szxL+fLlnfX5tN812dnZ6tK1Fl6423tTu3ZtP/56CgcE43jTQO9smTJl+CSbEM+xNfA8WwPPswWCPSRBuAd60KBBA+nevbsaxt2+fbsz2KtTp4788ssvsnPnTqlevXqx+2Ab1K1b17kt3O29YX236EOgx/NgbjzH1sDzbA08zxbNxkWyBpQrV865rU2bNupy8eLFJdqjbIprm0i0JyIiItKT6YI9FCh2TczQ5s29/vrrsmzZMhXotW7d2nlb//791Rqx77zzjqxfv965HeVQUBevYsWKqkcwUu2JiIiI9GS6YVzUtRs2bJgqqqwN1aKo8R9//KF+f+yxx9S8Pk1aWprcdtttMm3aNLniiitUORSM92PeX1FRkVpLNzk5OWLtyZjcS/aQ+fAcWwPPszXwPJt8bVwkYEycOFG+++67Ytsxd27kyJFyxx13lLgPgi8EXcjYLSgoUNswN+uhhx6SUaNGRbw9ERERkV5MF+xpsBYtEjFQnw6ZrFiODMOppd0HZVrwjeCCCy5QQ6zRbE9EREQUKtMGe0RERERkwgQNIiIiIvoLgz0iIiIiE2OwR0RERGRiDPaIiIiITMx0dfaIfGVDL1q0SH799Vex2Wzy7LPP+nyyMjMz5auvvpIdO3ao9YuxtvLFF1+sW3vSH5771atXy549e1T2fYsWLaRnz54l1qV2tW3bNlm4cKGqxYkSTX379lV1OvVqT/rDOUB5LaxznpCQIOnp6dKjRw+va1ejpimK6v/www+qyH6rVq2kd+/eXpc/DLQ9hd+UKVPUEqP169eX++67z2ObU6dOqfdgvD7wP9+1a1e55JJLvD5moO1jGbNxyfT27dsnd911l/zvf/8Th8OhtqH8jVZo2xO0vfnmm51L7GlQp/GVV14pUcYn0PakfyB//fXXy9q1a0vchjWpp06dqt7I3U2aNEnGjRsnhYWFzm0I1CdPnixXX311yO1JX6dPn5YBAwao/zdP659/+OGHqqyVq5ycHPW/uXTp0mLbUfB+1qxZUq9evZDaU/itXLnS+f/Vtm1btQKVu59//lluvPFGOXToULHtN910k7z55pvqC34o7WMdgz0yPSyfh162atWqqW//CxYskKysLK/BHm5DjxwCN3zL69Wrl/z+++8yY8YM9WHzwgsvyD333BN0e9IfvvFfdNFF0rRpU+nQoYP64M/OzpYvvvhC9u7dq1apQSBYo0aNYmtTDxo0SL2p33DDDerDHD05eH2gB+f77793rsITTHvSH/5nmzRpogI6rEaEwAuB/ty5c2X//v2q1wfnGb19mhEjRsj06dNV0I8gDj04CNp+++039X+LwMH1y1ig7Sm8zp49K507d1b/W3juPQV7CNDxejhw4IA6R1dddZV6XSD4x/vz008/rc5rsO3NgMEemR7+iTG8h39ufFDjg+LgwYNeg7233npLHn/8cRUYYq1l7Rsehgf79OmjAobNmzc7twfanvSH4RgMxbgPm585c0YN42JdaqyPPXjwYOdtCMoRoLlvHz16tOqpu/POO+Xll18Ouj3pD0XycZ7de+8Q2KPnFv/nGGJHwA+HDx9WQ/kI2NA7pAXj+LDHF0AEcLNnz1ZLWQbTnsJv/Pjx8v7776svVfgy7SnYe++999SKVJdddpn6gqctlbZmzRq58sorpVKlSmrZVO1LQKDtzYCfPmR66NFr376938EWPizg4YcfLnafTp06SZcuXdQHAtY2DrY96Q+r0XiaH1muXDm57rrr1O8nT550bj9x4oTqlcPqOrfcckux+2BZRZxH7bwG057CAz2o7oEeYL1zLcBDT5Bm8eLFasgdrwHXXlcEc8OHD1e/I4gItj2FF74kv/baa/L8889LSkqK13au78Gua+IiMOzWrZvz/zfY9mbAYI/IDZa0wzc6/OO7w3ACbNy4Mej2FFkY3gPXYBDnDJPw0VPg/iUAXw7OO+88NcSDpJtg2lNk4cMZPXEYrm/durVzO84bdOzYscR98EXM0/9yIO0pfPD/9s9//lMuv/xyNX3CF5w3/F/iS72/79m2ANqbAbNxidzeYLQsS7u95L8HtoOWiBFoe4osDLt98MEH6gMDPa2ao0ePFjs/7rAdHwg4b5UrVw64PYUX5lUhmx4JVzg3S5YsUT16GE53ff59nTdtm9YmmPYUPhhqRcCFrOvS4P8OPX+esqU9nbcjAbY3AwZ7RG5zghDAlS1b1uPzor05aENFgbanyEGWHXoE8Kb+zjvvFLsN5w28nTdtu9Yu0PYUXphDh8BOg571xx57TE20d+XrvKFMCxItXM9ZoO0pPJDghiSJMWPGlJr9jPffvLw8v/83iwJsbxYM9ojcgjNfb+iY8K/NBQumPUUG6q+hRAfmX6GOVs2aNYvdrp0P7fy407Zr9fkCbU/hheHa5557TvXsIQELZVKeeeYZmT9/vnz99dfOD2xf5037ouZ6zgJtT+HxyCOPSPPmzeXuu+8utS3ef3G+S/vfLPfnuQ20vVkw2CNygTeCWrVqqW+W6I1z//aHYr2ANsG0p/DDcOo111yjensQ6Hkqh6IVQUZZFk+086YFiYG2p/BCwOVaWPepp56SBx98UGVtYth+6NChpZ43T/+bgbYn/X377bfy5Zdfqix6VDnQaKMjqJuKDPjGjRs7g0GcN3zBQ1Y2knU8nbdUl8LngbY3AyZoELlBth96hPCm4w5V9bU2wban8EEGHYbyEHSjl8db3TskVGCOJUqpYEjHFT5Mtm/fLo0aNVI9SMG0p8hDyQzYsmWLc5v2f7d8+XK//5cDaU/6wxdnwGpHGKrXfhDIA6ob4DpqK7qftxUrVvh13i4IsL0ZMNgjcoPaeIBhIteu/jlz5qiCrQggsDxTsO0pPL755hv5+9//LlWrVlVDeSiw66tUC2psIbnm1VdfdW7HsCB6icB1RYxA21N4YOWMXbt2eRxi1YIB1x6Z7t27q6kWqKWG4uoaTL5/4403Spy3QNuT/pBNjfdS9x/M3wPM4cN11yFe7T0YBexRyF6DMjmod1q7du1i2fiBtjcDFlUmS8BkXy0Qw8oW6L4fNmxYscKdWjYthgtQegGrMmAlBhRTxbdJrKCAHrz//Oc/ztptwbQn/aEAKkpjoNcNc/U8DbWhpILrB/WPP/6o1jvFOcJ9sSIGgokNGzaojE7c7rriRqDtSX8TJ05UNdewWorWk4rMSpRdQR1FBOXI3nTNpsVcPixZiDlYOH8YAkavEQI4FEKfOXNmsX0E2p4iu3qKp6LKBQUF6n8Svbp169ZVQTvOF84bbnvzzTeL1ccMtL0ZMNgjS0AvD1ZZ8DV04JqGj2E5/LO7DgkhGMQcElRedxdoe9IXPuDxwewLlqzDN3lXn332mZrr5frtHoHitGnTnEV6Q2lP+sLwKrJutXp4rjDsht63Cy+8sNh2BOeo1/bf//632HZ82GN5LPdSOYG2p+gHe4A5eFjezrU+HmrpIdnjscceC7l9rGOwR5bw7rvv+ix/gl4+10rq2pv+qlWr1BJMWOwew3i+Ju0G2p70LbOCoTdfMJSuFcZ1hULImKej1UtETT5P9beCbU/6wwc0aijiHCD4atWqlZx//vk+74MvZJjTmZ+fr9p7KoIeSnsKLwzVo/YevlwhAcsTTKvA3GksqYceWfy/o+fOm0DbxzIGe0REREQmxgQNIiIiIhNjsEdERERkYgz2iIiIiEyMwR4RERGRiTHYIyIiIjIxBntEREREJsZgj4iIiMjEGOwRERERmRiDPSIiIiITO7fyOxEV8/XXX8uCBQvU71iG6b777vP6DP3jH/9Ql1hTEWvwGhnWcF27dq1cd911ajk3K8Df+80336j1j7H0VaNGjWJ2veKZM2fKihUrpG/fvtKzZ8+w72/9+vXyn//8R61JivVizfJ3WeF/56OPPlJrRvfr10969OgR7cOhKGPPHpEHv/zyi1oIHT9jx45Vayd6o7XDOp1Ghw9UHOuWLVvECt544w3p1q2bPPfcc2pdTfztCORj1Y8//qj+BgRhkbB37161v4ULF5rq77LC/w4CPRzvr7/+Gu1DIQNgzx5RKQoLC+XZZ59V3+wpdpw+fVrGjRunfr/pppvkoosukjJlyki1atWifWhERBHFYI/Ih+bNm8uOHTtk7ty5qrevdevWfL5iBHpj8/Ly1ND6W2+9JWaAIcQLLrhALrzwQjETs/5dREbBYI/Ih4YNG0r79u3lgw8+kPHjx6u5Rf6aOHGiGgYbPny4Chrd/fzzz/Luu++q29DG1/yglStXqmGkzMxMqVu3rgwcOFBdajZv3qyGJzEvLSUlRfr376/mGpZm+fLl6rHxuLVr11b3w/wsX4qKitSxYJjo2LFjUr58eRUEX3XVVVKuXLkS7d3/lu+//17t98iRI3LeeefJ0KFDxR9ZWVlqOHHDhg2Sk5MjNWvWlMsvv1zatWtXrN3u3bvl5ZdflsOHD6vrp06dcs6rhAcffFAaN27sc1/ux2yU52nPnj3yv//9T/3t6enpQT9H7vbv3y9ffPGFer0mJydLhw4d1PB3aU6cOKFed3j95ebmSq1atdTzgnl3+Hv95e3vcn9OMNyL+Zd4PtFD27t375ACRJyjb7/9Vp0jPM8VK1ZUx49zVLlyZZ/3DfRYCgoKZNWqVWpYFc+3zWZTr0Pcr06dOrq9Do8fPy5PPvmkev3Al19+KTt37nTe7mkOcrT+pylyGOwRleLRRx+VTz/9VBYvXqzeDDt27OjXczZ//nwV0CEw8xTs4QMOc2q6du1aItjDG+/s2bMlLS1N/v3vf8uiRYuK3a7NQcMHxeOPPy6TJ08uEWi+9tprcsstt3g8Nnww440af5P74+KDwjU4cvXbb7/JnXfe6XEeUGpqqkydOlU6d+7s8W9p1qxZib+lV69efn0wIIDBc4QPIlcYXsfkcyQRaB/OR48eVc+rBh+MrtcxpFtasOd6zJj3Z5TnSZvbht5K90SGQJ4jVzNmzJCRI0fKmTNnim1HgHjrrbd6fY4QRNx///0qmHaHoOmdd95Rr09/ePu7tOcE/z8IMPC7qwkTJsjDDz+s5tUGCgEqnlNP56hChQqqNxjBlDv0Fg8ZMiSgY8F7wYgRI0qcG8D/7xNPPKFu1+N1iIDf9fX+008/qR8NgnjXYC9a/9MUWQz2iEqBb914c3/77bfVHLBITvB/6aWX5OTJk3L11VerD1/01nz88ccqUMQH7Q033KACPQSMXbp0kfj4eNVDg54dfID/7W9/89hrgJ4vPG737t3liiuuUL0OX331lfrQxYcVemgQDLrCPvFGjt4c9Crig7BevXoqMQUfZps2bZJBgwbJ0qVLVZDqbZ94jEsvvVT1ILn2TnqDXgMErThGZNJef/31qvcSw+paEI7nAceAvx9tXn/9dTWMiw9IfGA99thjzscrrUcuFp+nQJ8jzbJly1SAiJ6dli1bqi8mCHTQ2zVv3jzZunWrx/2hB2fYsGHq9YjhV/QAVa9eXQXamPaAwHPXrl2i5/8BgnYErehpt9vtKlv+hx9+UM8Xei/xXPkLx4igEoEqnt9rr71W9UhhnideN/gfd+0NC/VY8Fh4bGTGNm3aVL1u8HrQetMQsDVo0EAGDBgQ8usQ5x2vf7xP4LHx3uGajev6fhCt/2mKPAZ7RH7AN3Z8W169erUauvFniEsPeCNFj4brhwA+ZDHEgg8cBHr4oMDQpAYf3uh9xAcavn176n3C46JHYdSoUc5taIefDz/8UMaMGaP2mZCQ4LwdpWXwofD3v/9d9dog2UEzevRo1VuAwAI9SdOnT/e4z1dffVXuuOOOgJ4D7BcfbvhgnTNnTrFhJQQ1+IBCsPPJJ5/IzTffrIbUBg8erIa7EOyhNwvXgxErz1Ogz5EGfxsCvSuvvFKV6kDgor3GcGyeepsAzy0CvTZt2qhAUrufBkEUhhP1gtc6epBcj/2BBx6Qa665RgWsOPZAgj2U3sExoscQzxe+ELhCYIaAVq9jQUkZvAYrVapUbDu+hKAHHv/DCCK9BXuBvA6TkpLUvjAsjmAPiUneXv/R+p+myGPpFSI/IIC455571O/o3cMHZCQgqHT/AKhSpYpzqAu9BO4fyHjDRg8NbNy40ePj4tu3e920uLg4efrpp1XPDua7oddBs2/fPsnIyJCyZcuqAMr1QwHQW/T888+r3/Hhj3p27jAX6/bbbw/o70fPAnoptSEr9/lD+FBFrwwgkNFbLDxPwT5HeG3gvpg7hg9z94Dttttu8zgvEHAfQG+U+/20YVzMd9ULestcgyvtGLTnCX+Hv9DjiPllgN5690APcG7RQ6rXseCx3AM910ARPWIYRvUWIAf6OvRHtP6nKTrYs0fkJ3yLRkIF5uFhiMvTfB69tW3b1uN2TM4GfGvXPnhdaUM1+ObtCYZ13N/ctSEgTM5H7+W6deucPZgYogJ8sLgOibrDBwd6fA4dOlSiwDTm/eADKhA4Bu3D7uKLL/bYBsHwZ5995myrp1h4noJ9jrTf0buFuVeeoEfKU+07TCnA34D/A/RKYaivRYsWAZ9ff11yySUet2vPnbfXuSfaOUIAhv+fSB0LviCidxVDrwcPHlRzJLUvjdrQOhJkqlatGvLr0B/R+p+m6GCwR+QnfDNHL9pTTz2lelAwF8ZToKUnvJl7og0bevpgAK23xeFweLzd10ofmLMDmH+lwRs9oOfBdfK3NxgG8/a4gdAKVfs6XvQuQXZ2tko8SUxMFL3EwvMU7HOk9SL5up+32xBYYr4WhgExDIkfDJdjGBnzyjB0jN49vXirjai9zlEL01/a+Qq25zGYY8GcPfSUaj2w3uD86PE69Ee0/qcpOhjsEQXg7rvvVvPkkMGGITFkdgYrUkPBnpw9e7bU21yH57Rv75ik7Z457ImnoTFPw32l0YJpT0NIrtmRGtfkA6s8T8E+R9qx+vobXe/nDgkhmE6AOW8oKbJmzRqVlYmfF154QfUkeutpjCbt+cIcx0jAfhD8IvEDX86QzILpFwiGtXONTN4DBw54fU8I9HXoj2j9T1N08EwRBQD1p5CsgR4NfKBpc6F89b5hCMTbnJloQS260m5Dhp9Gy7BDL1KwyQ7B0D5gfGV2almT6HFxTZSwyvMU7HOkTQXw52/0Bhm4KLOhldpAQIN6lChCjmxxrdabkWjnCF/YEFyFexgSw6V4XhDcIbHFU3Y8gj09X4f+iNb/NEUHEzSIAoThGAyrYH6Npww1jTbEun37do+3Y55NtKC0BLIK3eFYtbk8mAvkOjcH3+LxwYDSLpGCYUF8GKM+GUpBePL+++8721rxeQr2OcLcM9wPwQJ65jz16iETMxCY+/fKK6+o37GGrKcafNGmnSNk26JWYLhhfh6gtI2nQA9z7dCrp+frELQ5ft56fKP1P03RwWCPKEB4E0WhZcC8JW+0VQumTJmiVrbQYE7Piy++qMo0RAs+hNFDiflbGkwsx5xEzPPDZHvXVRfQg6NlIKLMi5bN6OmDS88PDvQ+aDXCUHjWvYcDhW+1QAWFYa34PAX7HGG+FTJLASU9tBVHtNcoHstbEIK/a8mSJR6HQrU6lJjYjx+jQe8mhlUB59FTFiuSsFBmSQ9YFQSQ6OKeqYv9+PO6DfR1qL0WfWUqR+t/mqKDw7hEQUCBWhQuxVCQN3gjRRssjYRelE6dOqlv0ih0iyFcLFuEKv7RgB6YWbNmqQ80HBc+tPGhh5pbCGZRO8sdynPgwwnHj0xkFKFFbwXmQCEoQJCBXgzMSULdLr0gMMZ8MDw+eqawPBPKz2Cyu/b8Yf4Yis3qLVaep2CfI0xFQEIFAgLMr8P9UKcNvUUouIu/H0OQ7vB8YOgRSRnI5kWPFXoJ8f+grcSAoUEjBnuABCss94XeRxQ6RmFo/D8iQQK9ZSgmjSxjnPNQoeYlCnmj7iWKn6MUDhKvMOyOlS0wvIuA0DXY1uN1iP3g/GJOJeZWYtUYvP+4LpcWrf9pijwGe0RBwCR3FDnFkK6vuVTIckNSB97IsaoAYM4UVrdo1apV1GpUYY4VsvcmTZqkPkRcjxkFYz0NiSIIwEoB+KDEsCA+KPGjwYc9SsVoNf70gqxJTPpHLwY+7FyXjMIcSkwuRwFYKz9PwT5HCNTQa4PXKOb1ab1y+LC/6667VMDg6TWOHkEES+gN0oYRXfeHx0OhXyNn1uP/EceIRCsExa6ZsigWrUegp/2/Yx8IfhF4o0dUgx459Lzi/PgK9oJ5HWKYFucBy+ThHGnnyXW5tGj9T1PkxWVmZkYvJZDIoPBtF8MuGCLz1mOEyd1YkkgbyurTp4/HUikYesFEdZQ6QE8I5tag1wU9J/iwxBu263JGgG/t+FaNHkF82/Z2fPiW7mmRe/QiYMkr9+N3f1z0DOBDAPOBcBz4gPMnyQF/Ez7s8a0fgQHui94LbcgqkL8lEAhI8KGMpBdMSMdjok6YJxg6R9FYPOfovQmEtvYpeszwgWmU5wk12vBhfOGFF3oteBzIc6TBUKDWm4cCv/iAxzFiXiqmG9SoUUMtieUOQ4nozUPvNeaGIekDtetK25+/f1dpzwnOC+bdIWjBChbBwDlFryjmPGKeLc6PpyX1Qj0WvF9gVQucH/R4IiMXPYqA++H+WMnENdFCj9chzg3eL3AfnGf0wnqqxxet/2mKDAZ7RERu3D9kiaKBr0PSCxM0iIiIiEyMwR4RERGRiTHYIyIiIjIxztkjInLDCehkBHwdkl4Y7BERERGZGIdxiYiIiEyMwR4RERGRiTHYIyIiIjIxBntEREREJsZgj4iIiMjEGOwRERERmRiDPSIiIiITY7BHREREZGIM9oiIiIjEvP4fTUkeI5HiiHgAAAAASUVORK5CYII=" + } } ], "source": [ "plots.figure(figsize=(6, 6))\n", - "plots.scatter(chars_periods_huck_finn.column(1), \n", - " chars_periods_huck_finn.column(0), \n", + "plots.scatter(chars_periods_huck_finn.to_series(1),\n", + " chars_periods_huck_finn.to_series(0),\n", " color='darkblue')\n", - "plots.scatter(chars_periods_little_women.column(1), \n", - " chars_periods_little_women.column(0), \n", + "plots.scatter(chars_periods_little_women.to_series(1),\n", + " chars_periods_little_women.to_series(0),\n", " color='gold')\n", "plots.xlabel('Number of periods in chapter')\n", "plots.ylabel('Number of characters in chapter');" From ca3873112cf8c6319e5afd34f73761f5b20e012c Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 02:56:18 -0700 Subject: [PATCH 12/17] Ch. 3.4 to polars --- chapters/03/4/Introduction_to_Tables.ipynb | 1241 ++++++++------------ 1 file changed, 508 insertions(+), 733 deletions(-) diff --git a/chapters/03/4/Introduction_to_Tables.ipynb b/chapters/03/4/Introduction_to_Tables.ipynb index 20f978b2d..281e0e3e2 100644 --- a/chapters/03/4/Introduction_to_Tables.ipynb +++ b/chapters/03/4/Introduction_to_Tables.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Introduction to Tables\n" + "# Introduction to DataFrames\n" ] }, { @@ -17,31 +17,31 @@ }, "outputs": [], "source": [ - "from datascience import *\n", + "import polars as pl\n", "path_data = '../../../assets/data/'\n", - "import numpy as np\n", "%matplotlib inline\n", "import matplotlib.pyplot as plots\n", "plots.style.use('fivethirtyeight')\n", "\n", - "cones = Table.read_table(path_data + 'cones.csv')\n", - "nba = Table.read_table(path_data + 'nba_salaries.csv').relabeled(3, 'SALARY')\n", - "movies = Table.read_table(path_data + 'movies_by_year.csv')" + "cones = pl.read_csv(path_data + 'cones.csv')\n", + "nba = pl.read_csv(path_data + 'nba_salaries.csv').rename({\"'15-'16 SALARY\": \"SALARY\"})\n", + "# POLARS_CHANGE: movies_by_year.csv separates rows with carriage returns\n", + "movies = pl.read_csv(path_data + 'movies_by_year.csv', eol_char='\\r')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We can now apply Python to analyze data. We will work with data stored in Table structures.\n", + "We can now apply Python to analyze data. We will work with data stored in DataFrame structures.\n", "\n", - "Tables are a fundamental way of representing data sets. A table can be viewed in two ways:\n", + "DataFrames are a fundamental way of representing data sets. A DataFrame can be viewed in two ways:\n", "* a sequence of named columns that each describe a single attribute of all entries in a data set, or\n", "* a sequence of rows that each contain all information about a single individual in a data set.\n", "\n", - "We will study tables in great detail in the next several chapters. For now, we will just introduce a few methods without going into technical details. \n", + "We will study DataFrames in great detail in the next several chapters. For now, we will just introduce a few methods without going into technical details. \n", "\n", - "The table `cones` has been imported for us; later we will see how, but here we will just work with it. First, let's take a look at it." + "The DataFrame `cones` has been imported for us; later we will see how, but here we will just work with it. First, let's take a look at it." ] }, { @@ -50,49 +50,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 2, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Color Price
strawberry pink 3.55
chocolate light brown 4.75
chocolate dark brown 5.25
strawberry pink 5.25
chocolate dark brown 5.25
bubblegum pink 4.75
" - ], "text/plain": [ - "Flavor | Color | Price\n", - "strawberry | pink | 3.55\n", - "chocolate | light brown | 4.75\n", - "chocolate | dark brown | 5.25\n", - "strawberry | pink | 5.25\n", - "chocolate | dark brown | 5.25\n", - "bubblegum | pink | 4.75" + "shape: (6, 3)\n", + "┌────────────┬─────────────┬───────┐\n", + "│ Flavor ┆ Color ┆ Price │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ f64 │\n", + "╞════════════╪═════════════╪═══════╡\n", + "│ strawberry ┆ pink ┆ 3.55 │\n", + "│ chocolate ┆ light brown ┆ 4.75 │\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "│ strawberry ┆ pink ┆ 5.25 │\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "│ bubblegum ┆ pink ┆ 4.75 │\n", + "└────────────┴─────────────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (6, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
"bubblegum""pink"4.75
" ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -103,15 +90,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The table has six rows. Each row corresponds to one ice cream cone. The ice cream cones are the *individuals*.\n", + "The DataFrame has six rows. Each row corresponds to one ice cream cone. The ice cream cones are the *individuals*.\n", "\n", "Each cone has three attributes: flavor, color, and price. Each column contains the data on one of these attributes, and so all the entries of any single column are of the same kind. Each column has a label. We will refer to columns by their labels.\n", "\n", - "A table method is just like a function, but it must operate on a table. So the call looks like\n", + "A DataFrame method is just like a function, but it must operate on a DataFrame. So the call looks like\n", "\n", - "`name_of_table.method(arguments)`\n", + "`name_of_dataframe.method(arguments)`\n", "\n", - "For example, if you want to see just the first two rows of a table, you can use the table method `show`." + "For example, if you want to see just the first two rows of a DataFrame, you can use the DataFrame method `head`." ] }, { @@ -120,35 +107,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 3, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Color Price
strawberry pink 3.55
chocolate light brown 4.75
\n", - "

... (4 rows omitted)

" - ], "text/plain": [ - "" + "shape: (2, 3)\n", + "┌────────────┬─────────────┬───────┐\n", + "│ Flavor ┆ Color ┆ Price │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ f64 │\n", + "╞════════════╪═════════════╪═══════╡\n", + "│ strawberry ┆ pink ┆ 3.55 │\n", + "│ chocolate ┆ light brown ┆ 4.75 │\n", + "└────────────┴─────────────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (2, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
" ] - }, - "metadata": {}, - "output_type": "display_data" + } } ], "source": [ - "cones.show(2)" + "cones.head(2)" ] }, { @@ -163,7 +151,7 @@ "metadata": {}, "source": [ "## Choosing Sets of Columns\n", - "The method `select` creates a new table consisting of only the specified columns." + "The method `select` creates a new DataFrame consisting of only the specified columns." ] }, { @@ -172,49 +160,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 4, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor
strawberry
chocolate
chocolate
strawberry
chocolate
bubblegum
" - ], "text/plain": [ - "Flavor\n", - "strawberry\n", - "chocolate\n", - "chocolate\n", - "strawberry\n", - "chocolate\n", - "bubblegum" + "shape: (6, 1)\n", + "┌────────────┐\n", + "│ Flavor │\n", + "│ --- │\n", + "│ str │\n", + "╞════════════╡\n", + "│ strawberry │\n", + "│ chocolate │\n", + "│ chocolate │\n", + "│ strawberry │\n", + "│ chocolate │\n", + "│ bubblegum │\n", + "└────────────┘" + ], + "text/html": [ + "
\n", + "shape: (6, 1)
Flavor
str
"strawberry"
"chocolate"
"chocolate"
"strawberry"
"chocolate"
"bubblegum"
" ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -225,7 +200,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This leaves the original table unchanged." + "This leaves the original DataFrame unchanged." ] }, { @@ -234,49 +209,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 5, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Color Price
strawberry pink 3.55
chocolate light brown 4.75
chocolate dark brown 5.25
strawberry pink 5.25
chocolate dark brown 5.25
bubblegum pink 4.75
" - ], "text/plain": [ - "Flavor | Color | Price\n", - "strawberry | pink | 3.55\n", - "chocolate | light brown | 4.75\n", - "chocolate | dark brown | 5.25\n", - "strawberry | pink | 5.25\n", - "chocolate | dark brown | 5.25\n", - "bubblegum | pink | 4.75" + "shape: (6, 3)\n", + "┌────────────┬─────────────┬───────┐\n", + "│ Flavor ┆ Color ┆ Price │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ f64 │\n", + "╞════════════╪═════════════╪═══════╡\n", + "│ strawberry ┆ pink ┆ 3.55 │\n", + "│ chocolate ┆ light brown ┆ 4.75 │\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "│ strawberry ┆ pink ┆ 5.25 │\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "│ bubblegum ┆ pink ┆ 4.75 │\n", + "└────────────┴─────────────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (6, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
"bubblegum""pink"4.75
" ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -296,49 +258,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 6, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Price
strawberry 3.55
chocolate 4.75
chocolate 5.25
strawberry 5.25
chocolate 5.25
bubblegum 4.75
" - ], "text/plain": [ - "Flavor | Price\n", - "strawberry | 3.55\n", - "chocolate | 4.75\n", - "chocolate | 5.25\n", - "strawberry | 5.25\n", - "chocolate | 5.25\n", - "bubblegum | 4.75" + "shape: (6, 2)\n", + "┌────────────┬───────┐\n", + "│ Flavor ┆ Price │\n", + "│ --- ┆ --- │\n", + "│ str ┆ f64 │\n", + "╞════════════╪═══════╡\n", + "│ strawberry ┆ 3.55 │\n", + "│ chocolate ┆ 4.75 │\n", + "│ chocolate ┆ 5.25 │\n", + "│ strawberry ┆ 5.25 │\n", + "│ chocolate ┆ 5.25 │\n", + "│ bubblegum ┆ 4.75 │\n", + "└────────────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (6, 2)
FlavorPrice
strf64
"strawberry"3.55
"chocolate"4.75
"chocolate"5.25
"strawberry"5.25
"chocolate"5.25
"bubblegum"4.75
" ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -349,7 +298,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You can also *drop* columns you don't want. The table above can be created by dropping the `Color` column." + "You can also *drop* columns you don't want. The DataFrame above can be created by dropping the `Color` column." ] }, { @@ -358,49 +307,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 7, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Price
strawberry 3.55
chocolate 4.75
chocolate 5.25
strawberry 5.25
chocolate 5.25
bubblegum 4.75
" - ], "text/plain": [ - "Flavor | Price\n", - "strawberry | 3.55\n", - "chocolate | 4.75\n", - "chocolate | 5.25\n", - "strawberry | 5.25\n", - "chocolate | 5.25\n", - "bubblegum | 4.75" + "shape: (6, 2)\n", + "┌────────────┬───────┐\n", + "│ Flavor ┆ Price │\n", + "│ --- ┆ --- │\n", + "│ str ┆ f64 │\n", + "╞════════════╪═══════╡\n", + "│ strawberry ┆ 3.55 │\n", + "│ chocolate ┆ 4.75 │\n", + "│ chocolate ┆ 5.25 │\n", + "│ strawberry ┆ 5.25 │\n", + "│ chocolate ┆ 5.25 │\n", + "│ bubblegum ┆ 4.75 │\n", + "└────────────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (6, 2)
FlavorPrice
strf64
"strawberry"3.55
"chocolate"4.75
"chocolate"5.25
"strawberry"5.25
"chocolate"5.25
"bubblegum"4.75
" ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -411,7 +347,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You can name this new table and look at it again by just typing its name." + "You can name this new DataFrame and look at it again by just typing its name." ] }, { @@ -420,49 +356,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 8, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Price
strawberry 3.55
chocolate 4.75
chocolate 5.25
strawberry 5.25
chocolate 5.25
bubblegum 4.75
" - ], "text/plain": [ - "Flavor | Price\n", - "strawberry | 3.55\n", - "chocolate | 4.75\n", - "chocolate | 5.25\n", - "strawberry | 5.25\n", - "chocolate | 5.25\n", - "bubblegum | 4.75" + "shape: (6, 2)\n", + "┌────────────┬───────┐\n", + "│ Flavor ┆ Price │\n", + "│ --- ┆ --- │\n", + "│ str ┆ f64 │\n", + "╞════════════╪═══════╡\n", + "│ strawberry ┆ 3.55 │\n", + "│ chocolate ┆ 4.75 │\n", + "│ chocolate ┆ 5.25 │\n", + "│ strawberry ┆ 5.25 │\n", + "│ chocolate ┆ 5.25 │\n", + "│ bubblegum ┆ 4.75 │\n", + "└────────────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (6, 2)
FlavorPrice
strf64
"strawberry"3.55
"chocolate"4.75
"chocolate"5.25
"strawberry"5.25
"chocolate"5.25
"bubblegum"4.75
" ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -475,7 +398,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Like `select`, the `drop` method creates a smaller table and leaves the original table unchanged. In order to explore your data, you can create any number of smaller tables by using choosing or dropping columns. It will do no harm to your original data table." + "Like `select`, the `drop` method creates a smaller DataFrame and leaves the original DataFrame unchanged. In order to explore your data, you can create any number of smaller DataFrames by using choosing or dropping columns. It will do no harm to your original DataFrame." ] }, { @@ -489,7 +412,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The `sort` method creates a new table by arranging the rows of the original table in ascending order of the values in the specified column. Here the `cones` table has been sorted in ascending order of the price of the cones." + "The `sort` method creates a new DataFrame by arranging the rows of the original DataFrame in ascending order of the values in the specified column. Here the `cones` DataFrame has been sorted in ascending order of the price of the cones." ] }, { @@ -498,49 +421,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 9, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Color Price
strawberry pink 3.55
chocolate light brown 4.75
bubblegum pink 4.75
chocolate dark brown 5.25
strawberry pink 5.25
chocolate dark brown 5.25
" - ], "text/plain": [ - "Flavor | Color | Price\n", - "strawberry | pink | 3.55\n", - "chocolate | light brown | 4.75\n", - "bubblegum | pink | 4.75\n", - "chocolate | dark brown | 5.25\n", - "strawberry | pink | 5.25\n", - "chocolate | dark brown | 5.25" + "shape: (6, 3)\n", + "┌────────────┬─────────────┬───────┐\n", + "│ Flavor ┆ Color ┆ Price │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ f64 │\n", + "╞════════════╪═════════════╪═══════╡\n", + "│ strawberry ┆ pink ┆ 3.55 │\n", + "│ chocolate ┆ light brown ┆ 4.75 │\n", + "│ bubblegum ┆ pink ┆ 4.75 │\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "│ strawberry ┆ pink ┆ 5.25 │\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "└────────────┴─────────────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (6, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
"bubblegum""pink"4.75
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
" ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -562,49 +472,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 10, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Color Price
chocolate dark brown 5.25
strawberry pink 5.25
chocolate dark brown 5.25
bubblegum pink 4.75
chocolate light brown 4.75
strawberry pink 3.55
" - ], "text/plain": [ - "Flavor | Color | Price\n", - "chocolate | dark brown | 5.25\n", - "strawberry | pink | 5.25\n", - "chocolate | dark brown | 5.25\n", - "bubblegum | pink | 4.75\n", - "chocolate | light brown | 4.75\n", - "strawberry | pink | 3.55" + "shape: (6, 3)\n", + "┌────────────┬─────────────┬───────┐\n", + "│ Flavor ┆ Color ┆ Price │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ f64 │\n", + "╞════════════╪═════════════╪═══════╡\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "│ strawberry ┆ pink ┆ 5.25 │\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "│ chocolate ┆ light brown ┆ 4.75 │\n", + "│ bubblegum ┆ pink ┆ 4.75 │\n", + "│ strawberry ┆ pink ┆ 3.55 │\n", + "└────────────┴─────────────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (6, 3)
FlavorColorPrice
strstrf64
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
"chocolate""light brown"4.75
"bubblegum""pink"4.75
"strawberry""pink"3.55
" ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -615,7 +512,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Like `select` and `drop`, the `sort` method leaves the original table unchanged." + "Like `select` and `drop`, the `sort` method leaves the original DataFrame unchanged." ] }, { @@ -623,9 +520,9 @@ "metadata": {}, "source": [ "## Selecting Rows that Satisfy a Condition\n", - "The `where` method creates a new table consisting only of the rows that satisfy a given condition. In this section we will work with a very simple condition, which is that the value in a specified column must be equal to a value that we also specify. Thus the `where` method has two arguments.\n", + "The `filter` method creates a new DataFrame consisting only of the rows that satisfy a given condition. In this section we will work with a very simple condition, which is that the value in a specified column must be equal to a value that we also specify. The condition is the expression `pl.col('Flavor') == 'chocolate'`.\n", "\n", - "The code in the cell below creates a table consisting only of the rows corresponding to chocolate cones." + "The code in the cell below creates a DataFrame consisting only of the rows corresponding to chocolate cones." ] }, { @@ -634,50 +531,46 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 11, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Color Price
chocolate light brown 4.75
chocolate dark brown 5.25
chocolate dark brown 5.25
" - ], "text/plain": [ - "Flavor | Color | Price\n", - "chocolate | light brown | 4.75\n", - "chocolate | dark brown | 5.25\n", - "chocolate | dark brown | 5.25" + "shape: (3, 3)\n", + "┌───────────┬─────────────┬───────┐\n", + "│ Flavor ┆ Color ┆ Price │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ f64 │\n", + "╞═══════════╪═════════════╪═══════╡\n", + "│ chocolate ┆ light brown ┆ 4.75 │\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "│ chocolate ┆ dark brown ┆ 5.25 │\n", + "└───────────┴─────────────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (3, 3)
FlavorColorPrice
strstrf64
"chocolate""light brown"4.75
"chocolate""dark brown"5.25
"chocolate""dark brown"5.25
" ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "cones.where('Flavor', 'chocolate')" + "cones.filter(pl.col('Flavor') == 'chocolate')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The arguments, separated by a comma, are the label of the column and the value we are looking for in that column. The `where` method can also be used when the condition that the rows must satisfy is more complicated. In those situations the call will be a little more complicated as well.\n", + "The expression compares a column with the value we are looking for. The `filter` method can also be used when the condition that the rows must satisfy is more complicated. In those situations the call will be a little more complicated as well.\n", "\n", - "It is important to provide the value exactly. For example, if we specify `Chocolate` instead of `chocolate`, then `where` correctly finds no rows where the flavor is `Chocolate`." + "It is important to provide the value exactly. For example, if we specify `Chocolate` instead of `chocolate`, then `filter` correctly finds no rows where the flavor is `Chocolate`." ] }, { @@ -686,36 +579,41 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 12, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Flavor Color Price
" - ], "text/plain": [ - "Flavor | Color | Price" + "shape: (0, 3)\n", + "┌────────┬───────┬───────┐\n", + "│ Flavor ┆ Color ┆ Price │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ f64 │\n", + "╞════════╪═══════╪═══════╡\n", + "└────────┴───────┴───────┘" + ], + "text/html": [ + "
\n", + "shape: (0, 3)
FlavorColorPrice
strstrf64
" ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "cones.where('Flavor', 'Chocolate')" + "cones.filter(pl.col('Flavor') == 'Chocolate')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Like all the other table methods in this section, `where` leaves the original table unchanged." + "Like all the other DataFrame methods in this section, `filter` leaves the original DataFrame unchanged." ] }, { @@ -729,7 +627,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "\"The NBA is the highest paying professional sports league in the world,\" [reported CNN](http://edition.cnn.com/2015/12/04/sport/gallery/highest-paid-nba-players/) in March 2016. The table `nba` contains the [salaries of all National Basketball Association players](https://www.statcrunch.com/app/index.php?dataid=1843341) in 2015-2016.\n", + "\"The NBA is the highest paying professional sports league in the world,\" [reported CNN](http://edition.cnn.com/2015/12/04/sport/gallery/highest-paid-nba-players/) in March 2016. The DataFrame `nba` contains the [salaries of all National Basketball Association players](https://www.statcrunch.com/app/index.php?dataid=1843341) in 2015-2016.\n", "\n", "Each row represents one player. The columns are:\n", "\n", @@ -751,67 +649,41 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 13, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Paul Millsap PF Atlanta Hawks 18.6717
Al Horford C Atlanta Hawks 12
Tiago Splitter C Atlanta Hawks 9.75625
Jeff Teague PG Atlanta Hawks 8
Kyle Korver SG Atlanta Hawks 5.74648
Thabo Sefolosha SF Atlanta Hawks 4
Mike Scott PF Atlanta Hawks 3.33333
Kent Bazemore SF Atlanta Hawks 2
Dennis Schroder PG Atlanta Hawks 1.7634
Tim Hardaway Jr. SG Atlanta Hawks 1.30452
\n", - "

... (407 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Paul Millsap | PF | Atlanta Hawks | 18.6717\n", - "Al Horford | C | Atlanta Hawks | 12\n", - "Tiago Splitter | C | Atlanta Hawks | 9.75625\n", - "Jeff Teague | PG | Atlanta Hawks | 8\n", - "Kyle Korver | SG | Atlanta Hawks | 5.74648\n", - "Thabo Sefolosha | SF | Atlanta Hawks | 4\n", - "Mike Scott | PF | Atlanta Hawks | 3.33333\n", - "Kent Bazemore | SF | Atlanta Hawks | 2\n", - "Dennis Schroder | PG | Atlanta Hawks | 1.7634\n", - "Tim Hardaway Jr. | SG | Atlanta Hawks | 1.30452\n", - "... (407 rows omitted)" + "shape: (417, 4)\n", + "┌─────────────────┬──────────┬────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═════════════════╪══════════╪════════════════════╪═══════════╡\n", + "│ Paul Millsap ┆ PF ┆ Atlanta Hawks ┆ 18.671659 │\n", + "│ Al Horford ┆ C ┆ Atlanta Hawks ┆ 12.0 │\n", + "│ Tiago Splitter ┆ C ┆ Atlanta Hawks ┆ 9.75625 │\n", + "│ Jeff Teague ┆ PG ┆ Atlanta Hawks ┆ 8.0 │\n", + "│ Kyle Korver ┆ SG ┆ Atlanta Hawks ┆ 5.746479 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Gary Neal ┆ PG ┆ Washington Wizards ┆ 2.139 │\n", + "│ DeJuan Blair ┆ C ┆ Washington Wizards ┆ 2.0 │\n", + "│ Kelly Oubre Jr. ┆ SF ┆ Washington Wizards ┆ 1.92024 │\n", + "│ Garrett Temple ┆ SG ┆ Washington Wizards ┆ 1.100602 │\n", + "│ Jarell Eddie ┆ SG ┆ Washington Wizards ┆ 0.561716 │\n", + "└─────────────────┴──────────┴────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Tiago Splitter""C""Atlanta Hawks"9.75625
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
…………
"Gary Neal""PG""Washington Wizards"2.139
"DeJuan Blair""C""Washington Wizards"2.0
"Kelly Oubre Jr.""SF""Washington Wizards"1.92024
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -822,7 +694,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Fans of Stephen Curry can find his row by using `where`." + "Fans of Stephen Curry can find his row by using `filter`." ] }, { @@ -831,40 +703,42 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 14, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Stephen Curry PG Golden State Warriors 11.3708
" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Stephen Curry | PG | Golden State Warriors | 11.3708" + "shape: (1, 4)\n", + "┌───────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═══════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", + "└───────────────┴──────────┴───────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (1, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Stephen Curry""PG""Golden State Warriors"11.370786
" ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "nba.where('PLAYER', 'Stephen Curry')" + "nba.filter(pl.col('PLAYER') == 'Stephen Curry')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We can also create a new table called `warriors` consisting of just the data for the Golden State Warriors." + "We can also create a new DataFrame called `warriors` consisting of just the data for the Golden State Warriors." ] }, { @@ -873,71 +747,45 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 15, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Klay Thompson SG Golden State Warriors 15.501
Draymond Green PF Golden State Warriors 14.2609
Andrew Bogut C Golden State Warriors 13.8
Andre Iguodala SF Golden State Warriors 11.7105
Stephen Curry PG Golden State Warriors 11.3708
Jason Thompson PF Golden State Warriors 7.00847
Shaun Livingston PG Golden State Warriors 5.54373
Harrison Barnes SF Golden State Warriors 3.8734
Marreese Speights C Golden State Warriors 3.815
Leandro Barbosa SG Golden State Warriors 2.5
\n", - "

... (4 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Klay Thompson | SG | Golden State Warriors | 15.501\n", - "Draymond Green | PF | Golden State Warriors | 14.2609\n", - "Andrew Bogut | C | Golden State Warriors | 13.8\n", - "Andre Iguodala | SF | Golden State Warriors | 11.7105\n", - "Stephen Curry | PG | Golden State Warriors | 11.3708\n", - "Jason Thompson | PF | Golden State Warriors | 7.00847\n", - "Shaun Livingston | PG | Golden State Warriors | 5.54373\n", - "Harrison Barnes | SF | Golden State Warriors | 3.8734\n", - "Marreese Speights | C | Golden State Warriors | 3.815\n", - "Leandro Barbosa | SG | Golden State Warriors | 2.5\n", - "... (4 rows omitted)" + "shape: (14, 4)\n", + "┌──────────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞══════════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Klay Thompson ┆ SG ┆ Golden State Warriors ┆ 15.501 │\n", + "│ Draymond Green ┆ PF ┆ Golden State Warriors ┆ 14.26087 │\n", + "│ Andrew Bogut ┆ C ┆ Golden State Warriors ┆ 13.8 │\n", + "│ Andre Iguodala ┆ SF ┆ Golden State Warriors ┆ 11.710456 │\n", + "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Leandro Barbosa ┆ SG ┆ Golden State Warriors ┆ 2.5 │\n", + "│ Festus Ezeli ┆ C ┆ Golden State Warriors ┆ 2.008748 │\n", + "│ Brandon Rush ┆ SF ┆ Golden State Warriors ┆ 1.270964 │\n", + "│ Kevon Looney ┆ SF ┆ Golden State Warriors ┆ 1.13196 │\n", + "│ Anderson Varejao ┆ PF ┆ Golden State Warriors ┆ 0.289755 │\n", + "└──────────────────┴──────────┴───────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
…………
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "warriors = nba.where('TEAM', 'Golden State Warriors')\n", + "warriors = nba.filter(pl.col('TEAM') == 'Golden State Warriors')\n", "warriors" ] }, @@ -945,7 +793,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "By default, the first 10 lines of a table are displayed. You can use `show` to display more or fewer. To display the entire table, use `show` with no argument in the parentheses." + "By default, the display shows the first five and last five rows. `pl.Config(tbl_rows=-1)` makes `display` show every row." ] }, { @@ -954,77 +802,56 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 16, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Klay Thompson SG Golden State Warriors 15.501
Draymond Green PF Golden State Warriors 14.2609
Andrew Bogut C Golden State Warriors 13.8
Andre Iguodala SF Golden State Warriors 11.7105
Stephen Curry PG Golden State Warriors 11.3708
Jason Thompson PF Golden State Warriors 7.00847
Shaun Livingston PG Golden State Warriors 5.54373
Harrison Barnes SF Golden State Warriors 3.8734
Marreese Speights C Golden State Warriors 3.815
Leandro Barbosa SG Golden State Warriors 2.5
Festus Ezeli C Golden State Warriors 2.00875
Brandon Rush SF Golden State Warriors 1.27096
Kevon Looney SF Golden State Warriors 1.13196
Anderson Varejao PF Golden State Warriors 0.289755
" - ], "text/plain": [ - "" + "shape: (14, 4)\n", + "┌───────────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═══════════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Klay Thompson ┆ SG ┆ Golden State Warriors ┆ 15.501 │\n", + "│ Draymond Green ┆ PF ┆ Golden State Warriors ┆ 14.26087 │\n", + "│ Andrew Bogut ┆ C ┆ Golden State Warriors ┆ 13.8 │\n", + "│ Andre Iguodala ┆ SF ┆ Golden State Warriors ┆ 11.710456 │\n", + "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", + "│ Jason Thompson ┆ PF ┆ Golden State Warriors ┆ 7.008475 │\n", + "│ Shaun Livingston ┆ PG ┆ Golden State Warriors ┆ 5.543725 │\n", + "│ Harrison Barnes ┆ SF ┆ Golden State Warriors ┆ 3.873398 │\n", + "│ Marreese Speights ┆ C ┆ Golden State Warriors ┆ 3.815 │\n", + "│ Leandro Barbosa ┆ SG ┆ Golden State Warriors ┆ 2.5 │\n", + "│ Festus Ezeli ┆ C ┆ Golden State Warriors ┆ 2.008748 │\n", + "│ Brandon Rush ┆ SF ┆ Golden State Warriors ┆ 1.270964 │\n", + "│ Kevon Looney ┆ SF ┆ Golden State Warriors ┆ 1.13196 │\n", + "│ Anderson Varejao ┆ PF ┆ Golden State Warriors ┆ 0.289755 │\n", + "└───────────────────┴──────────┴───────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
"Jason Thompson""PF""Golden State Warriors"7.008475
"Shaun Livingston""PG""Golden State Warriors"5.543725
"Harrison Barnes""SF""Golden State Warriors"3.873398
"Marreese Speights""C""Golden State Warriors"3.815
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" ] - }, - "metadata": {}, - "output_type": "display_data" + } } ], "source": [ - "warriors.show()" + "with pl.Config(tbl_rows=-1):\n", + " display(warriors)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The `nba` table is sorted in alphabetical order of the team names. To see how the players were paid in 2015-2016, it is useful to sort the data by salary. Remember that by default, the sorting is in increasing order." + "The `nba` DataFrame is sorted in alphabetical order of the team names. To see how the players were paid in 2015-2016, it is useful to sort the data by salary. Remember that by default, the sorting is in increasing order." ] }, { @@ -1033,67 +860,41 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 17, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Thanasis Antetokounmpo SF New York Knicks 0.030888
Jordan McRae SG Phoenix Suns 0.049709
Cory Jefferson PF Phoenix Suns 0.049709
Elliot Williams SG Memphis Grizzlies 0.055722
Orlando Johnson SG Phoenix Suns 0.055722
Phil Pressey PG Phoenix Suns 0.055722
Keith Appling PG Orlando Magic 0.061776
Sean Kilpatrick SG Denver Nuggets 0.099418
Erick Green PG Utah Jazz 0.099418
Jeff Ayres PF Los Angeles Clippers 0.111444
\n", - "

... (407 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Thanasis Antetokounmpo | SF | New York Knicks | 0.030888\n", - "Jordan McRae | SG | Phoenix Suns | 0.049709\n", - "Cory Jefferson | PF | Phoenix Suns | 0.049709\n", - "Elliot Williams | SG | Memphis Grizzlies | 0.055722\n", - "Orlando Johnson | SG | Phoenix Suns | 0.055722\n", - "Phil Pressey | PG | Phoenix Suns | 0.055722\n", - "Keith Appling | PG | Orlando Magic | 0.061776\n", - "Sean Kilpatrick | SG | Denver Nuggets | 0.099418\n", - "Erick Green | PG | Utah Jazz | 0.099418\n", - "Jeff Ayres | PF | Los Angeles Clippers | 0.111444\n", - "... (407 rows omitted)" + "shape: (417, 4)\n", + "┌────────────────────────┬──────────┬─────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════════════════════╪══════════╪═════════════════════╪═══════════╡\n", + "│ Thanasis Antetokounmpo ┆ SF ┆ New York Knicks ┆ 0.030888 │\n", + "│ Jordan McRae ┆ SG ┆ Phoenix Suns ┆ 0.049709 │\n", + "│ Cory Jefferson ┆ PF ┆ Phoenix Suns ┆ 0.049709 │\n", + "│ Elliot Williams ┆ SG ┆ Memphis Grizzlies ┆ 0.055722 │\n", + "│ Orlando Johnson ┆ SG ┆ Phoenix Suns ┆ 0.055722 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Dwight Howard ┆ C ┆ Houston Rockets ┆ 22.359364 │\n", + "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", + "│ LeBron James ┆ SF ┆ Cleveland Cavaliers ┆ 22.9705 │\n", + "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", + "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", + "└────────────────────────┴──────────┴─────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Thanasis Antetokounmpo""SF""New York Knicks"0.030888
"Jordan McRae""SG""Phoenix Suns"0.049709
"Cory Jefferson""PF""Phoenix Suns"0.049709
"Elliot Williams""SG""Memphis Grizzlies"0.055722
"Orlando Johnson""SG""Phoenix Suns"0.055722
…………
"Dwight Howard""C""Houston Rockets"22.359364
"Carmelo Anthony""SF""New York Knicks"22.875
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Kobe Bryant""SF""Los Angeles Lakers"25.0
" ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -1104,7 +905,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "These figures are somewhat difficult to compare as some of these players changed teams during the season and received salaries from more than one team; only the salary from the last team appears in the table. \n", + "These figures are somewhat difficult to compare as some of these players changed teams during the season and received salaries from more than one team; only the salary from the last team appears in the DataFrame. \n", "\n", "The CNN report is about the other end of the salary scale – the players who were among the highest paid in the world. To identify these players we can sort in descending order of salary and look at the top few rows." ] @@ -1115,67 +916,41 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 18, + "metadata": {}, "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PLAYER POSITION TEAM SALARY
Kobe Bryant SF Los Angeles Lakers 25
Joe Johnson SF Brooklyn Nets 24.8949
LeBron James SF Cleveland Cavaliers 22.9705
Carmelo Anthony SF New York Knicks 22.875
Dwight Howard C Houston Rockets 22.3594
Chris Bosh PF Miami Heat 22.1927
Chris Paul PG Los Angeles Clippers 21.4687
Kevin Durant SF Oklahoma City Thunder 20.1586
Derrick Rose PG Chicago Bulls 20.0931
Dwyane Wade SG Miami Heat 20
\n", - "

... (407 rows omitted)

" - ], "text/plain": [ - "PLAYER | POSITION | TEAM | SALARY\n", - "Kobe Bryant | SF | Los Angeles Lakers | 25\n", - "Joe Johnson | SF | Brooklyn Nets | 24.8949\n", - "LeBron James | SF | Cleveland Cavaliers | 22.9705\n", - "Carmelo Anthony | SF | New York Knicks | 22.875\n", - "Dwight Howard | C | Houston Rockets | 22.3594\n", - "Chris Bosh | PF | Miami Heat | 22.1927\n", - "Chris Paul | PG | Los Angeles Clippers | 21.4687\n", - "Kevin Durant | SF | Oklahoma City Thunder | 20.1586\n", - "Derrick Rose | PG | Chicago Bulls | 20.0931\n", - "Dwyane Wade | SG | Miami Heat | 20\n", - "... (407 rows omitted)" + "shape: (417, 4)\n", + "┌────────────────────────┬──────────┬─────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞════════════════════════╪══════════╪═════════════════════╪═══════════╡\n", + "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", + "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", + "│ LeBron James ┆ SF ┆ Cleveland Cavaliers ┆ 22.9705 │\n", + "│ Carmelo Anthony ┆ SF ┆ New York Knicks ┆ 22.875 │\n", + "│ Dwight Howard ┆ C ┆ Houston Rockets ┆ 22.359364 │\n", + "│ … ┆ … ┆ … ┆ … │\n", + "│ Orlando Johnson ┆ SG ┆ Phoenix Suns ┆ 0.055722 │\n", + "│ Phil Pressey ┆ PG ┆ Phoenix Suns ┆ 0.055722 │\n", + "│ Jordan McRae ┆ SG ┆ Phoenix Suns ┆ 0.049709 │\n", + "│ Cory Jefferson ┆ PF ┆ Phoenix Suns ┆ 0.049709 │\n", + "│ Thanasis Antetokounmpo ┆ SF ┆ New York Knicks ┆ 0.030888 │\n", + "└────────────────────────┴──────────┴─────────────────────┴───────────┘" + ], + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Carmelo Anthony""SF""New York Knicks"22.875
"Dwight Howard""C""Houston Rockets"22.359364
…………
"Orlando Johnson""SG""Phoenix Suns"0.055722
"Phil Pressey""PG""Phoenix Suns"0.055722
"Jordan McRae""SG""Phoenix Suns"0.049709
"Cory Jefferson""PF""Phoenix Suns"0.049709
"Thanasis Antetokounmpo""SF""New York Knicks"0.030888
" ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ From 86964521e203106c5b64526913c8d93073e9f66b Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 23:56:52 -0700 Subject: [PATCH 13/17] Ch. 5 to polars arrays --> pl.Series --- chapters/03/4/Introduction_to_Tables.ipynb | 474 ++++++++++----------- chapters/05/Sequences.ipynb | 43 +- 2 files changed, 267 insertions(+), 250 deletions(-) diff --git a/chapters/03/4/Introduction_to_Tables.ipynb b/chapters/03/4/Introduction_to_Tables.ipynb index 281e0e3e2..3660eabce 100644 --- a/chapters/03/4/Introduction_to_Tables.ipynb +++ b/chapters/03/4/Introduction_to_Tables.ipynb @@ -50,10 +50,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 2, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (6, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
"bubblegum""pink"4.75
" + ], "text/plain": [ "shape: (6, 3)\n", "┌────────────┬─────────────┬───────┐\n", @@ -68,18 +75,11 @@ "│ chocolate ┆ dark brown ┆ 5.25 │\n", "│ bubblegum ┆ pink ┆ 4.75 │\n", "└────────────┴─────────────┴───────┘" - ], - "text/html": [ - "
\n", - "shape: (6, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
"bubblegum""pink"4.75
" ] - } + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -107,10 +107,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 3, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (2, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
" + ], "text/plain": [ "shape: (2, 3)\n", "┌────────────┬─────────────┬───────┐\n", @@ -121,18 +128,11 @@ "│ strawberry ┆ pink ┆ 3.55 │\n", "│ chocolate ┆ light brown ┆ 4.75 │\n", "└────────────┴─────────────┴───────┘" - ], - "text/html": [ - "
\n", - "shape: (2, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
" ] - } + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -160,10 +160,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 4, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (6, 1)
Flavor
str
"strawberry"
"chocolate"
"chocolate"
"strawberry"
"chocolate"
"bubblegum"
" + ], "text/plain": [ "shape: (6, 1)\n", "┌────────────┐\n", @@ -178,18 +185,11 @@ "│ chocolate │\n", "│ bubblegum │\n", "└────────────┘" - ], - "text/html": [ - "
\n", - "shape: (6, 1)
Flavor
str
"strawberry"
"chocolate"
"chocolate"
"strawberry"
"chocolate"
"bubblegum"
" ] - } + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -209,10 +209,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 5, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (6, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
"bubblegum""pink"4.75
" + ], "text/plain": [ "shape: (6, 3)\n", "┌────────────┬─────────────┬───────┐\n", @@ -227,18 +234,11 @@ "│ chocolate ┆ dark brown ┆ 5.25 │\n", "│ bubblegum ┆ pink ┆ 4.75 │\n", "└────────────┴─────────────┴───────┘" - ], - "text/html": [ - "
\n", - "shape: (6, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
"bubblegum""pink"4.75
" ] - } + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -258,10 +258,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 6, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (6, 2)
FlavorPrice
strf64
"strawberry"3.55
"chocolate"4.75
"chocolate"5.25
"strawberry"5.25
"chocolate"5.25
"bubblegum"4.75
" + ], "text/plain": [ "shape: (6, 2)\n", "┌────────────┬───────┐\n", @@ -276,18 +283,11 @@ "│ chocolate ┆ 5.25 │\n", "│ bubblegum ┆ 4.75 │\n", "└────────────┴───────┘" - ], - "text/html": [ - "
\n", - "shape: (6, 2)
FlavorPrice
strf64
"strawberry"3.55
"chocolate"4.75
"chocolate"5.25
"strawberry"5.25
"chocolate"5.25
"bubblegum"4.75
" ] - } + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -307,10 +307,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 7, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (6, 2)
FlavorPrice
strf64
"strawberry"3.55
"chocolate"4.75
"chocolate"5.25
"strawberry"5.25
"chocolate"5.25
"bubblegum"4.75
" + ], "text/plain": [ "shape: (6, 2)\n", "┌────────────┬───────┐\n", @@ -325,18 +332,11 @@ "│ chocolate ┆ 5.25 │\n", "│ bubblegum ┆ 4.75 │\n", "└────────────┴───────┘" - ], - "text/html": [ - "
\n", - "shape: (6, 2)
FlavorPrice
strf64
"strawberry"3.55
"chocolate"4.75
"chocolate"5.25
"strawberry"5.25
"chocolate"5.25
"bubblegum"4.75
" ] - } + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -356,10 +356,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 8, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (6, 2)
FlavorPrice
strf64
"strawberry"3.55
"chocolate"4.75
"chocolate"5.25
"strawberry"5.25
"chocolate"5.25
"bubblegum"4.75
" + ], "text/plain": [ "shape: (6, 2)\n", "┌────────────┬───────┐\n", @@ -374,18 +381,11 @@ "│ chocolate ┆ 5.25 │\n", "│ bubblegum ┆ 4.75 │\n", "└────────────┴───────┘" - ], - "text/html": [ - "
\n", - "shape: (6, 2)
FlavorPrice
strf64
"strawberry"3.55
"chocolate"4.75
"chocolate"5.25
"strawberry"5.25
"chocolate"5.25
"bubblegum"4.75
" ] - } + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -421,10 +421,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 9, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (6, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
"bubblegum""pink"4.75
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
" + ], "text/plain": [ "shape: (6, 3)\n", "┌────────────┬─────────────┬───────┐\n", @@ -439,18 +446,11 @@ "│ strawberry ┆ pink ┆ 5.25 │\n", "│ chocolate ┆ dark brown ┆ 5.25 │\n", "└────────────┴─────────────┴───────┘" - ], - "text/html": [ - "
\n", - "shape: (6, 3)
FlavorColorPrice
strstrf64
"strawberry""pink"3.55
"chocolate""light brown"4.75
"bubblegum""pink"4.75
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
" ] - } + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -472,10 +472,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 10, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (6, 3)
FlavorColorPrice
strstrf64
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
"chocolate""light brown"4.75
"bubblegum""pink"4.75
"strawberry""pink"3.55
" + ], "text/plain": [ "shape: (6, 3)\n", "┌────────────┬─────────────┬───────┐\n", @@ -490,18 +497,11 @@ "│ bubblegum ┆ pink ┆ 4.75 │\n", "│ strawberry ┆ pink ┆ 3.55 │\n", "└────────────┴─────────────┴───────┘" - ], - "text/html": [ - "
\n", - "shape: (6, 3)
FlavorColorPrice
strstrf64
"chocolate""dark brown"5.25
"strawberry""pink"5.25
"chocolate""dark brown"5.25
"chocolate""light brown"4.75
"bubblegum""pink"4.75
"strawberry""pink"3.55
" ] - } + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -531,10 +531,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 11, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (3, 3)
FlavorColorPrice
strstrf64
"chocolate""light brown"4.75
"chocolate""dark brown"5.25
"chocolate""dark brown"5.25
" + ], "text/plain": [ "shape: (3, 3)\n", "┌───────────┬─────────────┬───────┐\n", @@ -546,18 +553,11 @@ "│ chocolate ┆ dark brown ┆ 5.25 │\n", "│ chocolate ┆ dark brown ┆ 5.25 │\n", "└───────────┴─────────────┴───────┘" - ], - "text/html": [ - "
\n", - "shape: (3, 3)
FlavorColorPrice
strstrf64
"chocolate""light brown"4.75
"chocolate""dark brown"5.25
"chocolate""dark brown"5.25
" ] - } + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -579,19 +579,7 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 12, - "metadata": {}, "data": { - "text/plain": [ - "shape: (0, 3)\n", - "┌────────┬───────┬───────┐\n", - "│ Flavor ┆ Color ┆ Price │\n", - "│ --- ┆ --- ┆ --- │\n", - "│ str ┆ str ┆ f64 │\n", - "╞════════╪═══════╪═══════╡\n", - "└────────┴───────┴───────┘" - ], "text/html": [ "
\n", "shape: (0, 3)
FlavorColorPrice
strstrf64
" + ], + "text/plain": [ + "shape: (0, 3)\n", + "┌────────┬───────┬───────┐\n", + "│ Flavor ┆ Color ┆ Price │\n", + "│ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ f64 │\n", + "╞════════╪═══════╪═══════╡\n", + "└────────┴───────┴───────┘" ] - } + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -649,10 +649,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 13, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Tiago Splitter""C""Atlanta Hawks"9.75625
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
…………
"Gary Neal""PG""Washington Wizards"2.139
"DeJuan Blair""C""Washington Wizards"2.0
"Kelly Oubre Jr.""SF""Washington Wizards"1.92024
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" + ], "text/plain": [ "shape: (417, 4)\n", "┌─────────────────┬──────────┬────────────────────┬───────────┐\n", @@ -672,18 +679,11 @@ "│ Garrett Temple ┆ SG ┆ Washington Wizards ┆ 1.100602 │\n", "│ Jarell Eddie ┆ SG ┆ Washington Wizards ┆ 0.561716 │\n", "└─────────────────┴──────────┴────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Paul Millsap""PF""Atlanta Hawks"18.671659
"Al Horford""C""Atlanta Hawks"12.0
"Tiago Splitter""C""Atlanta Hawks"9.75625
"Jeff Teague""PG""Atlanta Hawks"8.0
"Kyle Korver""SG""Atlanta Hawks"5.746479
…………
"Gary Neal""PG""Washington Wizards"2.139
"DeJuan Blair""C""Washington Wizards"2.0
"Kelly Oubre Jr.""SF""Washington Wizards"1.92024
"Garrett Temple""SG""Washington Wizards"1.100602
"Jarell Eddie""SG""Washington Wizards"0.561716
" ] - } + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -703,20 +703,7 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 14, - "metadata": {}, "data": { - "text/plain": [ - "shape: (1, 4)\n", - "┌───────────────┬──────────┬───────────────────────┬───────────┐\n", - "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", - "│ --- ┆ --- ┆ --- ┆ --- │\n", - "│ str ┆ str ┆ str ┆ f64 │\n", - "╞═══════════════╪══════════╪═══════════════════════╪═══════════╡\n", - "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", - "└───────────────┴──────────┴───────────────────────┴───────────┘" - ], "text/html": [ "
\n", "shape: (1, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Stephen Curry""PG""Golden State Warriors"11.370786
" + ], + "text/plain": [ + "shape: (1, 4)\n", + "┌───────────────┬──────────┬───────────────────────┬───────────┐\n", + "│ PLAYER ┆ POSITION ┆ TEAM ┆ SALARY │\n", + "│ --- ┆ --- ┆ --- ┆ --- │\n", + "│ str ┆ str ┆ str ┆ f64 │\n", + "╞═══════════════╪══════════╪═══════════════════════╪═══════════╡\n", + "│ Stephen Curry ┆ PG ┆ Golden State Warriors ┆ 11.370786 │\n", + "└───────────────┴──────────┴───────────────────────┴───────────┘" ] - } + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -747,10 +747,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 15, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
…………
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" + ], "text/plain": [ "shape: (14, 4)\n", "┌──────────────────┬──────────┬───────────────────────┬───────────┐\n", @@ -770,18 +777,11 @@ "│ Kevon Looney ┆ SF ┆ Golden State Warriors ┆ 1.13196 │\n", "│ Anderson Varejao ┆ PF ┆ Golden State Warriors ┆ 0.289755 │\n", "└──────────────────┴──────────┴───────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
…………
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" ] - } + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -802,10 +802,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 16, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
"Jason Thompson""PF""Golden State Warriors"7.008475
"Shaun Livingston""PG""Golden State Warriors"5.543725
"Harrison Barnes""SF""Golden State Warriors"3.873398
"Marreese Speights""C""Golden State Warriors"3.815
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" + ], "text/plain": [ "shape: (14, 4)\n", "┌───────────────────┬──────────┬───────────────────────┬───────────┐\n", @@ -828,18 +835,11 @@ "│ Kevon Looney ┆ SF ┆ Golden State Warriors ┆ 1.13196 │\n", "│ Anderson Varejao ┆ PF ┆ Golden State Warriors ┆ 0.289755 │\n", "└───────────────────┴──────────┴───────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (14, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Klay Thompson""SG""Golden State Warriors"15.501
"Draymond Green""PF""Golden State Warriors"14.26087
"Andrew Bogut""C""Golden State Warriors"13.8
"Andre Iguodala""SF""Golden State Warriors"11.710456
"Stephen Curry""PG""Golden State Warriors"11.370786
"Jason Thompson""PF""Golden State Warriors"7.008475
"Shaun Livingston""PG""Golden State Warriors"5.543725
"Harrison Barnes""SF""Golden State Warriors"3.873398
"Marreese Speights""C""Golden State Warriors"3.815
"Leandro Barbosa""SG""Golden State Warriors"2.5
"Festus Ezeli""C""Golden State Warriors"2.008748
"Brandon Rush""SF""Golden State Warriors"1.270964
"Kevon Looney""SF""Golden State Warriors"1.13196
"Anderson Varejao""PF""Golden State Warriors"0.289755
" ] - } + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -860,10 +860,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 17, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Thanasis Antetokounmpo""SF""New York Knicks"0.030888
"Jordan McRae""SG""Phoenix Suns"0.049709
"Cory Jefferson""PF""Phoenix Suns"0.049709
"Elliot Williams""SG""Memphis Grizzlies"0.055722
"Orlando Johnson""SG""Phoenix Suns"0.055722
…………
"Dwight Howard""C""Houston Rockets"22.359364
"Carmelo Anthony""SF""New York Knicks"22.875
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Kobe Bryant""SF""Los Angeles Lakers"25.0
" + ], "text/plain": [ "shape: (417, 4)\n", "┌────────────────────────┬──────────┬─────────────────────┬───────────┐\n", @@ -883,18 +890,11 @@ "│ Joe Johnson ┆ SF ┆ Brooklyn Nets ┆ 24.894863 │\n", "│ Kobe Bryant ┆ SF ┆ Los Angeles Lakers ┆ 25.0 │\n", "└────────────────────────┴──────────┴─────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Thanasis Antetokounmpo""SF""New York Knicks"0.030888
"Jordan McRae""SG""Phoenix Suns"0.049709
"Cory Jefferson""PF""Phoenix Suns"0.049709
"Elliot Williams""SG""Memphis Grizzlies"0.055722
"Orlando Johnson""SG""Phoenix Suns"0.055722
…………
"Dwight Howard""C""Houston Rockets"22.359364
"Carmelo Anthony""SF""New York Knicks"22.875
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Joe Johnson""SF""Brooklyn Nets"24.894863
"Kobe Bryant""SF""Los Angeles Lakers"25.0
" ] - } + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -916,10 +916,17 @@ "metadata": {}, "outputs": [ { - "output_type": "execute_result", - "execution_count": 18, - "metadata": {}, "data": { + "text/html": [ + "
\n", + "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Carmelo Anthony""SF""New York Knicks"22.875
"Dwight Howard""C""Houston Rockets"22.359364
…………
"Orlando Johnson""SG""Phoenix Suns"0.055722
"Phil Pressey""PG""Phoenix Suns"0.055722
"Jordan McRae""SG""Phoenix Suns"0.049709
"Cory Jefferson""PF""Phoenix Suns"0.049709
"Thanasis Antetokounmpo""SF""New York Knicks"0.030888
" + ], "text/plain": [ "shape: (417, 4)\n", "┌────────────────────────┬──────────┬─────────────────────┬───────────┐\n", @@ -939,18 +946,11 @@ "│ Cory Jefferson ┆ PF ┆ Phoenix Suns ┆ 0.049709 │\n", "│ Thanasis Antetokounmpo ┆ SF ┆ New York Knicks ┆ 0.030888 │\n", "└────────────────────────┴──────────┴─────────────────────┴───────────┘" - ], - "text/html": [ - "
\n", - "shape: (417, 4)
PLAYERPOSITIONTEAMSALARY
strstrstrf64
"Kobe Bryant""SF""Los Angeles Lakers"25.0
"Joe Johnson""SF""Brooklyn Nets"24.894863
"LeBron James""SF""Cleveland Cavaliers"22.9705
"Carmelo Anthony""SF""New York Knicks"22.875
"Dwight Howard""C""Houston Rockets"22.359364
…………
"Orlando Johnson""SG""Phoenix Suns"0.055722
"Phil Pressey""PG""Phoenix Suns"0.055722
"Jordan McRae""SG""Phoenix Suns"0.049709
"Cory Jefferson""PF""Phoenix Suns"0.049709
"Thanasis Antetokounmpo""SF""New York Knicks"0.030888
" ] - } + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ diff --git a/chapters/05/Sequences.ipynb b/chapters/05/Sequences.ipynb index 744aa38aa..2395c46dc 100644 --- a/chapters/05/Sequences.ipynb +++ b/chapters/05/Sequences.ipynb @@ -17,7 +17,7 @@ }, "outputs": [], "source": [ - "from datascience import *\n", + "import polars as pl\n", "path_data = '../../assets/data/'" ] }, @@ -27,7 +27,7 @@ "source": [ "Values can be grouped together into collections, which allows programmers to organize those values and refer to all of them with a single name. By grouping values together, we can write code that performs a computation on many pieces of data at once.\n", "\n", - "Calling the function `make_array` on several values places them into an *array*, which is a kind of sequential collection. Below, we collect four different temperatures into an array called `highs`. These are the [estimated average daily high temperatures](http://berkeleyearth.lbl.gov/regions/global-land) over all land on Earth (in degrees Celsius) for the decades surrounding 1850, 1900, 1950, and 2000, respectively, expressed as deviations from the average absolute high temperature between 1951 and 1980, which was 14.48 degrees." + "Calling `pl.Series` with a name and a list of values places them into a *Polars Series*, which is a kind of sequential collection. Below, we collect four different temperatures into a Polars Series called `highs`. These are the [estimated average daily high temperatures](http://berkeleyearth.lbl.gov/regions/global-land) over all land on Earth (in degrees Celsius) for the decades surrounding 1850, 1900, 1950, and 2000, respectively, expressed as deviations from the average absolute high temperature between 1951 and 1980, which was 14.48 degrees." ] }, { @@ -36,20 +36,37 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 2, + "metadata": {}, "data": { "text/plain": [ - "array([13.6 , 14.387, 14.585, 15.164])" + "shape: (4,)\n", + "Series: 'highs' [f64]\n", + "[\n", + "\t13.6\n", + "\t14.387\n", + "\t14.585\n", + "\t15.164\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (4,)
highs
f64
13.6
14.387
14.585
15.164
" ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ "baseline_high = 14.48\n", - "highs = make_array(baseline_high - 0.880, baseline_high - 0.093,\n", - " baseline_high + 0.105, baseline_high + 0.684)\n", + "highs = pl.Series(\"highs\", [baseline_high - 0.880, baseline_high - 0.093,\n", + " baseline_high + 0.105, baseline_high + 0.684])\n", "highs" ] }, @@ -66,14 +83,14 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 3, + "metadata": {}, "data": { "text/plain": [ "14.434000000000001" ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ From bbd3c1e72eb253967e1803d9224d863bd91a55c4 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Sat, 17 Oct 2026 00:10:15 -0700 Subject: [PATCH 14/17] Ch 5.1 to polars - table methods are changed to adapt to polars --- chapters/05/1/Arrays.ipynb | 243 +++++++++++++++++++++++-------------- 1 file changed, 152 insertions(+), 91 deletions(-) diff --git a/chapters/05/1/Arrays.ipynb b/chapters/05/1/Arrays.ipynb index d40094412..ce82f9e70 100644 --- a/chapters/05/1/Arrays.ipynb +++ b/chapters/05/1/Arrays.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Arrays" + "# Polars Series" ] }, { @@ -17,7 +17,7 @@ }, "outputs": [], "source": [ - "from datascience import *\n", + "import polars as pl\n", "path_data = '../../../assets/data/'" ] }, @@ -25,9 +25,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "While there are many kinds of collections in Python, we will work primarily with arrays in this class. We've already seen that the `make_array` function can be used to create arrays of numbers.\n", + "While there are many kinds of collections in Python, we will work primarily with Polars Series in this class. We've already seen that `pl.Series` can be used to create a Polars Series of numbers.\n", "\n", - "Arrays can also contain strings or other types of values, but a single array can only contain a single kind of data. (It usually doesn't make sense to group together unlike data anyway.) For example:" + "A Polars Series can also contain strings or other types of values, but a single Polars Series can only contain a single kind of data. (It usually doesn't make sense to group together unlike data anyway.) For example:" ] }, { @@ -36,19 +36,39 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 2, + "metadata": {}, "data": { "text/plain": [ - "array(['noun', 'pronoun', 'verb', 'adverb', 'adjective', 'conjunction',\n", - " 'preposition', 'interjection'], dtype='\n", + "shape: (8,)
english_parts_of_speech
str
"noun"
"pronoun"
"verb"
"adverb"
"adjective"
"conjunction"
"preposition"
"interjection"
" ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "english_parts_of_speech = make_array(\"noun\", \"pronoun\", \"verb\", \"adverb\", \"adjective\", \"conjunction\", \"preposition\", \"interjection\")\n", + "english_parts_of_speech = pl.Series(\"english_parts_of_speech\", [\"noun\", \"pronoun\", \"verb\", \"adverb\", \"adjective\", \"conjunction\", \"preposition\", \"interjection\"])\n", "english_parts_of_speech" ] }, @@ -56,7 +76,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Returning to the temperature data, we create arrays of average daily [high temperatures](http://berkeleyearth.lbl.gov/auto/Regional/TMAX/Text/global-land-TMAX-Trend.txt) for the decades surrounding 1850, 1900, 1950, and 2000." + "Returning to the temperature data, we create a Polars Series of average daily [high temperatures](http://berkeleyearth.lbl.gov/auto/Regional/TMAX/Text/global-land-TMAX-Trend.txt) for the decades surrounding 1850, 1900, 1950, and 2000." ] }, { @@ -65,22 +85,39 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 3, + "metadata": {}, "data": { "text/plain": [ - "array([13.6 , 14.387, 14.585, 15.164])" + "shape: (4,)\n", + "Series: 'highs' [f64]\n", + "[\n", + "\t13.6\n", + "\t14.387\n", + "\t14.585\n", + "\t15.164\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (4,)
highs
f64
13.6
14.387
14.585
15.164
" ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ "baseline_high = 14.48\n", - "highs = make_array(baseline_high - 0.880, \n", + "highs = pl.Series(\"highs\", [baseline_high - 0.880, \n", " baseline_high - 0.093,\n", " baseline_high + 0.105, \n", - " baseline_high + 0.684)\n", + " baseline_high + 0.684])\n", "highs" ] }, @@ -88,7 +125,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Arrays can be used in arithmetic expressions to compute over their contents. When an array is combined with a single number, that number is combined with each element of the array. Therefore, we can convert all of these temperatures to Fahrenheit by writing the familiar conversion formula." + "Polars Series can be used in arithmetic expressions to compute over their contents. When a Polars Series is combined with a single number, that number is combined with each element of the Series. Therefore, we can convert all of these temperatures to Fahrenheit by writing the familiar conversion formula." ] }, { @@ -97,14 +134,31 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 4, + "metadata": {}, "data": { "text/plain": [ - "array([56.48 , 57.8966, 58.253 , 59.2952])" + "shape: (4,)\n", + "Series: 'highs' [f64]\n", + "[\n", + "\t56.48\n", + "\t57.8966\n", + "\t58.253\n", + "\t59.2952\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (4,)
highs
f64
56.48
57.8966
58.253
59.2952
" ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -115,14 +169,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "![Visual representation of array arithmetic. (9/5) times the array highs (13.6, 14.387, 14.585, 15.164) plus 32 equals (9/5) times 13.6 + 32 in the first slot of the resulting array, followed by (9/5) times 14.387 plus 32 in the second slot of the array, and so on. Finally on the right hand side of the image, an array is shown with the final answers (56.48, 57.8966, 58.253, 59.2952).](../../../images/array_arithmetic.png)" + "![Visual representation of Polars Series arithmetic. (9/5) times the Polars Series highs (13.6, 14.387, 14.585, 15.164) plus 32 equals (9/5) times 13.6 + 32 in the first slot of the resulting Polars Series, followed by (9/5) times 14.387 plus 32 in the second slot of the Polars Series, and so on. Finally on the right hand side of the image, a Polars Series is shown with the final answers (56.48, 57.8966, 58.253, 59.2952).](../../../images/array_arithmetic.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Arrays also have *methods*, which are functions that operate on the array values. The `mean` of a collection of numbers is its average value: the sum divided by the length. Each pair of parentheses in the examples below is part of a call expression; it's calling a function with no arguments to perform a computation on the array called `highs`." + "Polars Series also have *methods*, which are functions that operate on the Series values. The `mean` of a collection of numbers is its average value: the sum divided by the length. Each pair of parentheses in the examples below is part of a call expression; it's calling a function with no arguments to perform a computation on the Polars Series called `highs`." ] }, { @@ -131,18 +185,18 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 5, + "metadata": {}, "data": { "text/plain": [ "4" ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "highs.size" + "highs.len()" ] }, { @@ -151,14 +205,14 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 6, + "metadata": {}, "data": { "text/plain": [ "57.736000000000004" ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -171,14 +225,14 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 7, + "metadata": {}, "data": { "text/plain": [ "14.434000000000001" ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ @@ -189,96 +243,103 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Functions on Arrays\n", - "The `numpy` package, abbreviated `np` in programs, provides Python programmers with convenient and powerful functions for creating and manipulating arrays." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np" + "## Functions on Polars Series\n", + "A Polars Series has methods for manipulating its values. Call a method on the Series, as in `highs.diff()`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "For example, the `diff` function computes the difference between each adjacent pair of elements in an array. The first element of the `diff` is the second element minus the first. " + "For example, the `diff` method computes the difference between each adjacent pair of elements in a Polars Series. The first element is null. Each later element is that element minus the one before it." ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 8, + "metadata": {}, "data": { "text/plain": [ - "array([0.787, 0.198, 0.579])" + "shape: (4,)\n", + "Series: 'highs' [f64]\n", + "[\n", + "\tnull\n", + "\t0.787\n", + "\t0.198\n", + "\t0.579\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (4,)
highs
f64
null
0.787
0.198
0.579
" ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "np.diff(highs)" + "highs.diff()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The [full Numpy reference](http://docs.scipy.org/doc/numpy/reference/) lists these functions exhaustively, but only a small subset are used commonly for data processing applications. These are grouped into different packages within `np`. Learning this vocabulary is an important part of learning the Python language, so refer back to this list often as you work through examples and problems.\n", + "The [Polars Series reference](https://docs.pola.rs/api/python/stable/reference/series/index.html) lists these methods exhaustively, but only a small subset are used commonly for data processing applications. String methods are called on `str`, as in `s.str.to_lowercase()`. Learning this vocabulary is an important part of learning the Python language, so refer back to this list often as you work through examples and problems.\n", "\n", "However, you **don't need to memorize these**. Use this as a reference.\n", "\n", - "Each of these functions takes an array as an argument and returns a single value.\n", + "Each of these methods returns a single value.\n", "\n", - "| **Function** | Description |\n", + "| **Method** | Description |\n", "|--------------------|----------------------------------------------------------------------|\n", - "| `np.prod` | Multiply all elements together |\n", - "| `np.sum` | Add all elements together |\n", - "| `np.all` | Test whether all elements are true values (non-zero numbers are true)|\n", - "| `np.any` | Test whether any elements are true values (non-zero numbers are true)|\n", - "| `np.count_nonzero` | Count the number of non-zero elements |\n", + "| `s.product()` | Multiply all elements together |\n", + "| `s.sum()` | Add all elements together |\n", + "| `(s != 0).all()` | Test whether all elements are true values (non-zero numbers are true)|\n", + "| `(s != 0).any()` | Test whether any elements are true values (non-zero numbers are true)|\n", + "| `(s != 0).sum()` | Count the number of non-zero elements |\n", "\n", - "Each of these functions takes an array as an argument and returns an array of values.\n", + "Each of these methods returns a Polars Series of values.\n", "\n", - "| **Function** | Description |\n", + "| **Method** | Description |\n", "|--------------------|----------------------------------------------------------------------|\n", - "| `np.diff` | Difference between adjacent elements |\n", - "| `np.round` | Round each number to the nearest integer (whole number) |\n", - "| `np.cumprod` | A cumulative product: for each element, multiply all elements so far |\n", - "| `np.cumsum` | A cumulative sum: for each element, add all elements so far |\n", - "| `np.exp` | Exponentiate each element |\n", - "| `np.log` | Take the natural logarithm of each element |\n", - "| `np.sqrt` | Take the square root of each element |\n", - "| `np.sort` | Sort the elements |\n", + "| `s.diff()` | Difference between adjacent elements. The first element is null. |\n", + "| `s.round()` | Round each number to the nearest integer (whole number) |\n", + "| `s.cum_prod()` | A cumulative product: for each element, multiply all elements so far |\n", + "| `s.cum_sum()` | A cumulative sum: for each element, add all elements so far |\n", + "| `s.exp()` | Exponentiate each element |\n", + "| `s.log()` | Take the natural logarithm of each element |\n", + "| `s.sqrt()` | Take the square root of each element |\n", + "| `s.sort()` | Sort the elements |\n", "\n", - "Each of these functions takes an array of strings and returns an array.\n", + "Each of these string methods takes a Polars Series of strings and returns a Polars Series.\n", "\n", - "| **Function** | **Description** |\n", + "| **Method** | **Description** |\n", "|---------------------|--------------------------------------------------------------|\n", - "| `np.char.lower` | Lowercase each element |\n", - "| `np.char.upper` | Uppercase each element |\n", - "| `np.char.strip` | Remove spaces at the beginning or end of each element |\n", - "| `np.char.isalpha` | Whether each element is only letters (no numbers or symbols) |\n", - "| `np.char.isnumeric` | Whether each element is only numeric (no letters) \n", + "| `s.str.to_lowercase()` | Lowercase each element |\n", + "| `s.str.to_uppercase()` | Uppercase each element |\n", + "| `s.str.strip_chars()` | Remove spaces at the beginning or end of each element |\n", + "| `s.str.contains(r\"^\\p{Alphabetic}+$\")` | Whether each element is only letters (no numbers or symbols) |\n", + "| `s.str.contains(r\"^\\d+$\")` | Whether each element is only numeric (no letters) |\n", "\n", - "Each of these functions takes both an array of strings and a *search string*; each returns an array.\n", + "Each of these string methods takes a search string as well; each returns a Polars Series.\n", "\n", - "| **Function** | **Description** |\n", + "| **Method** | **Description** |\n", "|----------------------|----------------------------------------------------------------------------------|\n", - "| `np.char.count` | Count the number of times a search string appears among the elements of an array |\n", - "| `np.char.find` | The position within each element that a search string is found first |\n", - "| `np.char.rfind` | The position within each element that a search string is found last |\n", - "| `np.char.startswith` | Whether each element starts with the search string \n", - "\n" + "| `s.str.count_matches(substr, literal=True)` | Count the number of times a search string appears among the elements of a Polars Series |\n", + "| `s.str.find(substr, literal=True)` | The position within each element that a search string is found first. A missing search is null. |\n", + "| | The last position of a search string has no Polars Series method. |\n", + "| `s.str.starts_with(substr)` | Whether each element starts with the search string |" ] } ], From 1e32ecf35d846efcd0038a2fbc319446c14bf360 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Sat, 17 Oct 2026 00:13:31 -0700 Subject: [PATCH 15/17] Ch 5.2 to polars - pl.int_range --> for integers - pl.linear_space --> for fractional / float steps --- chapters/05/2/Ranges.ipynb | 230 ++++++++++++++++++++++++++++--------- 1 file changed, 175 insertions(+), 55 deletions(-) diff --git a/chapters/05/2/Ranges.ipynb b/chapters/05/2/Ranges.ipynb index 82fa85ad9..6afd7e150 100644 --- a/chapters/05/2/Ranges.ipynb +++ b/chapters/05/2/Ranges.ipynb @@ -6,16 +6,16 @@ "source": [ "# Ranges\n", "\n", - "A *range* is an array of numbers in increasing or decreasing order, each separated by a regular interval. \n", + "A *range* is a Polars Series of numbers in increasing or decreasing order, each separated by a regular interval. \n", "Ranges are useful in a surprisingly large number of situations, so it's worthwhile to learn about them.\n", "\n", - "Ranges are defined using the `np.arange` function, which takes either one, two, or three arguments: a start, and end, and a 'step'.\n", + "Integer ranges are defined using `pl.int_range`, which takes either one, two, or three arguments: a start, an end, and a step. Pass `eager=True` so the result is a Polars Series.\n", "\n", - "If you pass one argument to `np.arange`, this becomes the `end` value, with `start=0`, `step=1` assumed. Two arguments give the `start` and `end` with `step=1` assumed. Three arguments give the `start`, `end` and `step` explicitly.\n", + "If you pass one argument to `pl.int_range`, this becomes the `end` value, with `start=0`, `step=1` assumed. Two arguments give the `start` and `end` with `step=1` assumed. Three arguments give the `start`, `end` and `step` explicitly.\n", "\n", "A range always includes its `start` value, but does not include its `end` value. It counts up by `step`, and it stops before it gets to the `end`.\n", "\n", - " np.arange(end): An array starting with 0 of increasing consecutive integers, stopping before end." + " pl.int_range(end, eager=True): A Polars Series starting with 0 of increasing consecutive integers, stopping before end." ] }, { @@ -28,7 +28,7 @@ }, "outputs": [], "source": [ - "import numpy as np\n", + "import polars as pl\n", "path_data = '../../../assets/data/'" ] }, @@ -38,25 +38,44 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 2, + "metadata": {}, "data": { "text/plain": [ - "array([0, 1, 2, 3, 4])" + "shape: (5,)\n", + "Series: 'range' [i64]\n", + "[\n", + "\t0\n", + "\t1\n", + "\t2\n", + "\t3\n", + "\t4\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (5,)
range
i64
0
1
2
3
4
" ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "np.arange(5)" + "# POLARS_CHANGE: an eager range is named \"literal\" unless alias gives it a name\n", + "pl.int_range(5, eager=True).alias(\"range\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Notice how the array starts at 0 and goes only up to 4, not to the end value of 5." + "Notice how the Polars Series starts at 0 and goes only up to 4, not to the end value of 5." ] }, { @@ -64,7 +83,7 @@ "metadata": {}, "source": [ "\n", - " np.arange(start, end): An array of consecutive increasing integers from start, stopping before end." + " pl.int_range(start, end, eager=True): A Polars Series of consecutive increasing integers from start, stopping before end." ] }, { @@ -73,18 +92,37 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 3, + "metadata": {}, "data": { "text/plain": [ - "array([3, 4, 5, 6, 7, 8])" + "shape: (6,)\n", + "Series: 'range' [i64]\n", + "[\n", + "\t3\n", + "\t4\n", + "\t5\n", + "\t6\n", + "\t7\n", + "\t8\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (6,)
range
i64
3
4
5
6
7
8
" ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "np.arange(3, 9)" + "pl.int_range(3, 9, eager=True).alias(\"range\")" ] }, { @@ -92,7 +130,7 @@ "metadata": {}, "source": [ "\n", - " np.arange(start, end, step): A range with a difference of step between each pair of consecutive values, starting from start and stopping before end." + " pl.int_range(start, end, step, eager=True): A range with a difference of step between each pair of consecutive values, starting from start and stopping before end." ] }, { @@ -101,27 +139,46 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 4, + "metadata": {}, "data": { "text/plain": [ - "array([ 3, 8, 13, 18, 23, 28])" + "shape: (6,)\n", + "Series: 'range' [i64]\n", + "[\n", + "\t3\n", + "\t8\n", + "\t13\n", + "\t18\n", + "\t23\n", + "\t28\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (6,)
range
i64
3
8
13
18
23
28
" ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "np.arange(3, 30, 5)" + "pl.int_range(3, 30, 5, eager=True).alias(\"range\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This array starts at 3, then takes a step of 5 to get to 8, then another step of 5 to get to 13, and so on.\n", + "This Polars Series starts at 3, then takes a step of 5 to get to 8, then another step of 5 to get to 13, and so on.\n", "\n", - "When you specify a step, the start, end, and step can all be either positive or negative and may be whole numbers or fractions. " + "When you specify a step, the start, end, and step can be positive or negative whole numbers. `pl.int_range` does not take a fractional step. A fractional step is `pl.linear_space`, which takes the number of samples instead of a step. `closed=\"left\"` includes the start and excludes the end." ] }, { @@ -130,18 +187,39 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 5, + "metadata": {}, "data": { "text/plain": [ - "array([ 1.5, 1. , 0.5, 0. , -0.5, -1. , -1.5])" + "shape: (7,)\n", + "Series: 'range' [f64]\n", + "[\n", + "\t1.5\n", + "\t1.0\n", + "\t0.5\n", + "\t0.0\n", + "\t-0.5\n", + "\t-1.0\n", + "\t-1.5\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (7,)
range
f64
1.5
1.0
0.5
0.0
-0.5
-1.0
-1.5
" ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "np.arange(1.5, -2, -0.5)" + "# POLARS_CHANGE: 7 samples from 1.5 down to but not including -2\n", + "pl.linear_space(1.5, -2, 7, closed=\"left\", eager=True).alias(\"range\")" ] }, { @@ -165,7 +243,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Though some math is needed to establish this, we can use arrays to convince ourselves that the formula works. Let's calculate the first 5000 terms of Leibniz's infinite sum and see if it is close to $\\pi$.\n", + "Though some math is needed to establish this, we can use Polars Series to convince ourselves that the formula works. Let's calculate the first 5000 terms of Leibniz's infinite sum and see if it is close to $\\pi$.\n", "\n", "$$4 \\cdot \\left(1 - \\frac{1}{3} + \\frac{1}{5} - \\frac{1}{7} + \\frac{1}{9} - \\frac{1}{11} + \\dots - \\frac{1}{9999} \\right)$$\n", "\n", @@ -178,7 +256,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The positive terms in the sum have 1, 5, 9, and so on in the denominators. The array `by_four_to_20` contains these numbers up to 17:" + "The positive terms in the sum have 1, 5, 9, and so on in the denominators. The Polars Series `by_four_to_20` contains these numbers up to 17:" ] }, { @@ -187,18 +265,36 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 6, + "metadata": {}, "data": { "text/plain": [ - "array([ 1, 5, 9, 13, 17])" + "shape: (5,)\n", + "Series: 'by_four_to_20' [i64]\n", + "[\n", + "\t1\n", + "\t5\n", + "\t9\n", + "\t13\n", + "\t17\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (5,)
by_four_to_20
i64
1
5
9
13
17
" ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "by_four_to_20 = np.arange(1, 20, 4)\n", + "by_four_to_20 = pl.int_range(1, 20, 4, eager=True).alias(\"by_four_to_20\")\n", "by_four_to_20" ] }, @@ -206,7 +302,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To get an accurate approximation to $\\pi$, we'll use the much longer array `positive_term_denominators`." + "To get an accurate approximation to $\\pi$, we'll use the much longer Polars Series `positive_term_denominators`." ] }, { @@ -215,18 +311,42 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 7, + "metadata": {}, "data": { "text/plain": [ - "array([ 1, 5, 9, ..., 9989, 9993, 9997])" + "shape: (2_500,)\n", + "Series: 'positive_term_denominators' [i64]\n", + "[\n", + "\t1\n", + "\t5\n", + "\t9\n", + "\t13\n", + "\t17\n", + "\t…\n", + "\t9981\n", + "\t9985\n", + "\t9989\n", + "\t9993\n", + "\t9997\n", + "]" + ], + "text/html": [ + "
\n", + "shape: (2_500,)
positive_term_denominators
i64
1
5
9
13
17
…
9981
9985
9989
9993
9997
" ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ - "positive_term_denominators = np.arange(1, 10000, 4)\n", + "positive_term_denominators = pl.int_range(1, 10000, 4, eager=True).alias(\"positive_term_denominators\")\n", "positive_term_denominators" ] }, @@ -250,7 +370,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The negative terms have 3, 7, 11, and so on on in their denominators. This array is just 2 added to `positive_term_denominators`." + "The negative terms have 3, 7, 11, and so on on in their denominators. This Polars Series is just 2 added to `positive_term_denominators`." ] }, { @@ -275,14 +395,14 @@ "metadata": {}, "outputs": [ { + "output_type": "execute_result", + "execution_count": 10, + "metadata": {}, "data": { "text/plain": [ - "3.1413926535917955" + "3.1413926535917938" ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" + } } ], "source": [ From 80949c7e144a5aa6f6c273f02ad552b477660bf7 Mon Sep 17 00:00:00 2001 From: rinman57 Date: Sat, 17 Oct 2026 00:15:52 -0700 Subject: [PATCH 16/17] Ch 5.3 to polars - added extra notes for students to understand `.product()` "The expression below has three pieces:" --- chapters/05/3/More_on_Arrays.ipynb | 139 +++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 37 deletions(-) diff --git a/chapters/05/3/More_on_Arrays.ipynb b/chapters/05/3/More_on_Arrays.ipynb index 179672a8e..6b670b818 100644 --- a/chapters/05/3/More_on_Arrays.ipynb +++ b/chapters/05/3/More_on_Arrays.ipynb @@ -4,10 +4,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# More on Arrays\n", - "It's often necessary to compute something that involves data from more than one array. If two arrays are of the same size, Python makes it easy to do calculations involving both arrays.\n", + "# More on Polars Series\n", + "It's often necessary to compute something that involves data from more than one Polars Series. If two Polars Series are of the same size, Python makes it easy to do calculations involving both Series.\n", "\n", - "For our first example, we return once more to the temperature data. This time, we create arrays of average daily [high](http://berkeleyearth.lbl.gov/auto/Regional/TMAX/Text/global-land-TMAX-Trend.txt) and [low](http://berkeleyearth.lbl.gov/auto/Regional/TMIN/Text/global-land-TMIN-Trend.txt) temperatures for the decades surrounding 1850, 1900, 1950, and 2000." + "For our first example, we return once more to the temperature data. This time, we create Polars Series of average daily [high](http://berkeleyearth.lbl.gov/auto/Regional/TMAX/Text/global-land-TMAX-Trend.txt) and [low](http://berkeleyearth.lbl.gov/auto/Regional/TMIN/Text/global-land-TMIN-Trend.txt) temperatures for the decades surrounding 1850, 1900, 1950, and 2000." ] }, { @@ -20,8 +20,7 @@ }, "outputs": [], "source": [ - "from datascience import *\n", - "import numpy as np\n", + "import polars as pl\n", "path_data = '../../../assets/data/'" ] }, @@ -32,8 +31,25 @@ "outputs": [ { "data": { + "text/html": [ + "
\n", + "shape: (4,)
highs
f64
13.6
14.387
14.585
15.164
" + ], "text/plain": [ - "array([13.6 , 14.387, 14.585, 15.164])" + "shape: (4,)\n", + "Series: 'highs' [f64]\n", + "[\n", + "\t13.6\n", + "\t14.387\n", + "\t14.585\n", + "\t15.164\n", + "]" ] }, "execution_count": 2, @@ -43,10 +59,10 @@ ], "source": [ "baseline_high = 14.48\n", - "highs = make_array(baseline_high - 0.880, \n", + "highs = pl.Series(\"highs\", [baseline_high - 0.880, \n", " baseline_high - 0.093,\n", " baseline_high + 0.105, \n", - " baseline_high + 0.684)\n", + " baseline_high + 0.684])\n", "highs" ] }, @@ -57,8 +73,25 @@ "outputs": [ { "data": { + "text/html": [ + "
\n", + "shape: (4,)
lows
f64
2.128
2.371
2.874
3.728
" + ], "text/plain": [ - "array([2.128, 2.371, 2.874, 3.728])" + "shape: (4,)\n", + "Series: 'lows' [f64]\n", + "[\n", + "\t2.128\n", + "\t2.371\n", + "\t2.874\n", + "\t3.728\n", + "]" ] }, "execution_count": 3, @@ -68,8 +101,8 @@ ], "source": [ "baseline_low = 3.00\n", - "lows = make_array(baseline_low - 0.872, baseline_low - 0.629,\n", - " baseline_low - 0.126, baseline_low + 0.728)\n", + "lows = pl.Series(\"lows\", [baseline_low - 0.872, baseline_low - 0.629,\n", + " baseline_low - 0.126, baseline_low + 0.728])\n", "lows" ] }, @@ -89,8 +122,25 @@ "outputs": [ { "data": { + "text/html": [ + "
\n", + "shape: (4,)
range
f64
11.472
12.016
11.711
11.436
" + ], "text/plain": [ - "array([11.472, 12.016, 11.711, 11.436])" + "shape: (4,)\n", + "Series: 'range' [f64]\n", + "[\n", + "\t11.472\n", + "\t12.016\n", + "\t11.711\n", + "\t11.436\n", + "]" ] }, "execution_count": 4, @@ -99,19 +149,19 @@ } ], "source": [ - "make_array(\n", + "pl.Series(\"range\", [\n", " highs.item(0) - lows.item(0),\n", " highs.item(1) - lows.item(1),\n", " highs.item(2) - lows.item(2),\n", " highs.item(3) - lows.item(3)\n", - ")" + "])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "As when we converted an array of temperatures from Celsius to Fahrenheit, Python provides a much cleaner way to write this:" + "As when we converted a Polars Series of temperatures from Celsius to Fahrenheit, Python provides a much cleaner way to write this:" ] }, { @@ -121,8 +171,25 @@ "outputs": [ { "data": { + "text/html": [ + "
\n", + "shape: (4,)
highs
f64
11.472
12.016
11.711
11.436
" + ], "text/plain": [ - "array([11.472, 12.016, 11.711, 11.436])" + "shape: (4,)\n", + "Series: 'highs' [f64]\n", + "[\n", + "\t11.472\n", + "\t12.016\n", + "\t11.711\n", + "\t11.436\n", + "]" ] }, "execution_count": 5, @@ -138,24 +205,24 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "![Illustration of array subtraction. The highs array is shown on the left followed by a subtraction sign and then the lows array. The arrays are aligned so the numbers in the first position of the array are next to each other, same for the second, third, and fourth positions. Following that is an equal sign and an array representation with the first entry of lows subtracted from the first entry of highs, and the same for the second, third, and fourth entries. Following that is another equal sign with an array showing the result of the subtraction in each entry of the array.](../../../images/array_subtraction.png)" + "![Illustration of Polars Series subtraction. The highs Series is shown on the left followed by a subtraction sign and then the lows Series. The Series are aligned so the numbers in the first position of the Series are next to each other, same for the second, third, and fourth positions. Following that is an equal sign and a Series representation with the first entry of lows subtracted from the first entry of highs, and the same for the second, third, and fourth entries. Following that is another equal sign with a Series showing the result of the subtraction in each entry of the Series.](../../../images/array_subtraction.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "What we've seen in these examples are special cases of a general feature of arrays." + "What we've seen in these examples are special cases of a general feature of Polars Series." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Elementwise arithmetic on pairs of numerical arrays\n", - "If an arithmetic operator acts on two arrays of the same size, then the operation is performed on each corresponding pair of elements in the two arrays. The final result is an array. \n", + "## Elementwise arithmetic on pairs of numerical Polars Series\n", + "If an arithmetic operator acts on two Polars Series of the same size, then the operation is performed on each corresponding pair of elements in the two Series. The final result is a Polars Series. \n", "\n", - "For example, if `array1` and `array2` have the same number of elements, then the value of `array1 * array2` is an array. Its first element is the first element of `array1` times the first element of `array2`, its second element is the second element of `array1` times the second element of `array2`, and so on." + "For example, if `series1` and `series2` have the same number of elements, then the value of `series1 * series2` is a Polars Series. Its first element is the first element of `series1` times the first element of `series2`, its second element is the second element of `series1` times the second element of `series2`, and so on." ] }, { @@ -174,7 +241,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This is a product of \"even/odd\" fractions. Let's use arrays to multiply a million of them, and see if the product is close to $\\pi$." + "This is a product of \"even/odd\" fractions. Let's use Polars Series to multiply a million of them, and see if the product is close to $\\pi$." ] }, { @@ -190,7 +257,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We're now ready to do the calculation. We start by creating an array of even numbers 2, 4, 6, and so on upto 1,000,000. Then we create two lists of odd numbers: 1, 3, 5, 7, ... upto 999,999, and 3, 5, 7, ... upto 1,000,001." + "We're now ready to do the calculation. We start by creating a Polars Series of even numbers 2, 4, 6, and so on upto 1,000,000. Then we create two Polars Series of odd numbers: 1, 3, 5, 7, ... upto 999,999, and 3, 5, 7, ... upto 1,000,001." ] }, { @@ -199,7 +266,8 @@ "metadata": {}, "outputs": [], "source": [ - "even = np.arange(2, 1000001, 2)\n", + "# POLARS_CHANGE: an eager range is named \"literal\" unless alias gives it a name\n", + "even = pl.int_range(2, 1000001, 2, eager=True).alias(\"even\")\n", "one_below_even = even - 1\n", "one_above_even = even + 1" ] @@ -208,7 +276,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Remember that `np.prod` multiplies all the elements of an array together. Now we can calculate Wallis' product, to a good approximation." + "Remember that `product` multiplies all the elements of a Polars Series together. Now we can calculate Wallis' product, to a good approximation.\n", + "\n", + "The expression below has three pieces:\n", + "\n", + "- `even / one_below_even` divides element by element: 2/1, 4/3, 6/5, and so on.\n", + "- `even / one_above_even` divides element by element: 2/3, 4/5, 6/7, and so on.\n", + "- Each `.product()` multiplies every value in that Series into one number. Using just the first three values, `(2/1) * (4/3) * (6/5)` is 3.2, and `(2/3) * (4/5) * (6/7)` is about 0.457.\n", + "\n", + "Those two products are then multiplied together and by 2. With only those three values from each Series, `2 * 3.2 * 0.457` is about 2.926. The cell below uses every value, out to 1,000,000." ] }, { @@ -228,7 +304,7 @@ } ], "source": [ - "2 * np.prod(even/one_below_even) * np.prod(even/one_above_even)" + "2 * (even / one_below_even).product() * (even / one_above_even).product()" ] }, { @@ -242,20 +318,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "(footnotes)=\n", "## Footnotes\n", "[1] As we saw in the example about Leibniz's formula, when we add *infinitely* many fractions, the order can matter. The same is true with multiplying fractions, as we are doing here. But our approximation to $\\pi$ uses only a large finite number of fractions, so it's okay to multiply the terms in any convenient order." ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] } ], "metadata": { From 6181f145b4299517c8163379a6202153f8c81c7e Mon Sep 17 00:00:00 2001 From: rinman57 Date: Fri, 16 Oct 2026 23:56:52 -0700 Subject: [PATCH 17/17] Ch. 5 to polars arrays --> pl.Series