{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Index alignment\n", "\n", "To illustrate how index alignment can sometimes lead to problems, let's consider the following example: suppose we're throwing a party, and we plan to give people prizes based on the order in which they arrive. The first person to arrive at the party will get 20 dollars, the second will get 10 dollars, and the third person doesn't get anything. \n", "\n", "To keep track of how many prizes everyone gets, we build a DataFrame with all the party attendees, their arrival order, and a column for keeping track of how much they've received in prizes. \n", "\n", "We can also build a Series with the prize amounts we plan to give people. \n", "\n", "### Exercise 1\n", "\n", "Use the code below to get started: \n", "\n", "```python\n", "import pandas as pd\n", "\n", "attendees = pd.DataFrame(\n", " {\n", " \"names\": [\"Jill\", \"Kumar\", \"Zaira\"],\n", " \"prizes\": [0, 0, 0],\n", " \"arrival_order\": [2, 1, 3],\n", " }\n", ")\n", "arrival_prizes = pd.Series([20, 10, 0])\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise 2\n", "\n", "Now let's sort our `attendees` list by `arrival_order` so that the first row is the person who arrived first, the second is the person who arrived second, etc. to match how we've organized `arrival_prizes`. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise 3\n", "\n", "Now let's \"give\" everyone their arrival prizes by adding arrival prizes to people's prize column: \n", "\n", "```python\n", "attendees[\"prizes\"] = attendees[\"prizes\"] + arrival_prizes\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise 4\n", "\n", "Now let's look at the result. Does it look like what you expected? Do you know what went wrong?\n", "\n", "After you've formulated your thoughts, continue to [Discussion](Exercise_indices_discussion.ipynb). " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise 5\n", "\n", "If you ever *want* to get alignment on row numbers, the easiest way to achieve that is to reset the indices on both objects you want to merge. When one re-sets indices without specifying a column to become the new index, the new index will just be row-numbers. \n", "\n", "So reset prizes to 0, do what you need to do to get the order right, reset the index, and try again." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note:** When you reset the index on a Series, the Series is converted to a DataFrame, and the old index is added as a column. To avoid this behavior and just drop the old index when re-setting indices (in either a Series or a DataFrame), use the `drop=True` argument when resetting the index. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise 6\n", "\n", "OK, so besides doing automatic alignment, is there a reason to use indices?\n", "\n", "Let's find out. Create the following fake dataset of social security numbers and some \"names\" (random strings). Warning: this will take a little time to run. \n", "\n", "```python\n", "import numpy.random as npr\n", "import string\n", "import random\n", "\n", "npr.seed(42)\n", "random.seed(42)\n", "\n", "size = 1000000 # 1,000,000\n", "people = pd.DataFrame(\n", " {\n", " \"social_security_numbers\": npr.randint(low=10000000, high=99999999, size=size),\n", " \"names\": [\n", " \"\".join(random.choices(string.ascii_uppercase, k=10)) for i in range(size)\n", " ],\n", " }\n", ")\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise 7\n", "\n", "Now subset your data to get the social security number associated with the name of \"TPKSMSLREI\". (Yes, there are ways to get real random names, but they take a while to run because they query websites that generate fake names, so we're just doing this!)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise 8\n", "\n", "Now time your operation using the `%timeit` ipython magic function. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise 9\n", "\n", "Now make `names` your index for this data. Then try subsetting using `loc[]` to get all the observations with the name of \"TPKSMSLREI\" and time the operation. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Take-away\n", "\n", "So in short: indices can be nice in that they do automatic alignment, provided you're expecting it. Moreover, if you want to pull random rows out of your dataset, it is often much faster than a regular query!" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.4" } }, "nbformat": 4, "nbformat_minor": 4 }