{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Pandas for the NBA Lover\n", "## RPM, PER, and The Anatomy of the DataFrame" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For our first tutorial, we will be looking at a dataset containing two advanced metrics for players from ESPN - Real Plus-Minus (RPM), and Player Efficiency (PER). RPM is based on how a team performs (in terms of point differential) while a player is on the court, adjusted for factors such as teammate quality. PER, on the other hand, summarizes a player's box-score contributions into one statistic, and can be compared across players and seasons. \n", "\n", "Each of the next few tutorials will use this dataset, and as we build our pandas knowledge, we will gain more insight into both PER and RPM, including what each metric is and isn't good at measuring.\n", "\n", "For our first tutorial, we will learn about the **DataFrame**, the core data structure of the pandas library. In particular, we will learn about the key concepts and the terms, definitions, and rules that govern how DataFrames are used. At the end, we will produce a chart illustrating how PER and RPM vary across player's in the league." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First things first, let's import the pandas library." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "# formatting options: \n", "pd.set_option('display.max_rows', 10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What is a DataFrame?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A DataFrame is a data structure that makes it easy to work with tabular data.\n", "\n", "Let's create our first DataFrame by reading a `.csv` file containing our data. The first few rows of our dataset look like this:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "PLAYER,MPG,TEAM,POS,TS%,AST,TO,USG,ORR,DRR,REBR,PER,ORPM,DRPM,RPM\r\n", "James Harden,37.1,HOU,PG,0.622,20.8,13.5,40.0,2.1,17.0,9.3,29.21,7.76,-0.06,7.7\r\n", "Anthony Davis,36.9,NO,PF,0.598,14.3,6.7,29.3,10.0,27.7,19.1,31.09,3.93,3.24,7.17\r\n", "Paul George,35.7,OKC,SF,0.574,13.0,9.0,29.6,4.3,19.3,11.7,23.29,3.82,2.85,6.67\r\n", "Nikola Jokic,31.3,DEN,C,0.5870000000000001,27.6,12.0,29.1,9.7,25.6,17.6,26.09,4.46,1.83,6.29\r\n", "Kyrie Irving,32.1,BOS,PG,0.5920000000000001,22.9,8.9,29.9,3.8,12.2,8.0,24.55,4.6,0.92,5.52\r\n" ] } ], "source": [ "!cat ../data/advanced_metrics.csv | head -n 6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are a variety of ways to loading data into a DataFrame, a few of which we will cover in later sections. We use the `read_csv()` method here, which takes a filename string as a parameter:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "pandas.core.frame.DataFrame" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.read_csv(\"../data/advanced_metrics.csv\")\n", "type(df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Quick Peek into DataFrame Functionality" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before diving into technical details of what a DataFrame is, let's take a quick peek at some of the things we can do with our DataFrame.

The `head()` method prints the DataFrame's first 5 rows:" ] }, { "cell_type": "code", "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
PLAYERMPGTEAMPOSTS%ASTTOUSGORRDRRREBRPERORPMDRPMRPM
0James Harden37.1HOUPG0.62220.813.540.02.117.09.329.217.76-0.067.70
1Anthony Davis36.9NOPF0.59814.36.729.310.027.719.131.093.933.247.17
2Paul George35.7OKCSF0.57413.09.029.64.319.311.723.293.822.856.67
3Nikola Jokic31.3DENC0.58727.612.029.19.725.617.626.094.461.836.29
4Kyrie Irving32.1BOSPG0.59222.98.929.93.812.28.024.554.600.925.52
\n", "
" ], "text/plain": [ " PLAYER MPG TEAM POS TS% AST TO USG ORR DRR REBR \\\n", "0 James Harden 37.1 HOU PG 0.622 20.8 13.5 40.0 2.1 17.0 9.3 \n", "1 Anthony Davis 36.9 NO PF 0.598 14.3 6.7 29.3 10.0 27.7 19.1 \n", "2 Paul George 35.7 OKC SF 0.574 13.0 9.0 29.6 4.3 19.3 11.7 \n", "3 Nikola Jokic 31.3 DEN C 0.587 27.6 12.0 29.1 9.7 25.6 17.6 \n", "4 Kyrie Irving 32.1 BOS PG 0.592 22.9 8.9 29.9 3.8 12.2 8.0 \n", "\n", " PER ORPM DRPM RPM \n", "0 29.21 7.76 -0.06 7.70 \n", "1 31.09 3.93 3.24 7.17 \n", "2 23.29 3.82 2.85 6.67 \n", "3 26.09 4.46 1.83 6.29 \n", "4 24.55 4.60 0.92 5.52 " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `shape` property tells us our DataFrame has 343 rows and 15 columns, respectively:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(343, 15)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `describe()` method gives us a quick summary of our data:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true }, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MPGTS%ASTTOUSGORRDRRREBRPERORPMDRPMRPM
count343.0343.0343.0343.0343.0343.0343.0343.0343.0343.0343.0343.0
mean23.90.616.910.219.24.715.29.914.4-0.3-0.0-0.4
std7.10.17.62.65.43.86.34.74.81.81.52.3
min9.30.43.51.88.20.24.53.24.7-4.0-4.4-7.2
25%17.90.511.28.515.12.010.26.311.3-1.6-1.0-1.9
50%24.40.615.610.118.23.313.68.613.6-0.6-0.1-0.6
75%29.60.621.011.922.76.518.612.617.20.71.01.0
max37.10.742.919.240.017.836.525.531.17.84.17.7
\n", "
" ], "text/plain": [ " MPG TS% AST TO USG ORR DRR REBR PER ORPM \\\n", "count 343.0 343.0 343.0 343.0 343.0 343.0 343.0 343.0 343.0 343.0 \n", "mean 23.9 0.6 16.9 10.2 19.2 4.7 15.2 9.9 14.4 -0.3 \n", "std 7.1 0.1 7.6 2.6 5.4 3.8 6.3 4.7 4.8 1.8 \n", "min 9.3 0.4 3.5 1.8 8.2 0.2 4.5 3.2 4.7 -4.0 \n", "25% 17.9 0.5 11.2 8.5 15.1 2.0 10.2 6.3 11.3 -1.6 \n", "50% 24.4 0.6 15.6 10.1 18.2 3.3 13.6 8.6 13.6 -0.6 \n", "75% 29.6 0.6 21.0 11.9 22.7 6.5 18.6 12.6 17.2 0.7 \n", "max 37.1 0.7 42.9 19.2 40.0 17.8 36.5 25.5 31.1 7.8 \n", "\n", " DRPM RPM \n", "count 343.0 343.0 \n", "mean -0.0 -0.4 \n", "std 1.5 2.3 \n", "min -4.4 -7.2 \n", "25% -1.0 -1.9 \n", "50% -0.1 -0.6 \n", "75% 1.0 1.0 \n", "max 4.1 7.7 " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.describe().round(decimals=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The cells above demonstrate that we can loosely describe a DataFrame as a structure equipped with numerous methods for working with tabular data. Let's now turn to two of the DataFrame's underlying structures, the **Series** and the **Index**. Becoming familiar with these structures will help us build the necessary groundwork to work with pandas effectively." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The DataFrame: A Labeled Container" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A DataFrame is also described as a \"labeled container\" for tabular data. The first level of labels are the columns - we can use column names to select data for a column in our DataFrame the same way we would select a value in a Python dictionary using a key. Let's start with RPM: \n", "\n", "Note: selecting data will be covered much more in depth in the next section." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/plain": [ "0 7.70\n", "1 7.17\n", "2 6.67\n", "3 6.29\n", "4 5.52\n", " ... \n", "338 -5.30\n", "339 -5.59\n", "340 -6.02\n", "341 -6.14\n", "342 -7.17\n", "Name: RPM, Length: 343, dtype: float64" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df['RPM']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see from the output our dataset is already sorted in terms of descending RPM values. However, there's one slight problem: it isn't immeadiately clear which player each data point corresponds to - all we see is a column with numbers from 0 to 342 to the left." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Fortunately, this is easy to fix." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The Index" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The second level of labeling in a DataFrame are the rows. Every row in a DataFrame has a \"name\", which are formally referred to as **labels**. Collectively, these labels are known as an **Index**, and can be accessed through the DataFrame's `.index` property. We didn't specify how we wanted to label our rows when we created our DataFrame, so the index we see is the one pandas created one for us, ranging from 0 to the number of rows in our data." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "RangeIndex(start=0, stop=343, step=1)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.index" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Although they can be anything we want them to be, the labels of an Index often come from a column in the original dataset. Let's now go ahead and reload our DataFrame with the `index_col` parameter set to the first column, the \"Player\" column:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Index(['James Harden', 'Anthony Davis', 'Paul George', 'Nikola Jokic',\n", " 'Kyrie Irving', 'Stephen Curry', 'Nikola Vucevic', 'Kyle Lowry',\n", " 'LeBron James', 'Giannis Antetokounmpo',\n", " ...\n", " 'Mo Bamba', 'Avery Bradley', 'Jonathon Simmons', 'Antonio Blakeney',\n", " 'Cedi Osman', 'Allonzo Trier', 'Frank Ntilikina', 'Kevin Knox',\n", " 'Jamal Crawford', 'Collin Sexton'],\n", " dtype='object', name='PLAYER', length=343)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_with_index = pd.read_csv(\"../data/advanced_metrics.csv\", index_col=0)\n", "df_with_index.index" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, when we select RPM again, we see the corresponding player names in the output, which is much more useful:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PLAYER\n", "James Harden 7.70\n", "Anthony Davis 7.17\n", "Paul George 6.67\n", "Nikola Jokic 6.29\n", "Kyrie Irving 5.52\n", " ... \n", "Allonzo Trier -5.30\n", "Frank Ntilikina -5.59\n", "Kevin Knox -6.02\n", "Jamal Crawford -6.14\n", "Collin Sexton -7.17\n", "Name: RPM, Length: 343, dtype: float64" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_with_index['RPM']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Got to love the Young Bull Collin Sexton, the number 8 overall draft pick, coming in last place!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Columns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The column names of our Dataframe are also stored in an index data structure, which we can see by accessing the `columns` attribute:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Index(['PLAYER', 'MPG', 'TEAM', 'POS', 'TS%', 'AST', 'TO', 'USG', 'ORR', 'DRR',\n", " 'REBR', 'PER', 'ORPM', 'DRPM', 'RPM'],\n", " dtype='object')" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.columns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Because they are stored in an Index, columm names can also be referred to as labels. However, \"the index\" of a DataFrame always refers to the index which labels the rows." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Each Column is a Series" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The data associated with each of these column labels have the data type **Series**, which is another pandas data object:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "pandas.core.series.Series" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rpm = df_with_index['RPM']\n", "type(rpm)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A Series is a one-dimensional labeled list of data values, where each \"row\" has a label. You'll notice these labels are the exactly the same as the index labels in our original DataFrame." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PLAYER\n", "James Harden 7.70\n", "Anthony Davis 7.17\n", "Paul George 6.67\n", "Nikola Jokic 6.29\n", "Kyrie Irving 5.52\n", " ... \n", "Allonzo Trier -5.30\n", "Frank Ntilikina -5.59\n", "Kevin Knox -6.02\n", "Jamal Crawford -6.14\n", "Collin Sexton -7.17\n", "Name: RPM, Length: 343, dtype: float64" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rpm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Like the DataFrame, these labels can be accessed through the `.index` property." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Index(['James Harden', 'Anthony Davis', 'Paul George', 'Nikola Jokic',\n", " 'Kyrie Irving', 'Stephen Curry', 'Nikola Vucevic', 'Kyle Lowry',\n", " 'LeBron James', 'Giannis Antetokounmpo',\n", " ...\n", " 'Mo Bamba', 'Avery Bradley', 'Jonathon Simmons', 'Antonio Blakeney',\n", " 'Cedi Osman', 'Allonzo Trier', 'Frank Ntilikina', 'Kevin Knox',\n", " 'Jamal Crawford', 'Collin Sexton'],\n", " dtype='object', name='PLAYER', length=343)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rpm.index" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " A Series also has a name, which was the name of the column in our original DataFrame." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'RPM'" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rpm.name" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These observations leads to a more precise description of a DataFrame: a DataFrame is a group of equal length Series objects, glued together by a shared index. The names of the Series objects are the columns of the DataFrame." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Recap" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above sections illustrate the concept of a \"labeled container\" for tabular data. Thanks to spreadsheets and database tables, we're already familiar with the idea of labeled columns of data. But each row of a DataFrame also has a label, which taken together, are known as the DataFrame's index. This has some important consequences, one of which we'll see below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's now take a quick look at how RPM and PER vary for players across the league:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Why is the Index Important?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aside from labeling rows of data, a DataFrame's index has many other important functions. For example, the index determines how data is visualized.\n", "\n", "As I mentioned in the introduction to this tutorial series, pandas is popular because it simplifies data analysis. Case in point: it only takes a few lines of code to produce a chart showing the distribution of RPM across the league:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "rpm.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Producing the same chart for PER is a little bit more invovled, since we want to first sort our values to get the same type of curve:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "df_with_index['PER'].sort_values(ascending=False).plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Right off the bat, we can make a couple of observations. RPM has a symmetric distribution, which makes sense because it is rooted in point-differential data, and the point differiential across the entire league is 0. PER is much less symmetric, and it looks as if differences in production (as measured by PER) is much more pronounced at the top of the league than it is at the bottom. Pandas made the above analysis simple. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But taking advantage of this simplicity requires pre-requisite knowledge. The above visual was so easy to create because under the hood, pandas used our series's index labels (the player names) as the x-axis values of our plot. Pandas is full of subtle details like this, which can equally annoying and confusing at times. But if you've made it this far, you're well on your way to understanding them." ] } ], "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.6.5" } }, "nbformat": 4, "nbformat_minor": 2 }