diff --git a/python-data/notebooks/ex01_numpy_arrays.ipynb b/python-data/notebooks/ex01_numpy_arrays.ipynb index 1a3cc78..c74be41 100644 --- a/python-data/notebooks/ex01_numpy_arrays.ipynb +++ b/python-data/notebooks/ex01_numpy_arrays.ipynb @@ -143,7 +143,7 @@ "\n", "- Create an array of shape (2, 3, 4) of zeros\n", "- Create an array of shape (2, 3, 4) of ones.\n", - "- Create an array with values 0 to 999 using the `np.arrange` function." + "- Create an array with values 0 to 999 using the `np.arange` function." ] }, { diff --git a/python-data/slides/02_python_text_formats.pdf b/python-data/slides/02_python_text_formats.pdf index 655cb24..bec9544 100644 Binary files a/python-data/slides/02_python_text_formats.pdf and b/python-data/slides/02_python_text_formats.pdf differ diff --git a/python-data/slides/02_python_text_formats.pptx b/python-data/slides/02_python_text_formats.pptx index 099d47b..7f8b006 100644 Binary files a/python-data/slides/02_python_text_formats.pptx and b/python-data/slides/02_python_text_formats.pptx differ diff --git a/python-data/slides/04_binary_formats.pdf b/python-data/slides/04_binary_formats.pdf index 75ad03b..f22cd0a 100644 Binary files a/python-data/slides/04_binary_formats.pdf and b/python-data/slides/04_binary_formats.pdf differ diff --git a/python-data/slides/04_binary_formats.pptx b/python-data/slides/04_binary_formats.pptx index 1859e30..bbe2d01 100644 Binary files a/python-data/slides/04_binary_formats.pptx and b/python-data/slides/04_binary_formats.pptx differ diff --git a/python-data/slides/05_netcdf_overview.pdf b/python-data/slides/05_netcdf_overview.pdf index 1fa0bb7..ae55f18 100644 Binary files a/python-data/slides/05_netcdf_overview.pdf and b/python-data/slides/05_netcdf_overview.pdf differ diff --git a/python-data/slides/05_netcdf_overview.pptx b/python-data/slides/05_netcdf_overview.pptx index 6c98780..06e2b0a 100644 Binary files a/python-data/slides/05_netcdf_overview.pptx and b/python-data/slides/05_netcdf_overview.pptx differ diff --git a/python-data/slides/07_ncgen_ncdump_cdl.pdf b/python-data/slides/07_ncgen_ncdump_cdl.pdf index ef55bad..923e50c 100644 Binary files a/python-data/slides/07_ncgen_ncdump_cdl.pdf and b/python-data/slides/07_ncgen_ncdump_cdl.pdf differ diff --git a/python-data/slides/07_ncgen_ncdump_cdl.pptx b/python-data/slides/07_ncgen_ncdump_cdl.pptx index ed5f216..1f2837e 100644 Binary files a/python-data/slides/07_ncgen_ncdump_cdl.pptx and b/python-data/slides/07_ncgen_ncdump_cdl.pptx differ diff --git a/python-data/slides/09_cfchecker.pdf b/python-data/slides/09_cfchecker.pdf index 6f0e118..b69121a 100644 Binary files a/python-data/slides/09_cfchecker.pdf and b/python-data/slides/09_cfchecker.pdf differ diff --git a/python-data/slides/09_cfchecker.pptx b/python-data/slides/09_cfchecker.pptx index 8b3cc34..7dd9523 100644 Binary files a/python-data/slides/09_cfchecker.pptx and b/python-data/slides/09_cfchecker.pptx differ diff --git a/python-data/solutions/ex01_numpy_arrays_solutions.ipynb b/python-data/solutions/ex01_numpy_arrays_solutions.ipynb index 8947b66..09ec90c 100644 --- a/python-data/solutions/ex01_numpy_arrays_solutions.ipynb +++ b/python-data/solutions/ex01_numpy_arrays_solutions.ipynb @@ -173,7 +173,7 @@ "\n", "- Create an array of shape (2, 3, 4) of zeros and print.\n", "- Create an array of shape (2, 3, 4) of ones and print.\n", - "- Create an array with values 0 to 999 using the `np.arrange` function and print." + "- Create an array with values 0 to 999 using the `np.arange` function and print." ] }, { diff --git a/python-data/solutions/ex05_pandas.ipynb b/python-data/solutions/ex05_pandas.ipynb new file mode 100644 index 0000000..47c1975 --- /dev/null +++ b/python-data/solutions/ex05_pandas.ipynb @@ -0,0 +1,1680 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1a4fb627-2190-43ac-b4b5-93352cd23aa4", + "metadata": {}, + "source": [ + "# Working with Pandas DataFrames in Python\n", + "\n", + "Part of: Data Analysis and Visualization in Python for EcologistsData Analysis and Visualization in Python for Ecologists (**Data Carpentry**)\n", + "\n", + "From: https://datacarpentry.org/python-ecology-lesson/02-starting-with-data/index.htmlhttps://datacarpentry.org/python-ecology-lesson/02-starting-with-data/index.html\n", + "\n", + "teaching: 30 mins\n", + "exercises: 30 mins\n", + "\n", + "Questions:\n", + "- \"How can I import data in Python?\"\n", + "- \"What is Pandas?\"\n", + "- \"Why should I use Pandas to work with data?\"\n", + " \n", + "Objectives:\n", + "- \"Navigate the workshop directory and download a dataset.\"\n", + "- \"Explain what a library is and what libraries are used for.\"\n", + "- \"Describe what the Python Data Analysis Library (Pandas) is.\"\n", + "- \"Load the Python Data Analysis Library (Pandas).\"\n", + "- \"Use `read_csv` to read tabular data into Python.\"\n", + "- \"Describe what a DataFrame is in Python.\"\n", + "- \"Access and summarize data stored in a DataFrame.\"\n", + "- \"Define indexing as it relates to data structures.\"\n", + "- \"Perform basic mathematical operations and summary statistics on data in a Pandas DataFrame.\"\n", + "- \"Create simple plots.\"\n", + " \n", + "Key points:\n", + "- \"Libraries enable us to extend the functionality of Python.\"\n", + "- \"Pandas is a popular library for working with data.\"\n", + "- \"A Dataframe is a Pandas data structure that allows one to access data by column (name or index) or row.\"\n", + "- \"Aggregating data using the `groupby()` function enables you to generate useful summaries of data quickly.\"\n", + "- \"Plots can be created from DataFrames or subsets of data that have been generated with `groupby()`.\"\n", + " \n" + ] + }, + { + "cell_type": "markdown", + "id": "3c62fdbe-6cd7-473a-b1d8-288bd5dec187", + "metadata": {}, + "source": [ + "We can automate the process of performing data manipulations in Python. It's efficient to spend time\n", + "building the code to perform these tasks because once it's built, we can use it\n", + "over and over on different datasets that use a similar format. This makes our\n", + "methods easily reproducible. We can also easily share our code with colleagues\n", + "and they can replicate the same analysis.\n", + "\n", + "### Starting in the same spot\n", + "\n", + "To help the lesson run smoothly, let's ensure everyone is in the same directory.\n", + "This should help us avoid path and file name issues. At this time please\n", + "navigate to the workshop directory. If you are working in Jupyter Notebook be sure\n", + "that you start your notebook in the workshop directory.\n", + "\n", + "A quick aside that there are Python libraries like [OS Library][os-lib] that can work with our\n", + "directory structure, however, that is not our focus today." + ] + }, + { + "cell_type": "markdown", + "id": "d3fd3a90-3455-4df0-a4f4-9a327d81b177", + "metadata": {}, + "source": [ + "### Our Data\n", + "\n", + "For this lesson, we will be using the Portal Teaching data, a subset of the data\n", + "from Ernst et al\n", + "[Long-term monitoring and experimental manipulation of a Chihuahuan Desert ecosystem near Portal,\n", + "Arizona, USA][ernst].\n", + "\n", + "We will be using files from the [Portal Project Teaching Database][pptd].\n", + "This section will use the `surveys.csv` file that can be downloaded here:\n", + "[https://ndownloader.figshare.com/files/2292172][figshare-ndownloader]\n", + "\n", + "We are studying the species and weight of animals caught in sites in our study\n", + "area. The dataset is stored as a `.csv` file: each row holds information for a\n", + "single animal, and the columns represent:\n", + "\n", + "| Column | Description |\n", + "|------------------|------------------------------------|\n", + "| record_id | Unique id for the observation |\n", + "| month | month of observation |\n", + "| day | day of observation |\n", + "| year | year of observation |\n", + "| plot_id | ID of a particular site |\n", + "| species_id | 2-letter code |\n", + "| sex | sex of animal (\"M\", \"F\") |\n", + "| hindfoot_length | length of the hindfoot in mm |\n", + "| weight | weight of the animal in grams |\n", + "\n", + "\n", + "The first few rows of our first file look like this:\n", + "\n", + "```\n", + "record_id,month,day,year,plot_id,species_id,sex,hindfoot_length,weight\n", + "1,7,16,1977,2,NL,M,32,\n", + "2,7,16,1977,3,NL,M,33,\n", + "3,7,16,1977,2,DM,F,37,\n", + "4,7,16,1977,7,DM,M,36,\n", + "5,7,16,1977,3,DM,M,35,\n", + "6,7,16,1977,1,PF,M,14,\n", + "7,7,16,1977,2,PE,F,,\n", + "8,7,16,1977,1,DM,M,37,\n", + "9,7,16,1977,1,DM,F,34,\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0e8a0333-7d52-4739-a9d7-ee2388a07033", + "metadata": {}, + "outputs": [], + "source": [ + "# Download the file\n", + "import requests\n", + "url = \"https://ndownloader.figshare.com/files/2292172\"\n", + "content = requests.get(url).text\n", + "\n", + "datafile = \"surveys.csv\"\n", + "with open(datafile, \"w\") as csv:\n", + " csv.write(content)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f73c654d-65fc-40bc-a02f-b708eec455dd", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "id": "6c9ee6ef-0b55-404e-8757-678e7a760dd1", + "metadata": {}, + "source": [ + "Each time we call a function that's in a library, we use the syntax\n", + "`LibraryName.FunctionName`. Adding the library name with a `.` before the\n", + "function name tells Python where to find the function. In the example above, we\n", + "have imported Pandas as `pd`. This means we don't have to type out `pandas` each\n", + "time we call a Pandas function.\n", + "\n", + "\n", + "# Reading CSV Data Using Pandas\n", + "\n", + "We will begin by locating and reading our survey data which are in CSV format. CSV stands for\n", + "Comma-Separated Values and is a common way to store formatted data. Other symbols may also be used, so\n", + "you might see tab-separated, colon-separated or space separated files. It is quite easy to replace\n", + "one separator with another, to match your application. The first line in the file often has headers\n", + "to explain what is in each column. CSV (and other separators) make it easy to share data, and can be\n", + "imported and exported from many applications, including Microsoft Excel. For more details on CSV\n", + "files, see the [Data Organisation in Spreadsheets][spreadsheet-lesson5] lesson.\n", + "We can use Pandas' `read_csv` function to pull the file directly into a [DataFrame][pd-dataframe].\n", + "\n", + "## So What's a DataFrame?\n", + "\n", + "A DataFrame is a 2-dimensional data structure that can store data of different\n", + "types (including characters, integers, floating point values, factors and more)\n", + "in columns. It is similar to a spreadsheet or an SQL table or the `data.frame` in\n", + "R. A DataFrame always has an index (0-based). An index refers to the position of\n", + "an element in the data structure." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "eb36110d-ebc1-4376-8e13-abe486c128f9", + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
record_idmonthdayyearplot_idspecies_idsexhindfoot_lengthweight
0171619772NLM32.0NaN
1271619773NLM33.0NaN
2371619772DMF37.0NaN
3471619777DMM36.0NaN
4571619773DMM35.0NaN
..............................
35544355451231200215AHNaNNaNNaN
35545355461231200215AHNaNNaNNaN
35546355471231200210RMF15.014.0
3554735548123120027DOM36.051.0
3554835549123120025NaNNaNNaNNaN
\n", + "

35549 rows × 9 columns

\n", + "
" + ], + "text/plain": [ + " record_id month day year plot_id species_id sex hindfoot_length \\\n", + "0 1 7 16 1977 2 NL M 32.0 \n", + "1 2 7 16 1977 3 NL M 33.0 \n", + "2 3 7 16 1977 2 DM F 37.0 \n", + "3 4 7 16 1977 7 DM M 36.0 \n", + "4 5 7 16 1977 3 DM M 35.0 \n", + "... ... ... ... ... ... ... ... ... \n", + "35544 35545 12 31 2002 15 AH NaN NaN \n", + "35545 35546 12 31 2002 15 AH NaN NaN \n", + "35546 35547 12 31 2002 10 RM F 15.0 \n", + "35547 35548 12 31 2002 7 DO M 36.0 \n", + "35548 35549 12 31 2002 5 NaN NaN NaN \n", + "\n", + " weight \n", + "0 NaN \n", + "1 NaN \n", + "2 NaN \n", + "3 NaN \n", + "4 NaN \n", + "... ... \n", + "35544 NaN \n", + "35545 NaN \n", + "35546 14.0 \n", + "35547 51.0 \n", + "35548 NaN \n", + "\n", + "[35549 rows x 9 columns]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Note that pd.read_csv is used because we imported pandas as pd\n", + "pd.read_csv(datafile)" + ] + }, + { + "cell_type": "markdown", + "id": "3686eebc-e266-4496-99ff-475f69ec72ce", + "metadata": {}, + "source": [ + "We can see that there were 35,549 rows parsed. Each row has 9\n", + "columns. The first column is the index of the DataFrame. The index is used to\n", + "identify the position of the data, but it is not an actual column of the DataFrame.\n", + "It looks like the `read_csv` function in Pandas read our file properly. However,\n", + "we haven't saved any data to memory so we can work with it. We need to assign the\n", + "DataFrame to a variable. Remember that a variable is a name for a value, such as `x`,\n", + "or `data`. We can create a new object with a variable name by assigning a value to it using `=`.\n", + "\n", + "Let's call the imported survey data `surveys_df`:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9c692fd0-32cf-4dad-be80-64458c563ab1", + "metadata": {}, + "outputs": [], + "source": [ + "surveys_df = pd.read_csv(datafile)" + ] + }, + { + "cell_type": "markdown", + "id": "dcefc541-b4ac-4ebc-93ed-8348180f7779", + "metadata": {}, + "source": [ + "Notice when you assign the imported DataFrame to a variable, Python does not\n", + "produce any output on the screen. We can view the value of the `surveys_df`\n", + "object by typing its name into the Python command prompt." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "5429befb-4dba-4251-9071-a259e96738e4", + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
record_idmonthdayyearplot_idspecies_idsexhindfoot_lengthweight
0171619772NLM32.0NaN
1271619773NLM33.0NaN
2371619772DMF37.0NaN
3471619777DMM36.0NaN
4571619773DMM35.0NaN
..............................
35544355451231200215AHNaNNaNNaN
35545355461231200215AHNaNNaNNaN
35546355471231200210RMF15.014.0
3554735548123120027DOM36.051.0
3554835549123120025NaNNaNNaNNaN
\n", + "

35549 rows × 9 columns

\n", + "
" + ], + "text/plain": [ + " record_id month day year plot_id species_id sex hindfoot_length \\\n", + "0 1 7 16 1977 2 NL M 32.0 \n", + "1 2 7 16 1977 3 NL M 33.0 \n", + "2 3 7 16 1977 2 DM F 37.0 \n", + "3 4 7 16 1977 7 DM M 36.0 \n", + "4 5 7 16 1977 3 DM M 35.0 \n", + "... ... ... ... ... ... ... ... ... \n", + "35544 35545 12 31 2002 15 AH NaN NaN \n", + "35545 35546 12 31 2002 15 AH NaN NaN \n", + "35546 35547 12 31 2002 10 RM F 15.0 \n", + "35547 35548 12 31 2002 7 DO M 36.0 \n", + "35548 35549 12 31 2002 5 NaN NaN NaN \n", + "\n", + " weight \n", + "0 NaN \n", + "1 NaN \n", + "2 NaN \n", + "3 NaN \n", + "4 NaN \n", + "... ... \n", + "35544 NaN \n", + "35545 NaN \n", + "35546 14.0 \n", + "35547 51.0 \n", + "35548 NaN \n", + "\n", + "[35549 rows x 9 columns]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "surveys_df" + ] + }, + { + "cell_type": "markdown", + "id": "3c8b9fbf-5b0a-44b2-ae9b-2cbc094f2eeb", + "metadata": {}, + "source": [ + "Note: if the output is too wide to print on your narrow terminal window, you may see something\n", + "slightly different as the large set of data scrolls past. You may see simply the last column\n", + "of data.\n", + "\n", + "Never fear, all the data is there, if you scroll up. Selecting just a few rows, so it is\n", + "easier to fit on one window, you can see that pandas has neatly formatted the data to fit\n", + "our screen:Never fear, all the data is there, if you scroll up. Selecting just a few rows, so it is\n", + "easier to fit on one window, you can see that pandas has neatly formatted the data to fit\n", + "our screen:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "7fa897f3-1237-434e-a4dd-44c1654578bd", + "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", + "
record_idmonthdayyearplot_idspecies_idsexhindfoot_lengthweight
0171619772NLM32.0NaN
1271619773NLM33.0NaN
2371619772DMF37.0NaN
3471619777DMM36.0NaN
4571619773DMM35.0NaN
\n", + "
" + ], + "text/plain": [ + " record_id month day year plot_id species_id sex hindfoot_length \\\n", + "0 1 7 16 1977 2 NL M 32.0 \n", + "1 2 7 16 1977 3 NL M 33.0 \n", + "2 3 7 16 1977 2 DM F 37.0 \n", + "3 4 7 16 1977 7 DM M 36.0 \n", + "4 5 7 16 1977 3 DM M 35.0 \n", + "\n", + " weight \n", + "0 NaN \n", + "1 NaN \n", + "2 NaN \n", + "3 NaN \n", + "4 NaN " + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "surveys_df.head() # The head() method displays the first several lines of a file. It\n", + " # is discussed below." + ] + }, + { + "cell_type": "markdown", + "id": "e1a68826-2a82-4700-8f3f-b543fb1c3c13", + "metadata": {}, + "source": [ + "## Exploring our Species Survey Data\n", + "\n", + "Again, we can use the `type` function to see what kind of thing `surveys_df` is:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "86fe32ef-6617-479c-9776-c0efa316e65f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "pandas.core.frame.DataFrame" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(surveys_df)" + ] + }, + { + "cell_type": "markdown", + "id": "7002ed40-3eca-49f9-8bb9-541e37c332e8", + "metadata": {}, + "source": [ + "As expected, it's a DataFrame (or, to use the full name that Python uses to refer\n", + "to it internally, a `pandas.core.frame.DataFrame`).\n", + "\n", + "What kind of things does `surveys_df` contain? DataFrames have an attribute\n", + "called `dtypes` that answers this:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "c586df32-ef8e-45c3-ad46-21c7f6aab133", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "record_id int64\n", + "month int64\n", + "day int64\n", + "year int64\n", + "plot_id int64\n", + "species_id object\n", + "sex object\n", + "hindfoot_length float64\n", + "weight float64\n", + "dtype: object" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "surveys_df.dtypes" + ] + }, + { + "cell_type": "markdown", + "id": "38184683-6906-4893-8289-3d756b1fbf08", + "metadata": {}, + "source": [ + "All the values in a column have the same type. For example, months have type\n", + "`int64`, which is a kind of integer. Cells in the month column cannot have\n", + "fractional values, but the weight and hindfoot_length columns can, because they\n", + "have type `float64`. The `object` type doesn't have a very helpful name, but in\n", + "this case it represents strings (such as 'M' and 'F' in the case of sex).\n", + "\n", + "We'll talk a bit more about what the different formats mean in a different lesson.\n", + "\n", + "### Useful Ways to View DataFrame objects in Python\n", + "\n", + "There are many ways to summarize and access the data stored in DataFrames,\n", + "using attributes and methods provided by the DataFrame object.\n", + "\n", + "To access an attribute, use the DataFrame object name followed by the attribute\n", + "name `df_object.attribute`. Using the DataFrame `surveys_df` and attribute\n", + "`columns`, an index of all the column names in the DataFrame can be accessed\n", + "with `surveys_df.columns`.\n", + "\n", + "Methods are called in a similar fashion using the syntax `df_object.method()`.\n", + "As an example, `surveys_df.head()` gets the first few rows in the DataFrame\n", + "`surveys_df` using **the `head()` method**. With a method, we can supply extra\n", + "information in the parens to control behaviour.\n", + "\n", + "Let's look at the data using these.\n", + "\n", + "> ## Challenge - DataFrames\n", + ">\n", + "> Using our DataFrame `surveys_df`, try out the attributes & methods below to see\n", + "> what they return.\n", + ">\n", + "> 1. `surveys_df.columns`\n", + "> 2. `surveys_df.shape` Take note of the output of `shape` - what format does it\n", + "> return the shape of the DataFrame in?\n", + ">\n", + "> HINT: [More on tuples, here][python-datastructures].\n", + "> 3. `surveys_df.head()` Also, what does `surveys_df.head(15)` do?\n", + "> 4. `surveys_df.tail()`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65d9b5c5-187b-495c-af05-1d29ae10e20a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "e52d475d-1ab0-4d63-b40f-79d4c101d6eb", + "metadata": {}, + "source": [ + "## Calculating Statistics From Data In A Pandas DataFrame\n", + "\n", + "We've read our data into Python. Next, let's perform some quick summary\n", + "statistics to learn more about the data that we're working with. We might want\n", + "to know how many animals were collected in each site, or how many of each\n", + "species were caught. We can perform summary stats quickly using groups. But\n", + "first we need to figure out what we want to group by.\n", + "\n", + "Let's begin by exploring our data:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "9a898fab-d2cb-42c2-bf7d-231b1c674c1f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['record_id', 'month', 'day', 'year', 'plot_id', 'species_id', 'sex',\n", + " 'hindfoot_length', 'weight'],\n", + " dtype='object')" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Look at the column names\n", + "surveys_df.columns" + ] + }, + { + "cell_type": "markdown", + "id": "f62f48b9-2915-49a4-8b8d-2249f5f61698", + "metadata": {}, + "source": [ + "Let's get a list of all the species. The `pd.unique` function tells us all of\n", + "the unique values in the `species_id` column." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "026c7b71-f64a-4dd8-9c52-8b539c15f36c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array(['NL', 'DM', 'PF', 'PE', 'DS', 'PP', 'SH', 'OT', 'DO', 'OX', 'SS',\n", + " 'OL', 'RM', nan, 'SA', 'PM', 'AH', 'DX', 'AB', 'CB', 'CM', 'CQ',\n", + " 'RF', 'PC', 'PG', 'PH', 'PU', 'CV', 'UR', 'UP', 'ZL', 'UL', 'CS',\n", + " 'SC', 'BA', 'SF', 'RO', 'AS', 'SO', 'PI', 'ST', 'CU', 'SU', 'RX',\n", + " 'PB', 'PL', 'PX', 'CT', 'US'], dtype=object)" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.unique(surveys_df['species_id'])" + ] + }, + { + "cell_type": "markdown", + "id": "5aa04d1b-5743-4f76-b6e9-b72dbbec3db8", + "metadata": {}, + "source": [ + "> ## Challenge - Statistics\n", + ">\n", + "> 1. Create a list of unique site ID's (\"plot_id\") found in the surveys data. Call it\n", + "> `site_names`. How many unique sites are there in the data? How many unique\n", + "> species are in the data?\n", + ">\n", + "> 2. What is the difference between `len(site_names)` and `surveys_df['plot_id'].nunique()`?" + ] + }, + { + "cell_type": "markdown", + "id": "77564088-9128-4d94-ace5-110e1518f86b", + "metadata": {}, + "source": [ + "# Groups in Pandas\n", + "\n", + "We often want to calculate summary statistics grouped by subsets or attributes\n", + "within fields of our data. For example, we might want to calculate the average\n", + "weight of all individuals per site.\n", + "\n", + "We can calculate basic statistics for all records in a single column using the\n", + "syntax below:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "9f78f9f4-e387-405f-9dfa-1549eea21769", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "count 32283.000000\n", + "mean 42.672428\n", + "std 36.631259\n", + "min 4.000000\n", + "25% 20.000000\n", + "50% 37.000000\n", + "75% 48.000000\n", + "max 280.000000\n", + "Name: weight, dtype: float64" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "surveys_df['weight'].describe()" + ] + }, + { + "cell_type": "markdown", + "id": "3f9cccd0-5861-42c8-ac47-94d241760afe", + "metadata": {}, + "source": [ + "We can also extract one specific metric if we wish:\n", + "\n", + "```\n", + "surveys_df['weight'].min()\n", + "surveys_df['weight'].max()\n", + "surveys_df['weight'].mean()\n", + "surveys_df['weight'].std()\n", + "surveys_df['weight'].count()\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "2546bf29-ae70-4897-ba4f-3892122b2d3b", + "metadata": {}, + "source": [ + "But if we want to summarize by one or more variables, for example sex, we can\n", + "use **Pandas' `.groupby` method**. Once we've created a groupby DataFrame, we\n", + "can quickly calculate summary statistics by a group of our choice." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "00fc49b2-c1a3-4db5-ba2c-0f6b2627c927", + "metadata": {}, + "outputs": [], + "source": [ + "# Group data by sex\n", + "grouped_data = surveys_df.groupby('sex')" + ] + }, + { + "cell_type": "markdown", + "id": "612c8906-b9a7-491e-8fb4-1a2388277119", + "metadata": {}, + "source": [ + "The **pandas function `describe`** will return descriptive stats including: mean,\n", + "median, max, min, std and count for a particular column in the data. Pandas'\n", + "`describe` function will only return summary values for columns containing\n", + "numeric data." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "421e6cc7-2f04-4732-93d3-c65eb844ec10", + "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", + "
record_idmonthdayyearplot_idhindfoot_lengthweight
sex
F18036.4120466.58304716.0071381990.64499711.44085428.83678042.170555
M17754.8356016.39266816.1842861990.48040111.09828229.70957842.995379
\n", + "
" + ], + "text/plain": [ + " record_id month day year plot_id \\\n", + "sex \n", + "F 18036.412046 6.583047 16.007138 1990.644997 11.440854 \n", + "M 17754.835601 6.392668 16.184286 1990.480401 11.098282 \n", + "\n", + " hindfoot_length weight \n", + "sex \n", + "F 28.836780 42.170555 \n", + "M 29.709578 42.995379 " + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Summary statistics for all numeric columns by sex\n", + "grouped_data.describe()\n", + "# Provide the mean for each numeric column by sex\n", + "grouped_data.mean()" + ] + }, + { + "cell_type": "markdown", + "id": "f32f9aeb-3a0e-45cf-a58d-e1e855a4f142", + "metadata": {}, + "source": [ + "The `groupby` command is powerful in that it allows us to quickly generate\n", + "summary stats.\n", + "\n", + "> ## Challenge - Summary Data\n", + ">\n", + "> 1. How many recorded individuals are female `F` and how many male `M`?\n", + "> 2. What happens when you group by two columns using the following syntax and\n", + "> then calculate mean values?\n", + "> - `grouped_data2 = surveys_df.groupby(['plot_id', 'sex'])`\n", + "> - `grouped_data2.mean()`\n", + "> 3. Summarize weight values for each site in your data. HINT: you can use the\n", + "> following syntax to only create summary statistics for one column in your data.\n", + "> `by_site['weight'].describe()`\n", + ">\n", + ">\n", + ">> ## Did you get #3 right?\n", + ">> **A Snippet of the Output from challenge 3 looks like:**\n", + ">>\n", + ">> ```\n", + ">> site\n", + ">> 1 count 1903.000000\n", + ">> mean 51.822911\n", + ">> std 38.176670\n", + ">> min 4.000000\n", + ">> 25% 30.000000\n", + ">> 50% 44.000000\n", + ">> 75% 53.000000\n", + ">> max 231.000000\n", + ">> ...\n", + ">> ```" + ] + }, + { + "cell_type": "markdown", + "id": "00512ec3-e3be-4fd9-a3b0-f99633a0737e", + "metadata": {}, + "source": [ + "## Quickly Creating Summary Counts in Pandas\n", + "\n", + "Let's next count the number of samples for each species. We can do this in a few\n", + "ways, but we'll use `groupby` combined with **a `count()` method**." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "56735fff-81c5-47bc-abe3-f57a206a2b8e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "species_id\n", + "AB 303\n", + "AH 437\n", + "AS 2\n", + "BA 46\n", + "CB 50\n", + "CM 13\n", + "CQ 16\n", + "CS 1\n", + "CT 1\n", + "CU 1\n", + "CV 1\n", + "DM 10596\n", + "DO 3027\n", + "DS 2504\n", + "DX 40\n", + "NL 1252\n", + "OL 1006\n", + "OT 2249\n", + "OX 12\n", + "PB 2891\n", + "PC 39\n", + "PE 1299\n", + "PF 1597\n", + "PG 8\n", + "PH 32\n", + "PI 9\n", + "PL 36\n", + "PM 899\n", + "PP 3123\n", + "PU 5\n", + "PX 6\n", + "RF 75\n", + "RM 2609\n", + "RO 8\n", + "RX 2\n", + "SA 75\n", + "SC 1\n", + "SF 43\n", + "SH 147\n", + "SO 43\n", + "SS 248\n", + "ST 1\n", + "SU 5\n", + "UL 4\n", + "UP 8\n", + "UR 10\n", + "US 4\n", + "ZL 2\n", + "Name: record_id, dtype: int64\n" + ] + } + ], + "source": [ + "# Count the number of samples by species\n", + "species_counts = surveys_df.groupby('species_id')['record_id'].count()\n", + "print(species_counts)" + ] + }, + { + "cell_type": "markdown", + "id": "91527637-b894-4ab7-89d3-3baaf6c7c564", + "metadata": {}, + "source": [ + "Or, we can also count just the rows that have the species \"DO\":" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "014171dd-62da-4bcb-95e0-98b4818085a8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3027" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "surveys_df.groupby('species_id')['record_id'].count()['DO']" + ] + }, + { + "cell_type": "markdown", + "id": "d402cd18-b262-4f1c-9cf9-d95fd68de038", + "metadata": {}, + "source": [ + "> ## Challenge - Make a list\n", + ">\n", + "> What's another way to create a list of species and associated `count` of the\n", + "> records in the data? Hint: you can perform `count`, `min`, etc. functions on\n", + "> groupby DataFrames in the same way you can perform them on regular DataFrames." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7e8ae98-dd6c-4e70-b6ed-866d67160f8d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "2e4f40b1-6568-4db2-acfe-affbf491cfc1", + "metadata": {}, + "source": [ + "## Basic Math Functions\n", + "\n", + "If we wanted to, we could perform math on an entire column of our data. For\n", + "example let's multiply all weight values by 2. A more practical use of this might\n", + "be to normalize the data according to a mean, area, or some other value\n", + "calculated from our data." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "a5acc742-0c2b-42d9-b91b-189e01f7f5bf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0 NaN\n", + "1 NaN\n", + "2 NaN\n", + "3 NaN\n", + "4 NaN\n", + " ... \n", + "35544 NaN\n", + "35545 NaN\n", + "35546 28.0\n", + "35547 102.0\n", + "35548 NaN\n", + "Name: weight, Length: 35549, dtype: float64" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Multiply all weight values by 2\n", + "surveys_df['weight']*2" + ] + }, + { + "cell_type": "markdown", + "id": "d5e6fb78-a9b1-45b1-8205-08b93ab3c9fd", + "metadata": {}, + "source": [ + "# Quick & Easy Plotting Data Using Pandas\n", + "\n", + "We can plot our summary stats using Pandas, too." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "da1e26aa-ce14-42a5-854b-945c98b7c000", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Make sure figures appear inline in Ipython Notebook\n", + "%matplotlib inline\n", + "# Create a quick bar chart\n", + "species_counts.plot(kind='bar');" + ] + }, + { + "cell_type": "markdown", + "id": "0e4c591a-ca11-4535-aadf-d74e50d5fe1b", + "metadata": {}, + "source": [ + "Count per species site\n", + "\n", + "We can also look at how many animals were captured in each site:" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "f6ec232f-9ec7-4ca0-b01f-9fc7c3947489", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX0AAAEKCAYAAAD+XoUoAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAAsTAAALEwEAmpwYAAAT2ElEQVR4nO3dfbBcdX3H8feXBCmIIJDwGDCMjVJAiRIiVasoDsZHYgudYEeiQ02rCNSHqcE+oE7Thk6ltVqYRkGCChhRDCoP0igyWgQCRkJ4GFIIkEkkEXzAtkMlfPvH+UV2Nrt77917sze5v/dr5sye/Z3zPed37+5+9uxvd89GZiJJqsMu490BSdLgGPqSVBFDX5IqYuhLUkUMfUmqiKEvSRWZPN4dGMqUKVNy+vTp490NSdqp3HHHHT/LzKnt7Tt86E+fPp2VK1eOdzckaacSEQ93and4R5IqYuhLUkUMfUmqiKEvSRUx9CWpIoa+JFXE0Jekihj6klSRHf7LWdKgTV/47a7L1i1+ywB7Io09j/QlqSKGviRVxNCXpIoY+pJUEUNfkipi6EtSRQx9SaqIoS9JFTH0Jakihr4kVcTQl6SKGPqSVBFDX5IqYuhLUkWqOLWyp8qVpIZH+pJUEUNfkipi6EtSRQx9SaqIoS9JFTH0Jakihr4kVcTQl6SKGPqSVBFDX5IqYuhLUkUMfUmqiKEvSRUZ8iybEXEocBlwIPAMsCQzPx0R+wJfAaYD64A/zsyfl5pzgTOALcDZmXlDaT8WuBTYHbgWOCczc2z/JEljzTPVThzDOdJ/GvhwZv4ecDxwZkQcCSwEVmTmDGBFuU5ZNg84CpgDXBgRk8q2LgIWADPKNGcM/xZJ0hCGDP3M3JiZd5b5J4F7gUOAk4GlZbWlwNwyfzJwZWY+lZkPAWuB2RFxELBXZt5Sju4va6mRJA3AiH5EJSKmAy8DbgUOyMyN0DwxRMT+ZbVDgB+1lK0vbb8p8+3tnfazgOYVAYcddthv232JKUmjM+w3ciNiT+BrwF9k5q96rdqhLXu0b9uYuSQzZ2XmrKlTpw63i5KkIQwr9CNiV5rA/3Jmfr00P1aGbCiXm0r7euDQlvJpwIbSPq1DuyRpQIbz6Z0ALgbuzcwLWhZdA8wHFpfL5S3tl0fEBcDBNG/Y3paZWyLiyYg4nmZ46HTgM2P2l+xAHIaStKMazpj+q4B3AasjYlVp+xhN2C+LiDOAR4BTATJzTUQsA+6h+eTPmZm5pdS9j2c/snldmSRJAzJk6GfmD+g8Hg9wYpeaRcCiDu0rgaNH0kFJ0tgZ0ad3pNFw2Esaf4a+JiyfZKRtee4dSaqIoS9JFXF4RyPmsMnY8v+pQfJIX5IqYuhLUkUMfUmqiKEvSRXxjdwefINN0kTjkb4kVcTQl6SKGPqSVBFDX5IqYuhLUkUMfUmqiKEvSRUx9CWpIoa+JFXE0Jekihj6klQRQ1+SKmLoS1JFDH1JqoihL0kVMfQlqSKGviRVxNCXpIoY+pJUEUNfkipi6EtSRSaPdwc0etMXfrvrsnWL3zLAnkja0XmkL0kVMfQlqSJDDu9ExCXAW4FNmXl0afs48F5gc1ntY5l5bVl2LnAGsAU4OzNvKO3HApcCuwPXAudkZo7lHyONJ4fZtDMYzpH+pcCcDu3/nJkzy7Q18I8E5gFHlZoLI2JSWf8iYAEwo0ydtilJ2o6GDP3MvBl4YpjbOxm4MjOfysyHgLXA7Ig4CNgrM28pR/eXAXP77LMkqU+jGdP/QETcFRGXRMQ+pe0Q4NGWddaXtkPKfHu7JGmA+g39i4AXAjOBjcCnSnt0WDd7tHcUEQsiYmVErNy8eXO31SRJI9RX6GfmY5m5JTOfAT4HzC6L1gOHtqw6DdhQ2qd1aO+2/SWZOSszZ02dOrWfLkqSOugr9MsY/VbvAO4u89cA8yJit4g4nOYN29sycyPwZEQcHxEBnA4sH0W/JUl9GM5HNq8ATgCmRMR64DzghIiYSTNEsw74M4DMXBMRy4B7gKeBMzNzS9nU+3j2I5vXlUmSNEBDhn5mntah+eIe6y8CFnVoXwkcPaLeSZLGlOfekbTd+IW1HY+nYZCkihj6klQRQ1+SKuKYvqQJY9DvIeyM71l4pC9JFTH0Jakihr4kVcTQl6SKGPqSVBFDX5IqYuhLUkUMfUmqiKEvSRUx9CWpIoa+JFXE0Jekihj6klQRQ1+SKmLoS1JFDH1JqoihL0kV8ZezdiA746/wSNuDj4Xtx9CXVL2anmQc3pGkihj6klQRQ1+SKmLoS1JFDH1JqoihL0kVMfQlqSKGviRVxNCXpIr4jVxpJ1TTN0g1tgx9SdpJjMWT/ZDDOxFxSURsioi7W9r2jYgbI+KBcrlPy7JzI2JtRNwfEW9saT82IlaXZf8aETGsHkqSxsxwxvQvBea0tS0EVmTmDGBFuU5EHAnMA44qNRdGxKRScxGwAJhRpvZtSpK2syFDPzNvBp5oaz4ZWFrmlwJzW9qvzMynMvMhYC0wOyIOAvbKzFsyM4HLWmokSQPS76d3DsjMjQDlcv/SfgjwaMt660vbIWW+vV2SNEBj/ZHNTuP02aO980YiFkTEyohYuXnz5jHrnCTVrt/Qf6wM2VAuN5X29cChLetNAzaU9mkd2jvKzCWZOSszZ02dOrXPLkqS2vUb+tcA88v8fGB5S/u8iNgtIg6necP2tjIE9GREHF8+tXN6S40kaUCG/Jx+RFwBnABMiYj1wHnAYmBZRJwBPAKcCpCZayJiGXAP8DRwZmZuKZt6H80ngXYHriuTJGmAhgz9zDyty6ITu6y/CFjUoX0lcPSIeidJGlOee0eSKmLoS1JFDH1JqoihL0kVMfQlqSKGviRVxNCXpIoY+pJUEUNfkipi6EtSRQx9SaqIP4xesbH4kWVJOxeP9CWpIoa+JFXE0Jekihj6klQRQ1+SKmLoS1JFDH1JqoihL0kVMfQlqSKGviRVxNCXpIoY+pJUEUNfkipi6EtSRTy1slQRT6ctj/QlqSKGviRVxNCXpIoY+pJUEUNfkirip3ckacDG81NUHulLUkUMfUmqyKhCPyLWRcTqiFgVEStL274RcWNEPFAu92lZ/9yIWBsR90fEG0fbeUnSyIzFkf7rMnNmZs4q1xcCKzJzBrCiXCcijgTmAUcBc4ALI2LSGOxfkjRM22N452RgaZlfCsxtab8yM5/KzIeAtcDs7bB/SVIXow39BL4TEXdExILSdkBmbgQol/uX9kOAR1tq15e2bUTEgohYGRErN2/ePMouSpK2Gu1HNl+VmRsiYn/gxoi4r8e60aEtO62YmUuAJQCzZs3quI4kaeRGdaSfmRvK5Sbgaprhmsci4iCAcrmprL4eOLSlfBqwYTT7lySNTN9H+hHxXGCXzHyyzJ8EfBK4BpgPLC6Xy0vJNcDlEXEBcDAwA7htFH1XJTwdsDR2RjO8cwBwdURs3c7lmXl9RNwOLIuIM4BHgFMBMnNNRCwD7gGeBs7MzC2j6r0kaUT6Dv3MfBA4pkP748CJXWoWAYv63ackaXT8Rq4kVcTQl6SKGPqSVBFDX5IqYuhLUkUMfUmqiKEvSRUx9CWpIoa+JFXE0Jekihj6klQRQ1+SKmLoS1JFDH1JqoihL0kVMfQlqSKGviRVxNCXpIoY+pJUEUNfkipi6EtSRQx9SaqIoS9JFTH0Jakihr4kVcTQl6SKGPqSVBFDX5IqYuhLUkUMfUmqiKEvSRUx9CWpIoa+JFXE0Jekihj6klSRgYd+RMyJiPsjYm1ELBz0/iWpZgMN/YiYBPwb8CbgSOC0iDhykH2QpJoN+kh/NrA2Mx/MzP8DrgROHnAfJKlakZmD21nEKcCczPzTcv1dwCsy8wNt6y0AFpSrLwbu77LJKcDP+ujKzlC3M/TROuus23HrXpCZU7dpzcyBTcCpwOdbrr8L+MwotrdyotbtDH20zjrrdr66QQ/vrAcObbk+Ddgw4D5IUrUGHfq3AzMi4vCIeA4wD7hmwH2QpGpNHuTOMvPpiPgAcAMwCbgkM9eMYpNLJnDdztBH66yzbierG+gbuZKk8eU3ciWpIoa+JFXE0Jekikz40I+IIyLixIjYs619zhB1syPiuDJ/ZER8KCLe3Mf+L+uj5tVlfycNsd4rImKvMr97RHwiIr4ZEedHxN496s6OiEO7Le9R95yIOD0i3lCuvzMiPhsRZ0bErkPUvjAiPhIRn46IT0XEn/fqo6TeImL/vuomwhu5EfGezPxCh/azgTOBe4GZwDmZubwsuzMzX95le+fRnB9oMnAj8ArgJuANwA2ZuahLXfvHTwN4HfBdgMx8e5e62zJzdpl/b+nz1cBJwDczc3GXujXAMeVTUUuA/wGuAk4s7X/Ype6XwH8D/wVcAXw1Mzd3Wret7ss0/5M9gF8AewJfL/uLzJzfpe5s4G3A94E3A6uAnwPvAN6fmTcNte9aRMT+mblpgPvbLzMfH9T+tpdyAHEuMBfY+i3UTcByYHFm/qKPbV6XmW/qsmyvsr9pwHWZeXnLsgsz8/1d6g4EzgOeAf4WOAv4I5qMOiczN3ap27e9CbgDeBnNY++JYf9h/XwLbEebgEe6tK8G9izz04GV5R8L8OMe21tN85HSPYBfAXuV9t2Bu3rU3Ql8CTgBeG253FjmX9uj7sct87cDU8v8c4HVPerubd1327JVvfZH8yrvJOBiYDNwPTAfeF6PurvK5WTgMWBSuR5D/F9Wt6y7B3BTmT9siNthb2AxcB/weJnuLW3P7/O+cl2PZXsB/wB8EXhn27ILe9QdCFxEczLB/YCPl795GXBQj7p926b9gHXAPsC+PermtP2PLgbuAi4HDuhRtxiYUuZnAQ8Ca4GHh7h/3gn8NfDCEf6vZwHfK4+JQ2kOoH5Z7uMv61G3J/BJYE1ZfzPwI+DdPWpuAD4KHNh2u3wUuLFH3cu7TMcCG3vUfa38P+fSfNfoa8BunR6LbXXX0wT9wnKbfbQ8Ds4ClveoewZ4qG36Tbl8cES3Sz8PnPGYyj+o07QaeKpLzT0d7kzXAxcwRCh2mi/Xe9XtAnyw3LlnlrYhbxDgJ+WBvh9tX6tu33/bsq8C7ynzXwBmlfkXAbf3qGt/gtgVeDvNUf/mHnV3A88pfX2SEkzA79DyBNShbnXLA2If4I7Wbfao84E8xO0HfB74O+AF5b73jV63Q8v894DjWu4vXb/OX/rzT8AjwG1lPwcP4359G80r5tOAR4FTSvuJwC096pYD76Y5iv4Q8DfADGAp8Pddau7vsb1ey7bQvBL/Xofpf3vUrWq7/lfAD2kew73uKz9umX+k1zbbln2k3M9e0nq7DHUbdNxWP0XjMdEcWc4sd+7WaTqwoUvNdynh29I2GbgM2NJjX7cCe5T5XVra9+51g7asN40mkD/bfsN2WX8dzVHXQ+XywNK+5xB3hL2BS2mGaW4tgfEgzTDKMcO543VYtnuPZR8s238YOBtYAXyOJtTP61F3Dk0YLqE5at/6RDUVuLlHnQ/kznV3dtv+EPu7D5hc5n/UtqzXK8rW/f0BcCHw0/L/XNDn/6XXffAnbddvL5e7APd1qfkO8Je0vNIBDqB5Av6PHvu6G5jRZdmjPerupSUbStt8mlcnDw/nbwP+bri3QVm+NVcuAJ7HCI/wf7udforGY6J5CfvqLssu7/FPOrDLslf12NduXdqntD5Ah9Hnt9DlyGSY9XsAhw9jvecBx9AcyXZ9ed+y/otG0aeDKUd5wPOBU4DZw6g7qqx7xAj25QO5c816miPgD9M8CUfLsl7DbGeV/+nraYag/gV4DfAJ4Is96rZ5wqMZ/pwDfKFH3S00Q4in0hwozC3tr6X3K4v/3PpYp3kv6IaWZR2f7GleQZ5P88T2c+CJcnueT++hslOAF3dZNrdH3T8Cb+jQPgd4oEfdJylDzm3tvwtcNczHxdtohrt+Opz1t6nvp8jJaRBT2wP5ibYH8j496ib0A5nmjcDWaet7QAcClw1RewLwFZr3dVYD19Kcxnxyj5or+7z9jqEZorsOOAL4NM0HANYAr+xR91KaoaFfAD+gHKTQvDI8u0fdETQfttizrX3OEP08gmbIaazq3rS990fz/uLRw6nbZjv93JhOTuM9UYaIJlJd2wN5h+3njlhHM9x4P/ANmuHSk1uW9Rqa67furAHX9dXPjtvq5x/v5DTeE8N4r8S6euoY3Sf1Jmxdp2mgZ9mURiIi7uq2iGZs3zrrtpqUmb8GyMx1EXECcFVEvKDUdTPR67Zh6GtHdgDwRpo35loFzZt91lm31U8jYmZmrgLIzF9HxFuBS4CX9NjXRK/bhqGvHdm3aF7SrmpfEBE3WWddi9OBp1sbMvNp4PSI+Pce+5rodduYEKdhkCQNz4Q/4Zok6VmGviRVxNCXpIoY+lKbiLgpImYNsc7HhrGdjp80iYhLI+KUfvsnjYahL/VnyNDPzFcOoiPSSBj6qlZETI+I+yJiaUTcFRFXRcQebeucFhGrI+LuiDi/tC0Gdo+IVeWHZbpt/9flMsovjN0TEd8G+vrFI2ksGPqq3YuBJZn5UpofzPntLx5FxME0J3d7Pc1pvY+LiLmZuZDmFM0zM/NPhrGPd5T9vAR4L+ArAI0bQ1+1ezQzf1jmvwS8umXZcTS/8rW5fBHmyzSnIh6p1wBXZOaWzNxA+flMaTwY+qpd+7cTW6+P6JwmI9yPNC4MfdXusIj4/TJ/Gs3527e6FXhtREyJiEll+ffLst9ExK7D3MfNwLyImBQRBwGvG4uOS/0w9FW7e4H55cyO+9L8wDkAmbkROJfmZwF/QnPe8uVl8RLgrl5v5La4GniA5vS4F/HsE4c0cJ57R9WKiOnAtzLz6PHuizQoHulLUkU80pdGISL2A1Z0WHRiZj4+6P5IQzH0JakiDu9IUkUMfUmqiKEvSRUx9CWpIoa+JFXk/wHAtX7qjHoiDQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "total_count = surveys_df.groupby('plot_id')['record_id'].nunique()\n", + "# Let's plot that too\n", + "total_count.plot(kind='bar')" + ] + }, + { + "cell_type": "markdown", + "id": "f2aa1252-3611-4c2a-aafa-12c0c892e43a", + "metadata": {}, + "source": [ + "> ## Challenge - Plots\n", + ">\n", + "> 1. Create a plot of average weight across all species per site.\n", + "> 2. Create a plot of total males versus total females for the entire dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "778470a0-3584-4b48-87c3-1d5f631bbe57", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "5a2945e0-d51f-487d-81a6-44395601df1c", + "metadata": {}, + "source": [ + "> ## Summary Plotting Challenge\n", + ">\n", + "> Create a stacked bar plot, with weight on the Y axis, and the stacked variable\n", + "> being sex. The plot should show total weight by sex for each site. Some\n", + "> tips are below to help you solve this challenge:\n", + ">\n", + "> * For more information on pandas plots, see [pandas' documentation page on visualization][pandas-plot].\n", + "> * You can use the code that follows to create a stacked bar plot but the data to stack\n", + "> need to be in individual columns. Here's a simple example with some data where\n", + "> 'a', 'b', and 'c' are the groups, and 'one' and 'two' are the subgroups.\n", + ">\n", + "> ```\n", + "> d = {'one' : pd.Series([1., 2., 3.], index=['a', 'b', 'c']), 'two' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}\n", + "> pd.DataFrame(d)\n", + "> ```\n", + ">\n", + "> shows the following data\n", + ">\n", + "> ```\n", + "> one two\n", + "> a 1 1\n", + "> b 2 2\n", + "> c 3 3\n", + "> d NaN 4\n", + "> ```\n", + ">\n", + "> We can plot the above with\n", + ">\n", + "> ```\n", + "> # Plot stacked data so columns 'one' and 'two' are stacked\n", + "> my_df = pd.DataFrame(d)\n", + "> my_df.plot(kind='bar', stacked=True, title=\"The title of my graph\")\n", + "> ```\n", + ">\n", + "> * You can use the `.unstack()` method to transform grouped data into columns\n", + "> for each plotting. Try running `.unstack()` on some DataFrames above and see\n", + "> what it yields.\n", + ">\n", + "> Start by transforming the grouped data (by site and sex) into an unstacked layout, then create a stacked plot.\n", + ">" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1c9d455-6187-40ac-9953-b4ec0ac4b95d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "fb555c44-643c-4287-b80a-608ee0344b55", + "metadata": {}, + "source": [ + ">> ## Solution to Summary Challenge\n", + ">>\n", + ">> First we group data by site and by sex, and then calculate a total for each site.\n", + ">>\n", + ">> ```\n", + ">> by_site_sex = surveys_df.groupby(['plot_id', 'sex'])\n", + ">> site_sex_count = by_site_sex['weight'].sum()\n", + ">> ```\n", + ">>\n", + ">> This calculates the sums of weights for each sex within each site as a table\n", + ">>\n", + ">> ```\n", + ">> site sex\n", + ">> plot_id sex\n", + ">> 1 F 38253\n", + ">> M 59979\n", + ">> 2 F 50144\n", + ">> M 57250\n", + ">> 3 F 27251\n", + ">> M 28253\n", + ">> 4 F 39796\n", + ">> M 49377\n", + ">> \n", + ">> ```\n", + ">>\n", + ">> Below we'll use `.unstack()` on our grouped data to figure out the total weight that each sex contributed to each site.\n", + ">>\n", + ">> ```\n", + ">> by_site_sex = surveys_df.groupby(['plot_id', 'sex'])\n", + ">> site_sex_count = by_site_sex['weight'].sum()\n", + ">> site_sex_count.unstack()\n", + ">> ```\n", + ">>\n", + ">> The `unstack` method above will display the following output:\n", + ">>\n", + ">> ```\n", + ">> sex F M\n", + ">> plot_id\n", + ">> 1 38253 59979\n", + ">> 2 50144 57250\n", + ">> 3 27251 28253\n", + ">> 4 39796 49377\n", + ">> \n", + ">> ```\n", + ">>\n", + ">> Now, create a stacked bar plot with that data where the weights for each sex are stacked by site.\n", + ">>\n", + ">> Rather than display it as a table, we can plot the above data by stacking the values of each sex as follows:\n", + ">>\n", + ">> ```\n", + ">> by_site_sex = surveys_df.groupby(['plot_id', 'sex'])\n", + ">> site_sex_count = by_site_sex['weight'].sum()\n", + ">> spc = site_sex_count.unstack()\n", + ">> s_plot = spc.plot(kind='bar', stacked=True, title=\"Total weight by site and sex\")\n", + ">> s_plot.set_ylabel(\"Weight\")\n", + ">> s_plot.set_xlabel(\"Plot\")\n", + ">> ```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa3cc636-053b-4b92-9ed3-be349d4d1285", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "9a864b9b-918d-4d08-98b6-7a140ce679ca", + "metadata": {}, + "source": [ + "## References\n", + "\n", + "- ernst: http://www.esapubs.org/archive/ecol/E090/118/default.htm\n", + "- figshare-ndownloader: https://ndownloader.figshare.com/files/2292172\n", + "- os-lib: https://docs.python.org/3/library/os.html\n", + "- matplotlib: https://matplotlib.org\n", + "- numpy: https://www.numpy.org/\n", + "- pandas: https://pandas.pydata.org\n", + "- pandas-plot: http://pandas.pydata.org/pandas-docs/stable/user_guide/visualization.html#basic-plotting-plot\n", + "- pd-dataframe: https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html\n", + "- pptd: https://figshare.com/articles/Portal_Project_Teaching_Database/1314459\n", + "- python-datastructures: https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences\n", + "- spreadsheet-lesson5: http://www.datacarpentry.org/spreadsheet-ecology-lesson/05-exporting-data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e4c4a30-de40-4ffd-befd-9b8dda7da968", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "7c6d9e59-e673-4ae3-9ca9-0a1f5b6b7509", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 + Jaspy", + "language": "python", + "name": "jaspy" + }, + "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.10.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python-data/solutions/ex06_pandas_rainfall.ipynb b/python-data/solutions/ex06_pandas_rainfall.ipynb new file mode 100644 index 0000000..b5e9192 --- /dev/null +++ b/python-data/solutions/ex06_pandas_rainfall.ipynb @@ -0,0 +1,1009 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "af6d2be1-db21-4ad7-9c12-ebf4ec6b79e1", + "metadata": {}, + "source": [ + "# Pandas to read CSV data\n", + "\n", + "Let's see Pandas in action, to understand some of its power and utility..." + ] + }, + { + "cell_type": "markdown", + "id": "1be9623f-bdbb-402f-8d74-7a8ef03ac2bd", + "metadata": {}, + "source": [ + "## If we just want the first 6 rows, just use readline()\n", + "\n", + "We know there are 6 header lines, we can get those using Python's `open()` and `f.readline()`:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "d179c1f2-9730-492b-b6fe-9c6fddb33c96", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Item: UK Rainfall (mm)\n", + "Item: Areal series, starting from 1910\n", + "Item: Allowances have been made for topographic, coastal and urban effects where relationships are found to exist.\n", + "Item: Seasons: Winter=Dec-Feb, Spring=Mar-May, Summer=June-Aug, Autumn=Sept-Nov. (Winter: Year refers to Jan/Feb).\n", + "Item: Values are ranked and displayed to 1 dp. Where values are equal, rankings are based in order of year descending.\n", + "Item: Data are provisional from December 2014 & Winter 2015. Last updated 07/04/2015\n" + ] + } + ], + "source": [ + "# Set the path and read metadata\n", + "fpath = \"../example_data/uk_rainfall.txt\"\n", + "with open(fpath) as f:\n", + " metadata = [f.readline().strip() for i in range(6)]\n", + " \n", + "for item in metadata:\n", + " print(\"Item:\", item)" + ] + }, + { + "cell_type": "markdown", + "id": "3294a316-66fc-4234-a226-a2ba4bf72480", + "metadata": {}, + "source": [ + "## Now let's see what Pandas can do to read the actual tabular data\n", + "\n", + "Pandas can read many formats, and stores data very efficiently. In this case we use:\n", + "\n", + "`pandas.read_csv()`\n", + "\n", + "See docs: https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html\n", + "\n", + "In one call, we tell it to:\n", + "- read from file `fpath`\n", + "- skip the first 6 rows of the header (captured above)\n", + "- use a regular expression to split the fields (i.e. `\"\\s+\"` which means split on white space\n", + "- use the first column (Year) as the index\n", + "- values specified as `\"---\"` should be treated as missing values" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "3f9a4009-7ae6-450c-8a8c-ceee826d55f5", + "metadata": {}, + "outputs": [], + "source": [ + "# Read it in one line with Pandas!\n", + "\n", + "import pandas as pd\n", + "df = pd.read_csv(fpath, skiprows=6, sep=\"\\s+\",\n", + "\t\t\t index_col=0, na_values=\"---\")" + ] + }, + { + "cell_type": "markdown", + "id": "c1a49fbb-b387-4b6c-86de-95d84149cefb", + "metadata": {}, + "source": [ + "View the data as the DataFrame `df`:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "65d6658e-1cf3-452a-be82-b3d16d1fd8f3", + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDECWINSPRSUMAUTANN
Year
1910111.4126.149.995.371.870.297.1140.227.089.4128.4142.2NaN217.0307.5244.81148.9
191159.299.762.169.052.277.043.369.369.491.5141.3188.4301.0183.4189.6302.21022.4
1912111.779.5128.236.158.2124.592.3167.657.1116.2106.9163.7379.6222.5384.4280.31242.0
1913123.457.1131.2102.981.563.833.744.573.7103.0125.986.6344.2315.6142.1302.61027.4
191478.8114.9124.352.359.652.594.480.157.261.8139.3203.3280.3236.3227.0258.31118.6
......................................................
201079.774.879.448.039.038.6107.697.6114.0101.1123.247.5255.4166.4243.8338.3950.5
2011102.8114.549.736.7101.885.176.1105.8108.5122.8100.6168.1264.9188.2266.9331.91172.5
2012110.960.037.0128.065.8149.0118.9111.3112.9126.2135.5179.4339.0230.8379.2374.61334.8
2013110.559.864.663.692.148.765.472.771.6163.491.0187.6349.6220.2186.8326.01091.0
2014188.0169.280.067.899.654.864.7138.822.8158.5123.7129.7544.9247.4258.3304.91297.6
\n", + "

105 rows × 17 columns

\n", + "
" + ], + "text/plain": [ + " JAN FEB MAR APR MAY JUN JUL AUG SEP OCT \\\n", + "Year \n", + "1910 111.4 126.1 49.9 95.3 71.8 70.2 97.1 140.2 27.0 89.4 \n", + "1911 59.2 99.7 62.1 69.0 52.2 77.0 43.3 69.3 69.4 91.5 \n", + "1912 111.7 79.5 128.2 36.1 58.2 124.5 92.3 167.6 57.1 116.2 \n", + "1913 123.4 57.1 131.2 102.9 81.5 63.8 33.7 44.5 73.7 103.0 \n", + "1914 78.8 114.9 124.3 52.3 59.6 52.5 94.4 80.1 57.2 61.8 \n", + "... ... ... ... ... ... ... ... ... ... ... \n", + "2010 79.7 74.8 79.4 48.0 39.0 38.6 107.6 97.6 114.0 101.1 \n", + "2011 102.8 114.5 49.7 36.7 101.8 85.1 76.1 105.8 108.5 122.8 \n", + "2012 110.9 60.0 37.0 128.0 65.8 149.0 118.9 111.3 112.9 126.2 \n", + "2013 110.5 59.8 64.6 63.6 92.1 48.7 65.4 72.7 71.6 163.4 \n", + "2014 188.0 169.2 80.0 67.8 99.6 54.8 64.7 138.8 22.8 158.5 \n", + "\n", + " NOV DEC WIN SPR SUM AUT ANN \n", + "Year \n", + "1910 128.4 142.2 NaN 217.0 307.5 244.8 1148.9 \n", + "1911 141.3 188.4 301.0 183.4 189.6 302.2 1022.4 \n", + "1912 106.9 163.7 379.6 222.5 384.4 280.3 1242.0 \n", + "1913 125.9 86.6 344.2 315.6 142.1 302.6 1027.4 \n", + "1914 139.3 203.3 280.3 236.3 227.0 258.3 1118.6 \n", + "... ... ... ... ... ... ... ... \n", + "2010 123.2 47.5 255.4 166.4 243.8 338.3 950.5 \n", + "2011 100.6 168.1 264.9 188.2 266.9 331.9 1172.5 \n", + "2012 135.5 179.4 339.0 230.8 379.2 374.6 1334.8 \n", + "2013 91.0 187.6 349.6 220.2 186.8 326.0 1091.0 \n", + "2014 123.7 129.7 544.9 247.4 258.3 304.9 1297.6 \n", + "\n", + "[105 rows x 17 columns]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "markdown", + "id": "be40d4ee-62b9-40f4-b17f-e511d46c1ba8", + "metadata": {}, + "source": [ + "Use some of the built-in Pandas DataFrame functions:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "2c32430e-9fdd-4e00-8aef-4bdb18883b14", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['JAN',\n", + " 'FEB',\n", + " 'MAR',\n", + " 'APR',\n", + " 'MAY',\n", + " 'JUN',\n", + " 'JUL',\n", + " 'AUG',\n", + " 'SEP',\n", + " 'OCT',\n", + " 'NOV',\n", + " 'DEC',\n", + " 'WIN',\n", + " 'SPR',\n", + " 'SUM',\n", + " 'AUT',\n", + " 'ANN']" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Get the column names as a list\n", + "df.columns.tolist()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "f5f86eb3-1b11-4d0c-888a-07a6d66bd634", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Year'" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Find out which field is the index\n", + "df.index.name" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "af1f7540-2a52-4db0-bc98-2f7c20f82388", + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDECWINSPRSUMAUTANN
count105.000000105.000000105.000000105.000000105.000000105.000000105.000000105.000000105.000000105.000000105.000000105.000000104.000000105.000000105.000000105.000000105.000000
mean113.30857183.38761978.65333368.53523869.38476269.09619082.01238192.47714391.883810113.569524114.699048118.287619314.483654216.570476243.580000320.1533331095.295238
std35.85673737.53393528.33396723.73422524.05508026.22927727.96689633.31835733.72433838.15677038.53817939.01311671.43750842.20788156.87460365.079506108.620457
min29.0000008.80000017.00000014.10000022.00000014.20000030.60000010.30000022.80000031.60000022.10000032.400000119.500000119.800000103.000000193.400000835.400000
25%93.30000058.00000057.20000050.00000051.70000050.40000061.90000073.90000069.40000089.40000086.10000088.600000259.825000189.400000205.700000268.1000001025.600000
50%111.40000079.50000075.50000069.00000066.40000064.90000078.50000090.30000092.000000115.300000112.800000115.500000309.450000212.700000240.800000321.5000001091.000000
75%137.000000106.30000093.50000087.20000086.70000086.90000098.500000112.900000113.700000142.300000143.000000142.200000356.900000237.300000280.100000368.5000001177.700000
max205.100000187.900000150.300000128.000000128.300000149.000000145.600000167.600000182.200000194.800000215.700000213.000000544.900000331.700000384.400000497.8000001337.300000
\n", + "
" + ], + "text/plain": [ + " JAN FEB MAR APR MAY JUN \\\n", + "count 105.000000 105.000000 105.000000 105.000000 105.000000 105.000000 \n", + "mean 113.308571 83.387619 78.653333 68.535238 69.384762 69.096190 \n", + "std 35.856737 37.533935 28.333967 23.734225 24.055080 26.229277 \n", + "min 29.000000 8.800000 17.000000 14.100000 22.000000 14.200000 \n", + "25% 93.300000 58.000000 57.200000 50.000000 51.700000 50.400000 \n", + "50% 111.400000 79.500000 75.500000 69.000000 66.400000 64.900000 \n", + "75% 137.000000 106.300000 93.500000 87.200000 86.700000 86.900000 \n", + "max 205.100000 187.900000 150.300000 128.000000 128.300000 149.000000 \n", + "\n", + " JUL AUG SEP OCT NOV DEC \\\n", + "count 105.000000 105.000000 105.000000 105.000000 105.000000 105.000000 \n", + "mean 82.012381 92.477143 91.883810 113.569524 114.699048 118.287619 \n", + "std 27.966896 33.318357 33.724338 38.156770 38.538179 39.013116 \n", + "min 30.600000 10.300000 22.800000 31.600000 22.100000 32.400000 \n", + "25% 61.900000 73.900000 69.400000 89.400000 86.100000 88.600000 \n", + "50% 78.500000 90.300000 92.000000 115.300000 112.800000 115.500000 \n", + "75% 98.500000 112.900000 113.700000 142.300000 143.000000 142.200000 \n", + "max 145.600000 167.600000 182.200000 194.800000 215.700000 213.000000 \n", + "\n", + " WIN SPR SUM AUT ANN \n", + "count 104.000000 105.000000 105.000000 105.000000 105.000000 \n", + "mean 314.483654 216.570476 243.580000 320.153333 1095.295238 \n", + "std 71.437508 42.207881 56.874603 65.079506 108.620457 \n", + "min 119.500000 119.800000 103.000000 193.400000 835.400000 \n", + "25% 259.825000 189.400000 205.700000 268.100000 1025.600000 \n", + "50% 309.450000 212.700000 240.800000 321.500000 1091.000000 \n", + "75% 356.900000 237.300000 280.100000 368.500000 1177.700000 \n", + "max 544.900000 331.700000 384.400000 497.800000 1337.300000 " + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Show the spread of each column\n", + "df.describe()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "3848706b-6fef-417b-8b74-73b0615a1744", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Int64Index: 105 entries, 1910 to 2014\n", + "Data columns (total 17 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 JAN 105 non-null float64\n", + " 1 FEB 105 non-null float64\n", + " 2 MAR 105 non-null float64\n", + " 3 APR 105 non-null float64\n", + " 4 MAY 105 non-null float64\n", + " 5 JUN 105 non-null float64\n", + " 6 JUL 105 non-null float64\n", + " 7 AUG 105 non-null float64\n", + " 8 SEP 105 non-null float64\n", + " 9 OCT 105 non-null float64\n", + " 10 NOV 105 non-null float64\n", + " 11 DEC 105 non-null float64\n", + " 12 WIN 104 non-null float64\n", + " 13 SPR 105 non-null float64\n", + " 14 SUM 105 non-null float64\n", + " 15 AUT 105 non-null float64\n", + " 16 ANN 105 non-null float64\n", + "dtypes: float64(17)\n", + "memory usage: 14.8 KB\n" + ] + } + ], + "source": [ + "# Get information about the overall DataFrame\n", + "df.info()" + ] + }, + { + "cell_type": "markdown", + "id": "766af082-3c2a-43a6-9abd-025d10f1fcdf", + "metadata": {}, + "source": [ + "You can use `df.loc` to locate specific columns/rows. In this case we select WINTER in 1918." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "0b0446c6-7a03-4aef-9937-cf0dffb8f829", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "272.9" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.loc[1918, \"WIN\"]" + ] + }, + { + "cell_type": "markdown", + "id": "6698a4be-edfd-461f-a98e-59f3cc7a6b02", + "metadata": {}, + "source": [ + "Whereas `df.iloc` uses the index lookups, here is the same lookup via indexes:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "2305918e-e01a-4c37-b1ce-ad4861ee7894", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "272.9" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.iloc[8, 12]" + ] + }, + { + "cell_type": "markdown", + "id": "3ab2aa8e-45b3-4560-bf68-39f3051f5369", + "metadata": {}, + "source": [ + "And you can slice as well as select individual values:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "898d499d-8832-4f7e-b5f4-6fca4f5eabbf", + "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", + "
AUTANN
Year
1910244.81148.9
1911302.21022.4
1912280.31242.0
1913302.61027.4
\n", + "
" + ], + "text/plain": [ + " AUT ANN\n", + "Year \n", + "1910 244.8 1148.9\n", + "1911 302.2 1022.4\n", + "1912 280.3 1242.0\n", + "1913 302.6 1027.4" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.iloc[:4, -2:]" + ] + }, + { + "cell_type": "markdown", + "id": "3852d509-3643-48ed-a753-4c1fd92267b9", + "metadata": {}, + "source": [ + "## Plotting\n", + "\n", + "Plotting is easy, just call the `plot()` method on the particular DataFrame or Series you are looking at." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "97109723-37d2-48d7-b383-a5de0956c740", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 23, + "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.MAR.plot(title=\"Time-series of rainfall in March\", ylabel=\"Rainfall (mm)\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26f05680-2ed6-4736-8b62-9c624db22dd4", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 + Jaspy", + "language": "python", + "name": "jaspy" + }, + "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.10.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}