{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"\n",
"\n",
"\n",
"\n",
"| - | - | - |\n",
"|-------------------------------------------------------------------------------|-------------------------------------------------------------------------------|-------------------------------------------------------------------------------|\n",
"| [Exercise 1 (split date continues)](<#Exercise-1-(split-date-continues)>) | [Exercise 2 (cycling weather)](<#Exercise-2-(cycling-weather)>) | [Exercise 3 (top bands)](<#Exercise-3-(top-bands)>) |\n",
"| [Exercise 4 (cyclists per day)](<#Exercise-4-(cyclists-per-day)>) | [Exercise 5 (best record company)](<#Exercise-5-(best-record-company)>) | [Exercise 6 (suicide fractions)](<#Exercise-6-(suicide-fractions)>) |\n",
"| [Exercise 7 (suicide weather)](<#Exercise-7-(suicide-weather)>) | [Exercise 8 (bicycle timeseries)](<#Exercise-8-(bicycle-timeseries)>) | [Exercise 9 (commute)](<#Exercise-9-(commute)>) |\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Pandas (continues)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.754504Z",
"start_time": "2020-06-24T19:33:41.502072Z"
}
},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Catenating datasets\n",
"\n",
"We already saw in the NumPy section how we can catenate arrays along an axis: `axis=0` catenates vertically and `axis=1` catenates horizontally, and so on. With the DataFrames of Pandas it works similarly except that the row indices and the column names require extra attention. Also note a slight difference in the name: `np.concatenate` but `pd.concat`.\n",
"\n",
"Let's start by considering catenation along the axis 0, that is, vertical catenation. We will first make a helper function to easily create DataFrames for testing."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.760458Z",
"start_time": "2020-06-24T19:33:41.756165Z"
}
},
"outputs": [],
"source": [
"def makedf(cols, ind):\n",
" data = {c : [str(c) + str(i) for i in ind] for c in cols}\n",
" return pd.DataFrame(data, ind)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next we will create some example DataFrames:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.779553Z",
"start_time": "2020-06-24T19:33:41.762127Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" A | \n",
" B | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" A0 | \n",
" B0 | \n",
"
\n",
" \n",
" 1 | \n",
" A1 | \n",
" B1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" A B\n",
"0 A0 B0\n",
"1 A1 B1"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"a=makedf(\"AB\", [0,1])\n",
"a"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.786616Z",
"start_time": "2020-06-24T19:33:41.780808Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" A | \n",
" B | \n",
"
\n",
" \n",
" \n",
" \n",
" 2 | \n",
" A2 | \n",
" B2 | \n",
"
\n",
" \n",
" 3 | \n",
" A3 | \n",
" B3 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" A B\n",
"2 A2 B2\n",
"3 A3 B3"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"b=makedf(\"AB\", [2,3])\n",
"b"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.795625Z",
"start_time": "2020-06-24T19:33:41.787902Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" C | \n",
" D | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" C0 | \n",
" D0 | \n",
"
\n",
" \n",
" 1 | \n",
" C1 | \n",
" D1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" C D\n",
"0 C0 D0\n",
"1 C1 D1"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"c=makedf(\"CD\", [0,1])\n",
"c"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.804676Z",
"start_time": "2020-06-24T19:33:41.797160Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" B | \n",
" C | \n",
"
\n",
" \n",
" \n",
" \n",
" 2 | \n",
" B2 | \n",
" C2 | \n",
"
\n",
" \n",
" 3 | \n",
" B3 | \n",
" C3 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" B C\n",
"2 B2 C2\n",
"3 B3 C3"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d=makedf(\"BC\", [2,3])\n",
"d"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the following simple case, the `concat` function works exactly as we expect it would:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.812230Z",
"start_time": "2020-06-24T19:33:41.805960Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" A | \n",
" B | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" A0 | \n",
" B0 | \n",
"
\n",
" \n",
" 1 | \n",
" A1 | \n",
" B1 | \n",
"
\n",
" \n",
" 2 | \n",
" A2 | \n",
" B2 | \n",
"
\n",
" \n",
" 3 | \n",
" A3 | \n",
" B3 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" A B\n",
"0 A0 B0\n",
"1 A1 B1\n",
"2 A2 B2\n",
"3 A3 B3"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.concat([a,b]) # The default axis is 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The next, however, will create duplicate indices:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.820781Z",
"start_time": "2020-06-24T19:33:41.814430Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" A | \n",
" B | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" A0 | \n",
" B0 | \n",
"
\n",
" \n",
" 1 | \n",
" A1 | \n",
" B1 | \n",
"
\n",
" \n",
" 0 | \n",
" A0 | \n",
" B0 | \n",
"
\n",
" \n",
" 1 | \n",
" A1 | \n",
" B1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" A B\n",
"0 A0 B0\n",
"1 A1 B1\n",
"0 A0 B0\n",
"1 A1 B1"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r=pd.concat([a,a])\n",
"r"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.827616Z",
"start_time": "2020-06-24T19:33:41.822424Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"0 A0\n",
"0 A0\n",
"Name: A, dtype: object"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r.loc[0,\"A\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is not usually what we want! There are three solutions to this. Firstly, deny creation of duplicated indices by giving the `verify_integrity` parameter to the `concat` function:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.834351Z",
"start_time": "2020-06-24T19:33:41.828736Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Indexes have overlapping values: Int64Index([0, 1], dtype='int64')\n"
]
}
],
"source": [
"try:\n",
" pd.concat([a,a], verify_integrity=True)\n",
"except ValueError as e:\n",
" import sys\n",
" print(e, file=sys.stderr)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Secondly, we can ask for automatic renumbering of rows:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.842276Z",
"start_time": "2020-06-24T19:33:41.835962Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" A | \n",
" B | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" A0 | \n",
" B0 | \n",
"
\n",
" \n",
" 1 | \n",
" A1 | \n",
" B1 | \n",
"
\n",
" \n",
" 2 | \n",
" A0 | \n",
" B0 | \n",
"
\n",
" \n",
" 3 | \n",
" A1 | \n",
" B1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" A B\n",
"0 A0 B0\n",
"1 A1 B1\n",
"2 A0 B0\n",
"3 A1 B1"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.concat([a,a], ignore_index=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Thirdly, we can ask for *hierarchical indexing*. The indices can contain multiple levels, but on this course we don't consider hierarchical indices in detail. Hierarchical indices can make a two dimensional array to work like higher dimensional array."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.851535Z",
"start_time": "2020-06-24T19:33:41.843511Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" | \n",
" A | \n",
" B | \n",
"
\n",
" \n",
" \n",
" \n",
" first | \n",
" 0 | \n",
" A0 | \n",
" B0 | \n",
"
\n",
" \n",
" 1 | \n",
" A1 | \n",
" B1 | \n",
"
\n",
" \n",
" second | \n",
" 0 | \n",
" A0 | \n",
" B0 | \n",
"
\n",
" \n",
" 1 | \n",
" A1 | \n",
" B1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" A B\n",
"first 0 A0 B0\n",
" 1 A1 B1\n",
"second 0 A0 B0\n",
" 1 A1 B1"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r2=pd.concat([a,a], keys=['first', 'second'])\n",
"r2"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.856921Z",
"start_time": "2020-06-24T19:33:41.852769Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"'A0'"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r2[\"A\"][\"first\"][0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Everything works similarly, when we want to catenate horizontally:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.866445Z",
"start_time": "2020-06-24T19:33:41.858187Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" A | \n",
" B | \n",
" C | \n",
" D | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" A0 | \n",
" B0 | \n",
" C0 | \n",
" D0 | \n",
"
\n",
" \n",
" 1 | \n",
" A1 | \n",
" B1 | \n",
" C1 | \n",
" D1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" A B C D\n",
"0 A0 B0 C0 D0\n",
"1 A1 B1 C1 D1"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.concat([a,c], axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We have so far assumed that when concatenating vertically the columns of both DataFrames are the same, and when joining horizontally the indices are the same. This is, however, not required:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.877755Z",
"start_time": "2020-06-24T19:33:41.868014Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" A | \n",
" B | \n",
" C | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" A0 | \n",
" B0 | \n",
" NaN | \n",
"
\n",
" \n",
" 1 | \n",
" A1 | \n",
" B1 | \n",
" NaN | \n",
"
\n",
" \n",
" 2 | \n",
" NaN | \n",
" B2 | \n",
" C2 | \n",
"
\n",
" \n",
" 3 | \n",
" NaN | \n",
" B3 | \n",
" C3 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" A B C\n",
"0 A0 B0 NaN\n",
"1 A1 B1 NaN\n",
"2 NaN B2 C2\n",
"3 NaN B3 C3"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.concat([a,d], sort=False) # sort option is used to silence a deprecation message"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It expanded the non-existing cases with `NaN`s. This method is called an *outer join*, which forms the union of columns in the two DataFrames. The alternative is *inner join*, which forms the intersection of columns:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.890107Z",
"start_time": "2020-06-24T19:33:41.878883Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" B | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" B0 | \n",
"
\n",
" \n",
" 1 | \n",
" B1 | \n",
"
\n",
" \n",
" 2 | \n",
" B2 | \n",
"
\n",
" \n",
" 3 | \n",
" B3 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" B\n",
"0 B0\n",
"1 B1\n",
"2 B2\n",
"3 B3"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.concat([a,d], join=\"inner\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise 1 (split date continues)
\n",
"\n",
"Write function `split_date_continues` that does\n",
"\n",
"* read the bicycle data set\n",
"* clean the data set of columns/rows that contain only missing values\n",
"* drops the `Päivämäärä` column and replaces it with its splitted components as before\n",
"\n",
"Use the `concat` function to do this. The function should return a DataFrame with 25 columns (first five related to the date and then the rest 20 conserning the measument location.\n",
"\n",
"**Hint**: You may use your solution or the model solution from exercise 16 of the previous set as a starting point.\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Merging dataframes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Merging combines two DataFrames based on some common field."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's recall the earlier DataFrame about wages and ages of persons:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.900440Z",
"start_time": "2020-06-24T19:33:41.891369Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Wage | \n",
" Name | \n",
" Age | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 1000 | \n",
" Jack | \n",
" 21 | \n",
"
\n",
" \n",
" 1 | \n",
" 1500 | \n",
" John | \n",
" 29 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Wage Name Age\n",
"0 1000 Jack 21\n",
"1 1500 John 29"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.DataFrame([[1000, \"Jack\", 21], [1500, \"John\", 29]], columns=[\"Wage\", \"Name\", \"Age\"])\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, create a new DataFrame with the occupations of persons:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.908987Z",
"start_time": "2020-06-24T19:33:41.902057Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Name | \n",
" Occupation | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" John | \n",
" Plumber | \n",
"
\n",
" \n",
" 1 | \n",
" Jack | \n",
" Carpenter | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Name Occupation\n",
"0 John Plumber\n",
"1 Jack Carpenter"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2 = pd.DataFrame({\"Name\" : [\"John\", \"Jack\"], \"Occupation\": [\"Plumber\", \"Carpenter\"]})\n",
"df2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following function call will merge the two DataFrames on their common field, and, importantly, will keep the indices *aligned*. What this means is that even though the names are listed in different order in the two frames, the merge will still give correct result."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.920951Z",
"start_time": "2020-06-24T19:33:41.910226Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Wage | \n",
" Name | \n",
" Age | \n",
" Occupation | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 1000 | \n",
" Jack | \n",
" 21 | \n",
" Carpenter | \n",
"
\n",
" \n",
" 1 | \n",
" 1500 | \n",
" John | \n",
" 29 | \n",
" Plumber | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Wage Name Age Occupation\n",
"0 1000 Jack 21 Carpenter\n",
"1 1500 John 29 Plumber"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.merge(df, df2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This was an example of a simple one-to-one merge, where the keys in the `Name` columns had 1-to-1 correspondence. Sometimes not all the keys appear in both DataFrames:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.928770Z",
"start_time": "2020-06-24T19:33:41.922030Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Name | \n",
" Occupation | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" John | \n",
" Plumber | \n",
"
\n",
" \n",
" 1 | \n",
" Jack | \n",
" Carpenter | \n",
"
\n",
" \n",
" 2 | \n",
" James | \n",
" Painter | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Name Occupation\n",
"0 John Plumber\n",
"1 Jack Carpenter\n",
"2 James Painter"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df3 = pd.concat([df2, pd.DataFrame({ \"Name\" : [\"James\"], \"Occupation\":[\"Painter\"]})], ignore_index=True)\n",
"df3"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.942166Z",
"start_time": "2020-06-24T19:33:41.930548Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Wage | \n",
" Name | \n",
" Age | \n",
" Occupation | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 1000 | \n",
" Jack | \n",
" 21 | \n",
" Carpenter | \n",
"
\n",
" \n",
" 1 | \n",
" 1500 | \n",
" John | \n",
" 29 | \n",
" Plumber | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Wage Name Age Occupation\n",
"0 1000 Jack 21 Carpenter\n",
"1 1500 John 29 Plumber"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.merge(df, df3) # By default an inner join is computed"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.952812Z",
"start_time": "2020-06-24T19:33:41.943661Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Wage | \n",
" Name | \n",
" Age | \n",
" Occupation | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 1000.0 | \n",
" Jack | \n",
" 21.0 | \n",
" Carpenter | \n",
"
\n",
" \n",
" 1 | \n",
" 1500.0 | \n",
" John | \n",
" 29.0 | \n",
" Plumber | \n",
"
\n",
" \n",
" 2 | \n",
" NaN | \n",
" James | \n",
" NaN | \n",
" Painter | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Wage Name Age Occupation\n",
"0 1000.0 Jack 21.0 Carpenter\n",
"1 1500.0 John 29.0 Plumber\n",
"2 NaN James NaN Painter"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.merge(df, df3, how=\"outer\") # Outer join"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Also, many-to-one and many-to-many relationships can occur in merges:"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.965551Z",
"start_time": "2020-06-24T19:33:41.957039Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Title | \n",
" Author | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" War and Peace | \n",
" Tolstoi | \n",
"
\n",
" \n",
" 1 | \n",
" Good Omens | \n",
" Terry Pratchett | \n",
"
\n",
" \n",
" 2 | \n",
" Good Omens | \n",
" Neil Gaiman | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Title Author\n",
"0 War and Peace Tolstoi\n",
"1 Good Omens Terry Pratchett\n",
"2 Good Omens Neil Gaiman"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"books = pd.DataFrame({\"Title\" : [\"War and Peace\", \"Good Omens\", \"Good Omens\"] , \n",
" \"Author\" : [\"Tolstoi\", \"Terry Pratchett\", \"Neil Gaiman\"]})\n",
"books"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.978714Z",
"start_time": "2020-06-24T19:33:41.969119Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Library | \n",
" Title | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" Oodi | \n",
" War and Peace | \n",
"
\n",
" \n",
" 1 | \n",
" Oodi | \n",
" Good Omens | \n",
"
\n",
" \n",
" 2 | \n",
" Pasila | \n",
" Good Omens | \n",
"
\n",
" \n",
" 3 | \n",
" Kallio | \n",
" War and Peace | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Library Title\n",
"0 Oodi War and Peace\n",
"1 Oodi Good Omens\n",
"2 Pasila Good Omens\n",
"3 Kallio War and Peace"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"collections = pd.DataFrame([[\"Oodi\", \"War and Peace\"],\n",
" [\"Oodi\", \"Good Omens\"],\n",
" [\"Pasila\", \"Good Omens\"],\n",
" [\"Kallio\", \"War and Peace\"]], columns=[\"Library\", \"Title\"])\n",
"collections"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"All combinations with matching keys (`Title`) are created:"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:41.990394Z",
"start_time": "2020-06-24T19:33:41.979834Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Title | \n",
" Author | \n",
" Library | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" War and Peace | \n",
" Tolstoi | \n",
" Oodi | \n",
"
\n",
" \n",
" 1 | \n",
" War and Peace | \n",
" Tolstoi | \n",
" Kallio | \n",
"
\n",
" \n",
" 2 | \n",
" Good Omens | \n",
" Terry Pratchett | \n",
" Oodi | \n",
"
\n",
" \n",
" 3 | \n",
" Good Omens | \n",
" Terry Pratchett | \n",
" Pasila | \n",
"
\n",
" \n",
" 4 | \n",
" Good Omens | \n",
" Neil Gaiman | \n",
" Oodi | \n",
"
\n",
" \n",
" 5 | \n",
" Good Omens | \n",
" Neil Gaiman | \n",
" Pasila | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Title Author Library\n",
"0 War and Peace Tolstoi Oodi\n",
"1 War and Peace Tolstoi Kallio\n",
"2 Good Omens Terry Pratchett Oodi\n",
"3 Good Omens Terry Pratchett Pasila\n",
"4 Good Omens Neil Gaiman Oodi\n",
"5 Good Omens Neil Gaiman Pasila"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"libraries_with_books_by = pd.merge(books, collections)\n",
"libraries_with_books_by"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise 2 (cycling weather)
\n",
"\n",
"Merge the processed cycling data set (from the previous exercise) and weather data set along the columns year, month, and day. Note that the names of these columns might be different in the two tables: use the `left_on` and `right_on` parameters. Then drop useless columns 'm', 'd', 'Time', and 'Time zone'.\n",
"\n",
"Write function `cycling_weather` that reads the data sets and returns the resulting DataFrame.\n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise 3 (top bands)
\n",
"\n",
"Merge the DataFrames UK top40 and the bands DataFrame that are stored in the `src` folder.\n",
"Do all this in the parameterless function `top_bands`, which should return the merged DataFrame.\n",
"Use the `left_on` and `right_on` parameters to `merge`. Test your function from the `main` function.\n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aggregates and groupings\n",
"\n",
"Let us use again the weather dataset. First, we make the column names a bit more uniform and concise. For example the columns `Year`, `m`, and `d` are not uniformly named.\n",
"\n",
"We can easily change the column names with the `rename` method of the DataFrame. Note that we cannot directly change the index `wh.columns` as it is immutable."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.062098Z",
"start_time": "2020-06-24T19:33:41.991633Z"
}
},
"outputs": [],
"source": [
"wh = pd.read_csv(\"https://raw.githubusercontent.com/csmastersUH/data_analysis_with_python_2020/master/kumpula-weather-2017.csv\")"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.080606Z",
"start_time": "2020-06-24T19:33:42.064189Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Year | \n",
" Month | \n",
" Day | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 2017 | \n",
" 1 | \n",
" 1 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" -1.0 | \n",
" 0.6 | \n",
"
\n",
" \n",
" 1 | \n",
" 2017 | \n",
" 1 | \n",
" 2 | \n",
" 00:00 | \n",
" UTC | \n",
" 4.4 | \n",
" -1.0 | \n",
" -3.9 | \n",
"
\n",
" \n",
" 2 | \n",
" 2017 | \n",
" 1 | \n",
" 3 | \n",
" 00:00 | \n",
" UTC | \n",
" 6.6 | \n",
" 7.0 | \n",
" -6.5 | \n",
"
\n",
" \n",
" 3 | \n",
" 2017 | \n",
" 1 | \n",
" 4 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 13.0 | \n",
" -12.8 | \n",
"
\n",
" \n",
" 4 | \n",
" 2017 | \n",
" 1 | \n",
" 5 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 10.0 | \n",
" -17.8 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Year Month Day Time Time zone Precipitation Snow Temperature\n",
"0 2017 1 1 00:00 UTC -1.0 -1.0 0.6\n",
"1 2017 1 2 00:00 UTC 4.4 -1.0 -3.9\n",
"2 2017 1 3 00:00 UTC 6.6 7.0 -6.5\n",
"3 2017 1 4 00:00 UTC -1.0 13.0 -12.8\n",
"4 2017 1 5 00:00 UTC -1.0 10.0 -17.8"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh3 = wh.rename(columns={\"m\": \"Month\", \"d\": \"Day\", \"Precipitation amount (mm)\" : \"Precipitation\", \n",
" \"Snow depth (cm)\" : \"Snow\", \"Air temperature (degC)\" : \"Temperature\"})\n",
"wh3.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pandas has an operation that splits a DataFrame into groups, performs some operation on each of the groups, and then combines the result from each group into a resulting DataFrame. This split-apply-combine functionality is really flexible and powerful operation. In Pandas you start by calling the `groupby` method, which splits the DataFrame into groups. In the following example the rows that contain measurements from the same month belong to the same group:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.086055Z",
"start_time": "2020-06-24T19:33:42.082166Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"groups = wh3.groupby(\"Month\")\n",
"groups"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Nothing happened yet, but the `groupby` object knows how the division into groups is done. This is called a lazy operation. We can query the number of groups in the `groupby` object:"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.092497Z",
"start_time": "2020-06-24T19:33:42.087572Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"12"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(groups)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can iterate through all the groups:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.103747Z",
"start_time": "2020-06-24T19:33:42.093972Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1 31\n",
"2 28\n",
"3 31\n",
"4 30\n",
"5 31\n",
"6 30\n",
"7 31\n",
"8 31\n",
"9 30\n",
"10 31\n",
"11 30\n",
"12 31\n"
]
}
],
"source": [
"for key, group in groups:\n",
" print(key, len(group))"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.121436Z",
"start_time": "2020-06-24T19:33:42.104826Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Year | \n",
" Month | \n",
" Day | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
"
\n",
" \n",
" \n",
" \n",
" 31 | \n",
" 2017 | \n",
" 2 | \n",
" 1 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.5 | \n",
" 4.0 | \n",
" -0.6 | \n",
"
\n",
" \n",
" 32 | \n",
" 2017 | \n",
" 2 | \n",
" 2 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.2 | \n",
" 5.0 | \n",
" -0.8 | \n",
"
\n",
" \n",
" 33 | \n",
" 2017 | \n",
" 2 | \n",
" 3 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 6.0 | \n",
" -0.2 | \n",
"
\n",
" \n",
" 34 | \n",
" 2017 | \n",
" 2 | \n",
" 4 | \n",
" 00:00 | \n",
" UTC | \n",
" 2.7 | \n",
" 6.0 | \n",
" 0.4 | \n",
"
\n",
" \n",
" 35 | \n",
" 2017 | \n",
" 2 | \n",
" 5 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 7.0 | \n",
" -2.5 | \n",
"
\n",
" \n",
" 36 | \n",
" 2017 | \n",
" 2 | \n",
" 6 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 7.0 | \n",
" -7.3 | \n",
"
\n",
" \n",
" 37 | \n",
" 2017 | \n",
" 2 | \n",
" 7 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" -12.1 | \n",
"
\n",
" \n",
" 38 | \n",
" 2017 | \n",
" 2 | \n",
" 8 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" -8.8 | \n",
"
\n",
" \n",
" 39 | \n",
" 2017 | \n",
" 2 | \n",
" 9 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" -10.1 | \n",
"
\n",
" \n",
" 40 | \n",
" 2017 | \n",
" 2 | \n",
" 10 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" -8.3 | \n",
"
\n",
" \n",
" 41 | \n",
" 2017 | \n",
" 2 | \n",
" 11 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" -5.4 | \n",
"
\n",
" \n",
" 42 | \n",
" 2017 | \n",
" 2 | \n",
" 12 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" -2.7 | \n",
"
\n",
" \n",
" 43 | \n",
" 2017 | \n",
" 2 | \n",
" 13 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" 1.5 | \n",
"
\n",
" \n",
" 44 | \n",
" 2017 | \n",
" 2 | \n",
" 14 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" 4.4 | \n",
"
\n",
" \n",
" 45 | \n",
" 2017 | \n",
" 2 | \n",
" 15 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 46 | \n",
" 2017 | \n",
" 2 | \n",
" 16 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.9 | \n",
" 8.0 | \n",
" 0.5 | \n",
"
\n",
" \n",
" 47 | \n",
" 2017 | \n",
" 2 | \n",
" 17 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.2 | \n",
" 8.0 | \n",
" 1.5 | \n",
"
\n",
" \n",
" 48 | \n",
" 2017 | \n",
" 2 | \n",
" 18 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.5 | \n",
" 5.0 | \n",
" 1.9 | \n",
"
\n",
" \n",
" 49 | \n",
" 2017 | \n",
" 2 | \n",
" 19 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.1 | \n",
" 5.0 | \n",
" 2.2 | \n",
"
\n",
" \n",
" 50 | \n",
" 2017 | \n",
" 2 | \n",
" 20 | \n",
" 00:00 | \n",
" UTC | \n",
" 2.8 | \n",
" 3.0 | \n",
" 0.4 | \n",
"
\n",
" \n",
" 51 | \n",
" 2017 | \n",
" 2 | \n",
" 21 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 7.0 | \n",
" -2.5 | \n",
"
\n",
" \n",
" 52 | \n",
" 2017 | \n",
" 2 | \n",
" 22 | \n",
" 00:00 | \n",
" UTC | \n",
" 12.2 | \n",
" 6.0 | \n",
" -4.6 | \n",
"
\n",
" \n",
" 53 | \n",
" 2017 | \n",
" 2 | \n",
" 23 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.3 | \n",
" 15.0 | \n",
" -0.7 | \n",
"
\n",
" \n",
" 54 | \n",
" 2017 | \n",
" 2 | \n",
" 24 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 13.0 | \n",
" -5.3 | \n",
"
\n",
" \n",
" 55 | \n",
" 2017 | \n",
" 2 | \n",
" 25 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.4 | \n",
" 13.0 | \n",
" -5.6 | \n",
"
\n",
" \n",
" 56 | \n",
" 2017 | \n",
" 2 | \n",
" 26 | \n",
" 00:00 | \n",
" UTC | \n",
" 2.5 | \n",
" 12.0 | \n",
" -2.0 | \n",
"
\n",
" \n",
" 57 | \n",
" 2017 | \n",
" 2 | \n",
" 27 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.0 | \n",
" 14.0 | \n",
" -2.3 | \n",
"
\n",
" \n",
" 58 | \n",
" 2017 | \n",
" 2 | \n",
" 28 | \n",
" 00:00 | \n",
" UTC | \n",
" 7.7 | \n",
" 13.0 | \n",
" 2.1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Year Month Day Time Time zone Precipitation Snow Temperature\n",
"31 2017 2 1 00:00 UTC 1.5 4.0 -0.6\n",
"32 2017 2 2 00:00 UTC 0.2 5.0 -0.8\n",
"33 2017 2 3 00:00 UTC -1.0 6.0 -0.2\n",
"34 2017 2 4 00:00 UTC 2.7 6.0 0.4\n",
"35 2017 2 5 00:00 UTC -1.0 7.0 -2.5\n",
"36 2017 2 6 00:00 UTC -1.0 7.0 -7.3\n",
"37 2017 2 7 00:00 UTC -1.0 8.0 -12.1\n",
"38 2017 2 8 00:00 UTC -1.0 8.0 -8.8\n",
"39 2017 2 9 00:00 UTC -1.0 8.0 -10.1\n",
"40 2017 2 10 00:00 UTC -1.0 8.0 -8.3\n",
"41 2017 2 11 00:00 UTC -1.0 8.0 -5.4\n",
"42 2017 2 12 00:00 UTC -1.0 8.0 -2.7\n",
"43 2017 2 13 00:00 UTC -1.0 8.0 1.5\n",
"44 2017 2 14 00:00 UTC -1.0 8.0 4.4\n",
"45 2017 2 15 00:00 UTC -1.0 8.0 0.0\n",
"46 2017 2 16 00:00 UTC 0.9 8.0 0.5\n",
"47 2017 2 17 00:00 UTC 0.2 8.0 1.5\n",
"48 2017 2 18 00:00 UTC 1.5 5.0 1.9\n",
"49 2017 2 19 00:00 UTC 1.1 5.0 2.2\n",
"50 2017 2 20 00:00 UTC 2.8 3.0 0.4\n",
"51 2017 2 21 00:00 UTC -1.0 7.0 -2.5\n",
"52 2017 2 22 00:00 UTC 12.2 6.0 -4.6\n",
"53 2017 2 23 00:00 UTC 0.3 15.0 -0.7\n",
"54 2017 2 24 00:00 UTC -1.0 13.0 -5.3\n",
"55 2017 2 25 00:00 UTC 0.4 13.0 -5.6\n",
"56 2017 2 26 00:00 UTC 2.5 12.0 -2.0\n",
"57 2017 2 27 00:00 UTC 1.0 14.0 -2.3\n",
"58 2017 2 28 00:00 UTC 7.7 13.0 2.1"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"groups.get_group(2) # Group with index two is February"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `groupby` object functions a bit like a DataFrame, so some operations which are allowed for DataFrames are also allowed for the `groupby` object. For example, we can get a subset of columns:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.127061Z",
"start_time": "2020-06-24T19:33:42.123115Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"groups[\"Temperature\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For each DataFrame corresponding to a group the Temperature column was chosen. Still nothing was shown, because we haven't applied any operation on the groups."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The common methods also include the aggregation methods. Let's try to apply the `mean` aggregation:"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.134774Z",
"start_time": "2020-06-24T19:33:42.128574Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Month\n",
"1 -2.316129\n",
"2 -2.389286\n",
"3 0.983871\n",
"4 2.676667\n",
"5 9.783871\n",
"6 13.726667\n",
"7 16.035484\n",
"8 16.183871\n",
"9 11.826667\n",
"10 5.454839\n",
"11 3.950000\n",
"12 1.741935\n",
"Name: Temperature, dtype: float64"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"groups[\"Temperature\"].mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now what happened was that after the mean aggregation was performed on each group, the results were automatically combined into a resulting DataFrame. Let's try some other aggregation:"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.141176Z",
"start_time": "2020-06-24T19:33:42.136621Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Month\n",
"1 26.9\n",
"2 21.0\n",
"3 29.7\n",
"4 26.9\n",
"5 -5.9\n",
"6 59.3\n",
"7 14.2\n",
"8 70.1\n",
"9 51.2\n",
"10 173.5\n",
"11 117.2\n",
"12 133.6\n",
"Name: Precipitation, dtype: float64"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"groups[\"Precipitation\"].sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ok, the -1.0 values in the Precipitation field are causing trouble here, let's convert them to zeros:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.159204Z",
"start_time": "2020-06-24T19:33:42.142294Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Year | \n",
" Month | \n",
" Day | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 2017 | \n",
" 1 | \n",
" 1 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.6 | \n",
"
\n",
" \n",
" 1 | \n",
" 2017 | \n",
" 1 | \n",
" 2 | \n",
" 00:00 | \n",
" UTC | \n",
" 4.4 | \n",
" 0.0 | \n",
" -3.9 | \n",
"
\n",
" \n",
" 2 | \n",
" 2017 | \n",
" 1 | \n",
" 3 | \n",
" 00:00 | \n",
" UTC | \n",
" 6.6 | \n",
" 7.0 | \n",
" -6.5 | \n",
"
\n",
" \n",
" 3 | \n",
" 2017 | \n",
" 1 | \n",
" 4 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 13.0 | \n",
" -12.8 | \n",
"
\n",
" \n",
" 4 | \n",
" 2017 | \n",
" 1 | \n",
" 5 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 10.0 | \n",
" -17.8 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Year Month Day Time Time zone Precipitation Snow Temperature\n",
"0 2017 1 1 00:00 UTC 0.0 0.0 0.6\n",
"1 2017 1 2 00:00 UTC 4.4 0.0 -3.9\n",
"2 2017 1 3 00:00 UTC 6.6 7.0 -6.5\n",
"3 2017 1 4 00:00 UTC 0.0 13.0 -12.8\n",
"4 2017 1 5 00:00 UTC 0.0 10.0 -17.8"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh4 = wh3.copy()\n",
"wh4.loc[wh4.Precipitation == -1, \"Precipitation\"] = 0\n",
"wh4.loc[wh4.Snow == -1, \"Snow\"] = 0\n",
"wh4.head()"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.164710Z",
"start_time": "2020-06-24T19:33:42.160205Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Month\n",
"1 38.9\n",
"2 35.0\n",
"3 41.7\n",
"4 39.9\n",
"5 16.1\n",
"6 76.3\n",
"7 31.2\n",
"8 86.1\n",
"9 65.2\n",
"10 184.5\n",
"11 120.2\n",
"12 140.6\n",
"Name: Precipitation, dtype: float64"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh4.groupby(\"Month\")[\"Precipitation\"].sum()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Other ways to operate on groups\n",
"\n",
"The aggregations are not the only possible operations on groups. The other possibilities are filtering, transformation, and application.\n",
"\n",
"In **filtering** some of the groups can be filtered out."
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.186293Z",
"start_time": "2020-06-24T19:33:42.165894Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Year | \n",
" Month | \n",
" Day | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
"
\n",
" \n",
" \n",
" \n",
" 273 | \n",
" 2017 | \n",
" 10 | \n",
" 1 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 9.1 | \n",
"
\n",
" \n",
" 274 | \n",
" 2017 | \n",
" 10 | \n",
" 2 | \n",
" 00:00 | \n",
" UTC | \n",
" 6.4 | \n",
" 0.0 | \n",
" 9.2 | \n",
"
\n",
" \n",
" 275 | \n",
" 2017 | \n",
" 10 | \n",
" 3 | \n",
" 00:00 | \n",
" UTC | \n",
" 21.5 | \n",
" 0.0 | \n",
" 8.3 | \n",
"
\n",
" \n",
" 276 | \n",
" 2017 | \n",
" 10 | \n",
" 4 | \n",
" 00:00 | \n",
" UTC | \n",
" 12.7 | \n",
" 0.0 | \n",
" 11.2 | \n",
"
\n",
" \n",
" 277 | \n",
" 2017 | \n",
" 10 | \n",
" 5 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.6 | \n",
" 0.0 | \n",
" 8.8 | \n",
"
\n",
" \n",
" 278 | \n",
" 2017 | \n",
" 10 | \n",
" 6 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.7 | \n",
" 0.0 | \n",
" 7.7 | \n",
"
\n",
" \n",
" 279 | \n",
" 2017 | \n",
" 10 | \n",
" 7 | \n",
" 00:00 | \n",
" UTC | \n",
" 11.7 | \n",
" 0.0 | \n",
" 8.1 | \n",
"
\n",
" \n",
" 280 | \n",
" 2017 | \n",
" 10 | \n",
" 8 | \n",
" 00:00 | \n",
" UTC | \n",
" 14.1 | \n",
" 0.0 | \n",
" 9.3 | \n",
"
\n",
" \n",
" 281 | \n",
" 2017 | \n",
" 10 | \n",
" 9 | \n",
" 00:00 | \n",
" UTC | \n",
" 18.3 | \n",
" 0.0 | \n",
" 8.6 | \n",
"
\n",
" \n",
" 282 | \n",
" 2017 | \n",
" 10 | \n",
" 10 | \n",
" 00:00 | \n",
" UTC | \n",
" 24.2 | \n",
" 0.0 | \n",
" 8.1 | \n",
"
\n",
" \n",
" 283 | \n",
" 2017 | \n",
" 10 | \n",
" 11 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.5 | \n",
" 0.0 | \n",
" 6.9 | \n",
"
\n",
" \n",
" 284 | \n",
" 2017 | \n",
" 10 | \n",
" 12 | \n",
" 00:00 | \n",
" UTC | \n",
" 18.1 | \n",
" 0.0 | \n",
" 6.0 | \n",
"
\n",
" \n",
" 285 | \n",
" 2017 | \n",
" 10 | \n",
" 13 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 7.5 | \n",
"
\n",
" \n",
" 286 | \n",
" 2017 | \n",
" 10 | \n",
" 14 | \n",
" 00:00 | \n",
" UTC | \n",
" 5.0 | \n",
" 0.0 | \n",
" 7.2 | \n",
"
\n",
" \n",
" 287 | \n",
" 2017 | \n",
" 10 | \n",
" 15 | \n",
" 00:00 | \n",
" UTC | \n",
" 3.3 | \n",
" 0.0 | \n",
" 8.3 | \n",
"
\n",
" \n",
" 288 | \n",
" 2017 | \n",
" 10 | \n",
" 16 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 10.7 | \n",
"
\n",
" \n",
" 289 | \n",
" 2017 | \n",
" 10 | \n",
" 17 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.6 | \n",
" 0.0 | \n",
" 8.5 | \n",
"
\n",
" \n",
" 290 | \n",
" 2017 | \n",
" 10 | \n",
" 18 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 8.3 | \n",
"
\n",
" \n",
" 291 | \n",
" 2017 | \n",
" 10 | \n",
" 19 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.9 | \n",
" 0.0 | \n",
" 4.6 | \n",
"
\n",
" \n",
" 292 | \n",
" 2017 | \n",
" 10 | \n",
" 20 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 2.0 | \n",
"
\n",
" \n",
" 293 | \n",
" 2017 | \n",
" 10 | \n",
" 21 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.2 | \n",
"
\n",
" \n",
" 294 | \n",
" 2017 | \n",
" 10 | \n",
" 22 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.1 | \n",
"
\n",
" \n",
" 295 | \n",
" 2017 | \n",
" 10 | \n",
" 23 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1.3 | \n",
"
\n",
" \n",
" 296 | \n",
" 2017 | \n",
" 10 | \n",
" 24 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.8 | \n",
"
\n",
" \n",
" 297 | \n",
" 2017 | \n",
" 10 | \n",
" 25 | \n",
" 00:00 | \n",
" UTC | \n",
" 8.5 | \n",
" 0.0 | \n",
" 2.1 | \n",
"
\n",
" \n",
" 298 | \n",
" 2017 | \n",
" 10 | \n",
" 26 | \n",
" 00:00 | \n",
" UTC | \n",
" 12.3 | \n",
" 2.0 | \n",
" 0.3 | \n",
"
\n",
" \n",
" 299 | \n",
" 2017 | \n",
" 10 | \n",
" 27 | \n",
" 00:00 | \n",
" UTC | \n",
" 2.7 | \n",
" 7.0 | \n",
" -0.3 | \n",
"
\n",
" \n",
" 300 | \n",
" 2017 | \n",
" 10 | \n",
" 28 | \n",
" 00:00 | \n",
" UTC | \n",
" 17.1 | \n",
" 4.0 | \n",
" 3.3 | \n",
"
\n",
" \n",
" 301 | \n",
" 2017 | \n",
" 10 | \n",
" 29 | \n",
" 00:00 | \n",
" UTC | \n",
" 3.3 | \n",
" 0.0 | \n",
" 2.1 | \n",
"
\n",
" \n",
" 302 | \n",
" 2017 | \n",
" 10 | \n",
" 30 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1.2 | \n",
"
\n",
" \n",
" 303 | \n",
" 2017 | \n",
" 10 | \n",
" 31 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" -0.4 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Year Month Day Time Time zone Precipitation Snow Temperature\n",
"273 2017 10 1 00:00 UTC 0.0 0.0 9.1\n",
"274 2017 10 2 00:00 UTC 6.4 0.0 9.2\n",
"275 2017 10 3 00:00 UTC 21.5 0.0 8.3\n",
"276 2017 10 4 00:00 UTC 12.7 0.0 11.2\n",
"277 2017 10 5 00:00 UTC 0.6 0.0 8.8\n",
"278 2017 10 6 00:00 UTC 0.7 0.0 7.7\n",
"279 2017 10 7 00:00 UTC 11.7 0.0 8.1\n",
"280 2017 10 8 00:00 UTC 14.1 0.0 9.3\n",
"281 2017 10 9 00:00 UTC 18.3 0.0 8.6\n",
"282 2017 10 10 00:00 UTC 24.2 0.0 8.1\n",
"283 2017 10 11 00:00 UTC 1.5 0.0 6.9\n",
"284 2017 10 12 00:00 UTC 18.1 0.0 6.0\n",
"285 2017 10 13 00:00 UTC 0.0 0.0 7.5\n",
"286 2017 10 14 00:00 UTC 5.0 0.0 7.2\n",
"287 2017 10 15 00:00 UTC 3.3 0.0 8.3\n",
"288 2017 10 16 00:00 UTC 0.0 0.0 10.7\n",
"289 2017 10 17 00:00 UTC 1.6 0.0 8.5\n",
"290 2017 10 18 00:00 UTC 0.0 0.0 8.3\n",
"291 2017 10 19 00:00 UTC 0.9 0.0 4.6\n",
"292 2017 10 20 00:00 UTC 0.0 0.0 2.0\n",
"293 2017 10 21 00:00 UTC 0.0 0.0 0.2\n",
"294 2017 10 22 00:00 UTC 0.0 0.0 0.1\n",
"295 2017 10 23 00:00 UTC 0.0 0.0 1.3\n",
"296 2017 10 24 00:00 UTC 0.0 0.0 0.8\n",
"297 2017 10 25 00:00 UTC 8.5 0.0 2.1\n",
"298 2017 10 26 00:00 UTC 12.3 2.0 0.3\n",
"299 2017 10 27 00:00 UTC 2.7 7.0 -0.3\n",
"300 2017 10 28 00:00 UTC 17.1 4.0 3.3\n",
"301 2017 10 29 00:00 UTC 3.3 0.0 2.1\n",
"302 2017 10 30 00:00 UTC 0.0 0.0 1.2\n",
"303 2017 10 31 00:00 UTC 0.0 0.0 -0.4"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def myfilter(df): # The filter function must return a boolean value\n",
" return df[\"Precipitation\"].sum() >= 150\n",
"\n",
"wh4.groupby(\"Month\").filter(myfilter) # Filter out months with total precipitation less that 150 mm"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In a **transformation** each group's DataFrame is manipulated in a way that retains its shape. An example of centering values, so that the deviations from the monthly means are shown:"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.230880Z",
"start_time": "2020-06-24T19:33:42.187218Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Year | \n",
" Month | \n",
" Day | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 2017 | \n",
" 1 | \n",
" 1 | \n",
" -1.254839 | \n",
" -6.903226 | \n",
" 2.916129 | \n",
"
\n",
" \n",
" 1 | \n",
" 2017 | \n",
" 1 | \n",
" 2 | \n",
" 3.145161 | \n",
" -6.903226 | \n",
" -1.583871 | \n",
"
\n",
" \n",
" 2 | \n",
" 2017 | \n",
" 1 | \n",
" 3 | \n",
" 5.345161 | \n",
" 0.096774 | \n",
" -4.183871 | \n",
"
\n",
" \n",
" 3 | \n",
" 2017 | \n",
" 1 | \n",
" 4 | \n",
" -1.254839 | \n",
" 6.096774 | \n",
" -10.483871 | \n",
"
\n",
" \n",
" 4 | \n",
" 2017 | \n",
" 1 | \n",
" 5 | \n",
" -1.254839 | \n",
" 3.096774 | \n",
" -15.483871 | \n",
"
\n",
" \n",
" 5 | \n",
" 2017 | \n",
" 1 | \n",
" 6 | \n",
" -0.954839 | \n",
" 3.096774 | \n",
" -15.483871 | \n",
"
\n",
" \n",
" 6 | \n",
" 2017 | \n",
" 1 | \n",
" 7 | \n",
" 4.045161 | \n",
" 3.096774 | \n",
" -1.483871 | \n",
"
\n",
" \n",
" 7 | \n",
" 2017 | \n",
" 1 | \n",
" 8 | \n",
" -1.254839 | \n",
" 5.096774 | \n",
" 1.816129 | \n",
"
\n",
" \n",
" 8 | \n",
" 2017 | \n",
" 1 | \n",
" 9 | \n",
" -0.154839 | \n",
" 5.096774 | \n",
" 2.816129 | \n",
"
\n",
" \n",
" 9 | \n",
" 2017 | \n",
" 1 | \n",
" 10 | \n",
" -0.954839 | \n",
" 2.096774 | \n",
" 4.016129 | \n",
"
\n",
" \n",
" 10 | \n",
" 2017 | \n",
" 1 | \n",
" 11 | \n",
" -1.254839 | \n",
" 0.096774 | \n",
" 0.716129 | \n",
"
\n",
" \n",
" 11 | \n",
" 2017 | \n",
" 1 | \n",
" 12 | \n",
" 6.745161 | \n",
" 0.096774 | \n",
" -0.483871 | \n",
"
\n",
" \n",
" 12 | \n",
" 2017 | \n",
" 1 | \n",
" 13 | \n",
" -1.154839 | \n",
" 6.096774 | \n",
" 3.416129 | \n",
"
\n",
" \n",
" 13 | \n",
" 2017 | \n",
" 1 | \n",
" 14 | \n",
" -1.154839 | \n",
" 1.096774 | \n",
" 3.116129 | \n",
"
\n",
" \n",
" 14 | \n",
" 2017 | \n",
" 1 | \n",
" 15 | \n",
" -1.254839 | \n",
" 1.096774 | \n",
" -0.483871 | \n",
"
\n",
" \n",
" 15 | \n",
" 2017 | \n",
" 1 | \n",
" 16 | \n",
" -1.254839 | \n",
" 1.096774 | \n",
" -1.883871 | \n",
"
\n",
" \n",
" 16 | \n",
" 2017 | \n",
" 1 | \n",
" 17 | \n",
" -1.054839 | \n",
" 1.096774 | \n",
" -1.183871 | \n",
"
\n",
" \n",
" 17 | \n",
" 2017 | \n",
" 1 | \n",
" 18 | \n",
" -0.354839 | \n",
" 1.096774 | \n",
" 3.416129 | \n",
"
\n",
" \n",
" 18 | \n",
" 2017 | \n",
" 1 | \n",
" 19 | \n",
" -1.254839 | \n",
" -1.903226 | \n",
" 3.916129 | \n",
"
\n",
" \n",
" 19 | \n",
" 2017 | \n",
" 1 | \n",
" 20 | \n",
" -0.954839 | \n",
" -1.903226 | \n",
" 1.716129 | \n",
"
\n",
" \n",
" 20 | \n",
" 2017 | \n",
" 1 | \n",
" 21 | \n",
" -0.854839 | \n",
" -1.903226 | \n",
" 0.516129 | \n",
"
\n",
" \n",
" 21 | \n",
" 2017 | \n",
" 1 | \n",
" 22 | \n",
" -1.054839 | \n",
" -1.903226 | \n",
" 3.316129 | \n",
"
\n",
" \n",
" 22 | \n",
" 2017 | \n",
" 1 | \n",
" 23 | \n",
" -1.154839 | \n",
" -0.903226 | \n",
" 2.416129 | \n",
"
\n",
" \n",
" 23 | \n",
" 2017 | \n",
" 1 | \n",
" 24 | \n",
" -1.254839 | \n",
" -0.903226 | \n",
" 0.116129 | \n",
"
\n",
" \n",
" 24 | \n",
" 2017 | \n",
" 1 | \n",
" 25 | \n",
" -0.654839 | \n",
" -0.903226 | \n",
" -1.483871 | \n",
"
\n",
" \n",
" 25 | \n",
" 2017 | \n",
" 1 | \n",
" 26 | \n",
" -1.254839 | \n",
" -0.903226 | \n",
" 4.216129 | \n",
"
\n",
" \n",
" 26 | \n",
" 2017 | \n",
" 1 | \n",
" 27 | \n",
" -1.254839 | \n",
" -2.903226 | \n",
" 3.916129 | \n",
"
\n",
" \n",
" 27 | \n",
" 2017 | \n",
" 1 | \n",
" 28 | \n",
" 0.545161 | \n",
" -2.903226 | \n",
" 3.116129 | \n",
"
\n",
" \n",
" 28 | \n",
" 2017 | \n",
" 1 | \n",
" 29 | \n",
" 1.345161 | \n",
" -3.903226 | \n",
" 2.916129 | \n",
"
\n",
" \n",
" 29 | \n",
" 2017 | \n",
" 1 | \n",
" 30 | \n",
" 4.345161 | \n",
" -1.903226 | \n",
" 3.316129 | \n",
"
\n",
" \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
"
\n",
" \n",
" 335 | \n",
" 2017 | \n",
" 12 | \n",
" 2 | \n",
" 0.764516 | \n",
" 3.516129 | \n",
" -0.341935 | \n",
"
\n",
" \n",
" 336 | \n",
" 2017 | \n",
" 12 | \n",
" 3 | \n",
" 2.664516 | \n",
" -1.483871 | \n",
" 3.258065 | \n",
"
\n",
" \n",
" 337 | \n",
" 2017 | \n",
" 12 | \n",
" 4 | \n",
" -4.535484 | \n",
" -1.483871 | \n",
" -0.441935 | \n",
"
\n",
" \n",
" 338 | \n",
" 2017 | \n",
" 12 | \n",
" 5 | \n",
" -3.835484 | \n",
" -1.483871 | \n",
" -1.741935 | \n",
"
\n",
" \n",
" 339 | \n",
" 2017 | \n",
" 12 | \n",
" 6 | \n",
" -4.535484 | \n",
" -1.483871 | \n",
" -2.941935 | \n",
"
\n",
" \n",
" 340 | \n",
" 2017 | \n",
" 12 | \n",
" 7 | \n",
" 11.764516 | \n",
" -1.483871 | \n",
" -2.541935 | \n",
"
\n",
" \n",
" 341 | \n",
" 2017 | \n",
" 12 | \n",
" 8 | \n",
" -2.535484 | \n",
" -1.483871 | \n",
" 3.458065 | \n",
"
\n",
" \n",
" 342 | \n",
" 2017 | \n",
" 12 | \n",
" 9 | \n",
" -4.335484 | \n",
" -1.483871 | \n",
" 2.458065 | \n",
"
\n",
" \n",
" 343 | \n",
" 2017 | \n",
" 12 | \n",
" 10 | \n",
" -4.535484 | \n",
" -1.483871 | \n",
" 0.258065 | \n",
"
\n",
" \n",
" 344 | \n",
" 2017 | \n",
" 12 | \n",
" 11 | \n",
" -3.235484 | \n",
" -1.483871 | \n",
" -0.341935 | \n",
"
\n",
" \n",
" 345 | \n",
" 2017 | \n",
" 12 | \n",
" 12 | \n",
" 30.464516 | \n",
" -1.483871 | \n",
" -0.141935 | \n",
"
\n",
" \n",
" 346 | \n",
" 2017 | \n",
" 12 | \n",
" 13 | \n",
" -0.335484 | \n",
" 3.516129 | \n",
" -0.141935 | \n",
"
\n",
" \n",
" 347 | \n",
" 2017 | \n",
" 12 | \n",
" 14 | \n",
" 0.664516 | \n",
" 2.516129 | \n",
" -0.141935 | \n",
"
\n",
" \n",
" 348 | \n",
" 2017 | \n",
" 12 | \n",
" 15 | \n",
" 5.464516 | \n",
" 8.516129 | \n",
" -0.041935 | \n",
"
\n",
" \n",
" 349 | \n",
" 2017 | \n",
" 12 | \n",
" 16 | \n",
" -3.235484 | \n",
" 4.516129 | \n",
" 0.658065 | \n",
"
\n",
" \n",
" 350 | \n",
" 2017 | \n",
" 12 | \n",
" 17 | \n",
" -4.535484 | \n",
" 3.516129 | \n",
" -1.641935 | \n",
"
\n",
" \n",
" 351 | \n",
" 2017 | \n",
" 12 | \n",
" 18 | \n",
" -1.035484 | \n",
" 3.516129 | \n",
" 0.258065 | \n",
"
\n",
" \n",
" 352 | \n",
" 2017 | \n",
" 12 | \n",
" 19 | \n",
" -4.335484 | \n",
" 1.516129 | \n",
" -0.741935 | \n",
"
\n",
" \n",
" 353 | \n",
" 2017 | \n",
" 12 | \n",
" 20 | \n",
" -0.935484 | \n",
" 1.516129 | \n",
" 0.858065 | \n",
"
\n",
" \n",
" 354 | \n",
" 2017 | \n",
" 12 | \n",
" 21 | \n",
" -4.535484 | \n",
" -1.483871 | \n",
" 0.758065 | \n",
"
\n",
" \n",
" 355 | \n",
" 2017 | \n",
" 12 | \n",
" 22 | \n",
" -4.535484 | \n",
" -1.483871 | \n",
" -1.841935 | \n",
"
\n",
" \n",
" 356 | \n",
" 2017 | \n",
" 12 | \n",
" 23 | \n",
" 3.064516 | \n",
" -1.483871 | \n",
" -0.541935 | \n",
"
\n",
" \n",
" 357 | \n",
" 2017 | \n",
" 12 | \n",
" 24 | \n",
" -4.535484 | \n",
" -1.483871 | \n",
" -2.041935 | \n",
"
\n",
" \n",
" 358 | \n",
" 2017 | \n",
" 12 | \n",
" 25 | \n",
" 1.364516 | \n",
" -1.483871 | \n",
" -1.441935 | \n",
"
\n",
" \n",
" 359 | \n",
" 2017 | \n",
" 12 | \n",
" 26 | \n",
" 3.264516 | \n",
" -1.483871 | \n",
" 0.158065 | \n",
"
\n",
" \n",
" 360 | \n",
" 2017 | \n",
" 12 | \n",
" 27 | \n",
" -3.435484 | \n",
" -1.483871 | \n",
" 2.058065 | \n",
"
\n",
" \n",
" 361 | \n",
" 2017 | \n",
" 12 | \n",
" 28 | \n",
" -0.835484 | \n",
" -1.483871 | \n",
" 1.058065 | \n",
"
\n",
" \n",
" 362 | \n",
" 2017 | \n",
" 12 | \n",
" 29 | \n",
" 3.264516 | \n",
" -1.483871 | \n",
" 2.058065 | \n",
"
\n",
" \n",
" 363 | \n",
" 2017 | \n",
" 12 | \n",
" 30 | \n",
" -0.435484 | \n",
" -1.483871 | \n",
" 0.758065 | \n",
"
\n",
" \n",
" 364 | \n",
" 2017 | \n",
" 12 | \n",
" 31 | \n",
" -1.335484 | \n",
" -1.483871 | \n",
" -0.141935 | \n",
"
\n",
" \n",
"
\n",
"
365 rows × 6 columns
\n",
"
"
],
"text/plain": [
" Year Month Day Precipitation Snow Temperature\n",
"0 2017 1 1 -1.254839 -6.903226 2.916129\n",
"1 2017 1 2 3.145161 -6.903226 -1.583871\n",
"2 2017 1 3 5.345161 0.096774 -4.183871\n",
"3 2017 1 4 -1.254839 6.096774 -10.483871\n",
"4 2017 1 5 -1.254839 3.096774 -15.483871\n",
"5 2017 1 6 -0.954839 3.096774 -15.483871\n",
"6 2017 1 7 4.045161 3.096774 -1.483871\n",
"7 2017 1 8 -1.254839 5.096774 1.816129\n",
"8 2017 1 9 -0.154839 5.096774 2.816129\n",
"9 2017 1 10 -0.954839 2.096774 4.016129\n",
"10 2017 1 11 -1.254839 0.096774 0.716129\n",
"11 2017 1 12 6.745161 0.096774 -0.483871\n",
"12 2017 1 13 -1.154839 6.096774 3.416129\n",
"13 2017 1 14 -1.154839 1.096774 3.116129\n",
"14 2017 1 15 -1.254839 1.096774 -0.483871\n",
"15 2017 1 16 -1.254839 1.096774 -1.883871\n",
"16 2017 1 17 -1.054839 1.096774 -1.183871\n",
"17 2017 1 18 -0.354839 1.096774 3.416129\n",
"18 2017 1 19 -1.254839 -1.903226 3.916129\n",
"19 2017 1 20 -0.954839 -1.903226 1.716129\n",
"20 2017 1 21 -0.854839 -1.903226 0.516129\n",
"21 2017 1 22 -1.054839 -1.903226 3.316129\n",
"22 2017 1 23 -1.154839 -0.903226 2.416129\n",
"23 2017 1 24 -1.254839 -0.903226 0.116129\n",
"24 2017 1 25 -0.654839 -0.903226 -1.483871\n",
"25 2017 1 26 -1.254839 -0.903226 4.216129\n",
"26 2017 1 27 -1.254839 -2.903226 3.916129\n",
"27 2017 1 28 0.545161 -2.903226 3.116129\n",
"28 2017 1 29 1.345161 -3.903226 2.916129\n",
"29 2017 1 30 4.345161 -1.903226 3.316129\n",
".. ... ... ... ... ... ...\n",
"335 2017 12 2 0.764516 3.516129 -0.341935\n",
"336 2017 12 3 2.664516 -1.483871 3.258065\n",
"337 2017 12 4 -4.535484 -1.483871 -0.441935\n",
"338 2017 12 5 -3.835484 -1.483871 -1.741935\n",
"339 2017 12 6 -4.535484 -1.483871 -2.941935\n",
"340 2017 12 7 11.764516 -1.483871 -2.541935\n",
"341 2017 12 8 -2.535484 -1.483871 3.458065\n",
"342 2017 12 9 -4.335484 -1.483871 2.458065\n",
"343 2017 12 10 -4.535484 -1.483871 0.258065\n",
"344 2017 12 11 -3.235484 -1.483871 -0.341935\n",
"345 2017 12 12 30.464516 -1.483871 -0.141935\n",
"346 2017 12 13 -0.335484 3.516129 -0.141935\n",
"347 2017 12 14 0.664516 2.516129 -0.141935\n",
"348 2017 12 15 5.464516 8.516129 -0.041935\n",
"349 2017 12 16 -3.235484 4.516129 0.658065\n",
"350 2017 12 17 -4.535484 3.516129 -1.641935\n",
"351 2017 12 18 -1.035484 3.516129 0.258065\n",
"352 2017 12 19 -4.335484 1.516129 -0.741935\n",
"353 2017 12 20 -0.935484 1.516129 0.858065\n",
"354 2017 12 21 -4.535484 -1.483871 0.758065\n",
"355 2017 12 22 -4.535484 -1.483871 -1.841935\n",
"356 2017 12 23 3.064516 -1.483871 -0.541935\n",
"357 2017 12 24 -4.535484 -1.483871 -2.041935\n",
"358 2017 12 25 1.364516 -1.483871 -1.441935\n",
"359 2017 12 26 3.264516 -1.483871 0.158065\n",
"360 2017 12 27 -3.435484 -1.483871 2.058065\n",
"361 2017 12 28 -0.835484 -1.483871 1.058065\n",
"362 2017 12 29 3.264516 -1.483871 2.058065\n",
"363 2017 12 30 -0.435484 -1.483871 0.758065\n",
"364 2017 12 31 -1.335484 -1.483871 -0.141935\n",
"\n",
"[365 rows x 6 columns]"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.concat([wh4.iloc[:, 0:3], \n",
" wh4.groupby(\"Month\")[[\"Precipitation\", \"Snow\", \"Temperature\"]].transform(lambda x : x - x.mean())], \n",
" axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The **apply** method is very generic and only requires that for each group's DataFrame the given function returns a DataFrame, Series, or a scalar. In the following example, we sort within each group by the temperature:"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.271807Z",
"start_time": "2020-06-24T19:33:42.233462Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" | \n",
" Year | \n",
" Month | \n",
" Day | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
"
\n",
" \n",
" Month | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 1 | \n",
" 4 | \n",
" 2017 | \n",
" 1 | \n",
" 5 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 10.0 | \n",
" -17.8 | \n",
"
\n",
" \n",
" 5 | \n",
" 2017 | \n",
" 1 | \n",
" 6 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.3 | \n",
" 10.0 | \n",
" -17.8 | \n",
"
\n",
" \n",
" 3 | \n",
" 2017 | \n",
" 1 | \n",
" 4 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 13.0 | \n",
" -12.8 | \n",
"
\n",
" \n",
" 2 | \n",
" 2017 | \n",
" 1 | \n",
" 3 | \n",
" 00:00 | \n",
" UTC | \n",
" 6.6 | \n",
" 7.0 | \n",
" -6.5 | \n",
"
\n",
" \n",
" 15 | \n",
" 2017 | \n",
" 1 | \n",
" 16 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 8.0 | \n",
" -4.2 | \n",
"
\n",
" \n",
" 1 | \n",
" 2017 | \n",
" 1 | \n",
" 2 | \n",
" 00:00 | \n",
" UTC | \n",
" 4.4 | \n",
" 0.0 | \n",
" -3.9 | \n",
"
\n",
" \n",
" 24 | \n",
" 2017 | \n",
" 1 | \n",
" 25 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.6 | \n",
" 6.0 | \n",
" -3.8 | \n",
"
\n",
" \n",
" 6 | \n",
" 2017 | \n",
" 1 | \n",
" 7 | \n",
" 00:00 | \n",
" UTC | \n",
" 5.3 | \n",
" 10.0 | \n",
" -3.8 | \n",
"
\n",
" \n",
" 16 | \n",
" 2017 | \n",
" 1 | \n",
" 17 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.2 | \n",
" 8.0 | \n",
" -3.5 | \n",
"
\n",
" \n",
" 11 | \n",
" 2017 | \n",
" 1 | \n",
" 12 | \n",
" 00:00 | \n",
" UTC | \n",
" 8.0 | \n",
" 7.0 | \n",
" -2.8 | \n",
"
\n",
" \n",
" 14 | \n",
" 2017 | \n",
" 1 | \n",
" 15 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 8.0 | \n",
" -2.8 | \n",
"
\n",
" \n",
" 23 | \n",
" 2017 | \n",
" 1 | \n",
" 24 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 6.0 | \n",
" -2.2 | \n",
"
\n",
" \n",
" 20 | \n",
" 2017 | \n",
" 1 | \n",
" 21 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.4 | \n",
" 5.0 | \n",
" -1.8 | \n",
"
\n",
" \n",
" 10 | \n",
" 2017 | \n",
" 1 | \n",
" 11 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 7.0 | \n",
" -1.6 | \n",
"
\n",
" \n",
" 19 | \n",
" 2017 | \n",
" 1 | \n",
" 20 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.3 | \n",
" 5.0 | \n",
" -0.6 | \n",
"
\n",
" \n",
" 7 | \n",
" 2017 | \n",
" 1 | \n",
" 8 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 12.0 | \n",
" -0.5 | \n",
"
\n",
" \n",
" 22 | \n",
" 2017 | \n",
" 1 | \n",
" 23 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.1 | \n",
" 6.0 | \n",
" 0.1 | \n",
"
\n",
" \n",
" 30 | \n",
" 2017 | \n",
" 1 | \n",
" 31 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 4.0 | \n",
" 0.2 | \n",
"
\n",
" \n",
" 8 | \n",
" 2017 | \n",
" 1 | \n",
" 9 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.1 | \n",
" 12.0 | \n",
" 0.5 | \n",
"
\n",
" \n",
" 28 | \n",
" 2017 | \n",
" 1 | \n",
" 29 | \n",
" 00:00 | \n",
" UTC | \n",
" 2.6 | \n",
" 3.0 | \n",
" 0.6 | \n",
"
\n",
" \n",
" 0 | \n",
" 2017 | \n",
" 1 | \n",
" 1 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 0.6 | \n",
"
\n",
" \n",
" 13 | \n",
" 2017 | \n",
" 1 | \n",
" 14 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.1 | \n",
" 8.0 | \n",
" 0.8 | \n",
"
\n",
" \n",
" 27 | \n",
" 2017 | \n",
" 1 | \n",
" 28 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.8 | \n",
" 4.0 | \n",
" 0.8 | \n",
"
\n",
" \n",
" 29 | \n",
" 2017 | \n",
" 1 | \n",
" 30 | \n",
" 00:00 | \n",
" UTC | \n",
" 5.6 | \n",
" 5.0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 21 | \n",
" 2017 | \n",
" 1 | \n",
" 22 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.2 | \n",
" 5.0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 12 | \n",
" 2017 | \n",
" 1 | \n",
" 13 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.1 | \n",
" 13.0 | \n",
" 1.1 | \n",
"
\n",
" \n",
" 17 | \n",
" 2017 | \n",
" 1 | \n",
" 18 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.9 | \n",
" 8.0 | \n",
" 1.1 | \n",
"
\n",
" \n",
" 18 | \n",
" 2017 | \n",
" 1 | \n",
" 19 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 5.0 | \n",
" 1.6 | \n",
"
\n",
" \n",
" 26 | \n",
" 2017 | \n",
" 1 | \n",
" 27 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 4.0 | \n",
" 1.6 | \n",
"
\n",
" \n",
" 9 | \n",
" 2017 | \n",
" 1 | \n",
" 10 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.3 | \n",
" 9.0 | \n",
" 1.7 | \n",
"
\n",
" \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
" ... | \n",
"
\n",
" \n",
" 12 | \n",
" 340 | \n",
" 2017 | \n",
" 12 | \n",
" 7 | \n",
" 00:00 | \n",
" UTC | \n",
" 16.3 | \n",
" 0.0 | \n",
" -0.8 | \n",
"
\n",
" \n",
" 357 | \n",
" 2017 | \n",
" 12 | \n",
" 24 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" -0.3 | \n",
"
\n",
" \n",
" 355 | \n",
" 2017 | \n",
" 12 | \n",
" 22 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" -0.1 | \n",
"
\n",
" \n",
" 338 | \n",
" 2017 | \n",
" 12 | \n",
" 5 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.7 | \n",
" 0.0 | \n",
" 0.0 | \n",
"
\n",
" \n",
" 350 | \n",
" 2017 | \n",
" 12 | \n",
" 17 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 5.0 | \n",
" 0.1 | \n",
"
\n",
" \n",
" 358 | \n",
" 2017 | \n",
" 12 | \n",
" 25 | \n",
" 00:00 | \n",
" UTC | \n",
" 5.9 | \n",
" 0.0 | \n",
" 0.3 | \n",
"
\n",
" \n",
" 334 | \n",
" 2017 | \n",
" 12 | \n",
" 1 | \n",
" 00:00 | \n",
" UTC | \n",
" 3.4 | \n",
" 0.0 | \n",
" 0.9 | \n",
"
\n",
" \n",
" 352 | \n",
" 2017 | \n",
" 12 | \n",
" 19 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.2 | \n",
" 3.0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 356 | \n",
" 2017 | \n",
" 12 | \n",
" 23 | \n",
" 00:00 | \n",
" UTC | \n",
" 7.6 | \n",
" 0.0 | \n",
" 1.2 | \n",
"
\n",
" \n",
" 337 | \n",
" 2017 | \n",
" 12 | \n",
" 4 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 1.3 | \n",
"
\n",
" \n",
" 335 | \n",
" 2017 | \n",
" 12 | \n",
" 2 | \n",
" 00:00 | \n",
" UTC | \n",
" 5.3 | \n",
" 5.0 | \n",
" 1.4 | \n",
"
\n",
" \n",
" 344 | \n",
" 2017 | \n",
" 12 | \n",
" 11 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.3 | \n",
" 0.0 | \n",
" 1.4 | \n",
"
\n",
" \n",
" 364 | \n",
" 2017 | \n",
" 12 | \n",
" 31 | \n",
" 00:00 | \n",
" UTC | \n",
" 3.2 | \n",
" 0.0 | \n",
" 1.6 | \n",
"
\n",
" \n",
" 346 | \n",
" 2017 | \n",
" 12 | \n",
" 13 | \n",
" 00:00 | \n",
" UTC | \n",
" 4.2 | \n",
" 5.0 | \n",
" 1.6 | \n",
"
\n",
" \n",
" 345 | \n",
" 2017 | \n",
" 12 | \n",
" 12 | \n",
" 00:00 | \n",
" UTC | \n",
" 35.0 | \n",
" 0.0 | \n",
" 1.6 | \n",
"
\n",
" \n",
" 347 | \n",
" 2017 | \n",
" 12 | \n",
" 14 | \n",
" 00:00 | \n",
" UTC | \n",
" 5.2 | \n",
" 4.0 | \n",
" 1.6 | \n",
"
\n",
" \n",
" 348 | \n",
" 2017 | \n",
" 12 | \n",
" 15 | \n",
" 00:00 | \n",
" UTC | \n",
" 10.0 | \n",
" 10.0 | \n",
" 1.7 | \n",
"
\n",
" \n",
" 359 | \n",
" 2017 | \n",
" 12 | \n",
" 26 | \n",
" 00:00 | \n",
" UTC | \n",
" 7.8 | \n",
" 0.0 | \n",
" 1.9 | \n",
"
\n",
" \n",
" 351 | \n",
" 2017 | \n",
" 12 | \n",
" 18 | \n",
" 00:00 | \n",
" UTC | \n",
" 3.5 | \n",
" 5.0 | \n",
" 2.0 | \n",
"
\n",
" \n",
" 343 | \n",
" 2017 | \n",
" 12 | \n",
" 10 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 2.0 | \n",
"
\n",
" \n",
" 349 | \n",
" 2017 | \n",
" 12 | \n",
" 16 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.3 | \n",
" 6.0 | \n",
" 2.4 | \n",
"
\n",
" \n",
" 363 | \n",
" 2017 | \n",
" 12 | \n",
" 30 | \n",
" 00:00 | \n",
" UTC | \n",
" 4.1 | \n",
" 0.0 | \n",
" 2.5 | \n",
"
\n",
" \n",
" 354 | \n",
" 2017 | \n",
" 12 | \n",
" 21 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.0 | \n",
" 0.0 | \n",
" 2.5 | \n",
"
\n",
" \n",
" 353 | \n",
" 2017 | \n",
" 12 | \n",
" 20 | \n",
" 00:00 | \n",
" UTC | \n",
" 3.6 | \n",
" 3.0 | \n",
" 2.6 | \n",
"
\n",
" \n",
" 361 | \n",
" 2017 | \n",
" 12 | \n",
" 28 | \n",
" 00:00 | \n",
" UTC | \n",
" 3.7 | \n",
" 0.0 | \n",
" 2.8 | \n",
"
\n",
" \n",
" 360 | \n",
" 2017 | \n",
" 12 | \n",
" 27 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.1 | \n",
" 0.0 | \n",
" 3.8 | \n",
"
\n",
" \n",
" 362 | \n",
" 2017 | \n",
" 12 | \n",
" 29 | \n",
" 00:00 | \n",
" UTC | \n",
" 7.8 | \n",
" 0.0 | \n",
" 3.8 | \n",
"
\n",
" \n",
" 342 | \n",
" 2017 | \n",
" 12 | \n",
" 9 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.2 | \n",
" 0.0 | \n",
" 4.2 | \n",
"
\n",
" \n",
" 336 | \n",
" 2017 | \n",
" 12 | \n",
" 3 | \n",
" 00:00 | \n",
" UTC | \n",
" 7.2 | \n",
" 0.0 | \n",
" 5.0 | \n",
"
\n",
" \n",
" 341 | \n",
" 2017 | \n",
" 12 | \n",
" 8 | \n",
" 00:00 | \n",
" UTC | \n",
" 2.0 | \n",
" 0.0 | \n",
" 5.2 | \n",
"
\n",
" \n",
"
\n",
"
365 rows × 8 columns
\n",
"
"
],
"text/plain": [
" Year Month Day Time Time zone Precipitation Snow Temperature\n",
"Month \n",
"1 4 2017 1 5 00:00 UTC 0.0 10.0 -17.8\n",
" 5 2017 1 6 00:00 UTC 0.3 10.0 -17.8\n",
" 3 2017 1 4 00:00 UTC 0.0 13.0 -12.8\n",
" 2 2017 1 3 00:00 UTC 6.6 7.0 -6.5\n",
" 15 2017 1 16 00:00 UTC 0.0 8.0 -4.2\n",
" 1 2017 1 2 00:00 UTC 4.4 0.0 -3.9\n",
" 24 2017 1 25 00:00 UTC 0.6 6.0 -3.8\n",
" 6 2017 1 7 00:00 UTC 5.3 10.0 -3.8\n",
" 16 2017 1 17 00:00 UTC 0.2 8.0 -3.5\n",
" 11 2017 1 12 00:00 UTC 8.0 7.0 -2.8\n",
" 14 2017 1 15 00:00 UTC 0.0 8.0 -2.8\n",
" 23 2017 1 24 00:00 UTC 0.0 6.0 -2.2\n",
" 20 2017 1 21 00:00 UTC 0.4 5.0 -1.8\n",
" 10 2017 1 11 00:00 UTC 0.0 7.0 -1.6\n",
" 19 2017 1 20 00:00 UTC 0.3 5.0 -0.6\n",
" 7 2017 1 8 00:00 UTC 0.0 12.0 -0.5\n",
" 22 2017 1 23 00:00 UTC 0.1 6.0 0.1\n",
" 30 2017 1 31 00:00 UTC 0.0 4.0 0.2\n",
" 8 2017 1 9 00:00 UTC 1.1 12.0 0.5\n",
" 28 2017 1 29 00:00 UTC 2.6 3.0 0.6\n",
" 0 2017 1 1 00:00 UTC 0.0 0.0 0.6\n",
" 13 2017 1 14 00:00 UTC 0.1 8.0 0.8\n",
" 27 2017 1 28 00:00 UTC 1.8 4.0 0.8\n",
" 29 2017 1 30 00:00 UTC 5.6 5.0 1.0\n",
" 21 2017 1 22 00:00 UTC 0.2 5.0 1.0\n",
" 12 2017 1 13 00:00 UTC 0.1 13.0 1.1\n",
" 17 2017 1 18 00:00 UTC 0.9 8.0 1.1\n",
" 18 2017 1 19 00:00 UTC 0.0 5.0 1.6\n",
" 26 2017 1 27 00:00 UTC 0.0 4.0 1.6\n",
" 9 2017 1 10 00:00 UTC 0.3 9.0 1.7\n",
"... ... ... ... ... ... ... ... ...\n",
"12 340 2017 12 7 00:00 UTC 16.3 0.0 -0.8\n",
" 357 2017 12 24 00:00 UTC 0.0 0.0 -0.3\n",
" 355 2017 12 22 00:00 UTC 0.0 0.0 -0.1\n",
" 338 2017 12 5 00:00 UTC 0.7 0.0 0.0\n",
" 350 2017 12 17 00:00 UTC 0.0 5.0 0.1\n",
" 358 2017 12 25 00:00 UTC 5.9 0.0 0.3\n",
" 334 2017 12 1 00:00 UTC 3.4 0.0 0.9\n",
" 352 2017 12 19 00:00 UTC 0.2 3.0 1.0\n",
" 356 2017 12 23 00:00 UTC 7.6 0.0 1.2\n",
" 337 2017 12 4 00:00 UTC 0.0 0.0 1.3\n",
" 335 2017 12 2 00:00 UTC 5.3 5.0 1.4\n",
" 344 2017 12 11 00:00 UTC 1.3 0.0 1.4\n",
" 364 2017 12 31 00:00 UTC 3.2 0.0 1.6\n",
" 346 2017 12 13 00:00 UTC 4.2 5.0 1.6\n",
" 345 2017 12 12 00:00 UTC 35.0 0.0 1.6\n",
" 347 2017 12 14 00:00 UTC 5.2 4.0 1.6\n",
" 348 2017 12 15 00:00 UTC 10.0 10.0 1.7\n",
" 359 2017 12 26 00:00 UTC 7.8 0.0 1.9\n",
" 351 2017 12 18 00:00 UTC 3.5 5.0 2.0\n",
" 343 2017 12 10 00:00 UTC 0.0 0.0 2.0\n",
" 349 2017 12 16 00:00 UTC 1.3 6.0 2.4\n",
" 363 2017 12 30 00:00 UTC 4.1 0.0 2.5\n",
" 354 2017 12 21 00:00 UTC 0.0 0.0 2.5\n",
" 353 2017 12 20 00:00 UTC 3.6 3.0 2.6\n",
" 361 2017 12 28 00:00 UTC 3.7 0.0 2.8\n",
" 360 2017 12 27 00:00 UTC 1.1 0.0 3.8\n",
" 362 2017 12 29 00:00 UTC 7.8 0.0 3.8\n",
" 342 2017 12 9 00:00 UTC 0.2 0.0 4.2\n",
" 336 2017 12 3 00:00 UTC 7.2 0.0 5.0\n",
" 341 2017 12 8 00:00 UTC 2.0 0.0 5.2\n",
"\n",
"[365 rows x 8 columns]"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh4.groupby(\"Month\").apply(lambda df : df.sort_values(\"Temperature\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise 4 (cyclists per day)
\n",
"\n",
"This exercise can give two points at maximum!\n",
"\n",
"Part 1.\n",
"\n",
"Read, clean and parse the bicycle data set as before. Group the rows by year, month, and day. Get the sum for each group.\n",
"Make function `cyclists_per_day` that does the above. The function should return a DataFrame.\n",
"Make sure that the columns Hour and Weekday are not included in the returned DataFrame.\n",
"\n",
"Part 2.\n",
"\n",
"In the `main` function, using the function `cyclists_per_day`, get the daily counts. The index of the DataFrame now consists of tuples (Year, Month, Day). Then restrict this data to August of year 2017, and plot this data. Don't forget to call the `plt.show` function of matplotlib. The x-axis should have ticks from 1 to 31, and there should be a curve to each measuring station. Can you spot the weekends?\n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise 5 (best record company)
\n",
"\n",
"We use again the UK top 40 data set from the first week of 1964 in the `src` folder. Here we define \"goodness\" of a record company (`Publisher`) based on the sum of the weeks on chart (WoC) of its singles. Return a DataFrame of the singles by the best record company (a subset of rows of the original DataFrame). Do this with function `best_record_company`.\n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise 6 (suicide fractions)
\n",
"\n",
"Load the suicide data set from `src` folder. This data was originally downloaded from [Kaggle](https://www.kaggle.com/szamil/who-suicide-statistics). Kaggle contains lots of interesting open data sets.\n",
"\n",
"Write function `suicide_fractions` that loads the data set and returns a Series that has the country as the (row) index and as the column the mean fraction of suicides per population in that country. In other words, the value is the average of suicide fractions. The information about year, sex and age is not used.\n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise 7 (suicide weather)
\n",
"\n",
"Copy the function `suicide fractions` from the previous exercise. \n",
"\n",
"Implement function `suicide_weather` as described below.\n",
"We use the dataset of average temperature (over years 1961-1990) in different countries from `src/List_of_countries_by_average_yearly_temperature.html` (https://en.wikipedia.org/wiki/List_of_countries_by_average_yearly_temperature) .\n",
"You can use the function `pd.read_html` to get all the tables from a html page. By default `pd.read_html` does not know which row contains column headers and which column contains row headers. Therefore, you have to give both `index_col` and `header` parameters to `read_html`. Maku sure you use the country as the (row) index for both of the DataFrames. What is the [Spearman correlation](https://en.wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient) between these variables? Use the `corr` method of Series object. Note the the two Series need not be sorted as the indices of the rows (country names) are used to align them.\n",
"\n",
"The return value of the function `suicide_weather` is a tuple (suicide_rows, temperature_rows, common_rows, spearman_correlation)\n",
"The output from the `main` function should be of the following form:\n",
"\n",
"```\n",
"Suicide DataFrame has x rows\n",
"Temperature DataFrame has x rows\n",
"Common DataFrame has x rows\n",
"Spearman correlation: x.x\n",
"```\n",
"\n",
"You might have trouble when trying to convert the temperatures to float. The is because the negative numbers on that html page use a special *unicode minus sign*, which looks typographically nice, but the float constructor cannot interpret it as a minus sign. You can try out the following example:"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.275989Z",
"start_time": "2020-06-24T19:33:42.272909Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"−5\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"could not convert string to float: '−5'\n"
]
}
],
"source": [
"s=\"\\u2212\" \"5\" # unicode minus sign and five\n",
"print(s)\n",
"try:\n",
" float(s)\n",
"except ValueError as e:\n",
" import sys\n",
" print(e, file=sys.stderr)\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But if we explicitly convert unicode minus sign to normal minus sign, it works:"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.280281Z",
"start_time": "2020-06-24T19:33:42.277216Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"-5.0"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"float(s.replace(\"\\u2212\", \"-\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Time series\n",
"\n",
"If a measurement is made at certain points in time, the resulting values with their measurement times is called a time series. In Pandas a Series whose index consists of dates/times is a time series."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's make a copy of the DataFrame that we can mess with:"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.285498Z",
"start_time": "2020-06-24T19:33:42.281448Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Index(['Year', 'Month', 'Day', 'Time', 'Time zone', 'Precipitation', 'Snow',\n",
" 'Temperature'],\n",
" dtype='object')"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh2 = wh3.copy()\n",
"wh2.columns"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The column names `Year`, `Month`, and `Day` are now in appropriate form for the `to_datetime` function. It can convert these fields into a timestamp series, which we will add to the DataFrame."
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.305980Z",
"start_time": "2020-06-24T19:33:42.287593Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Year | \n",
" Month | \n",
" Day | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
" Date | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 2017 | \n",
" 1 | \n",
" 1 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" -1.0 | \n",
" 0.6 | \n",
" 2017-01-01 | \n",
"
\n",
" \n",
" 1 | \n",
" 2017 | \n",
" 1 | \n",
" 2 | \n",
" 00:00 | \n",
" UTC | \n",
" 4.4 | \n",
" -1.0 | \n",
" -3.9 | \n",
" 2017-01-02 | \n",
"
\n",
" \n",
" 2 | \n",
" 2017 | \n",
" 1 | \n",
" 3 | \n",
" 00:00 | \n",
" UTC | \n",
" 6.6 | \n",
" 7.0 | \n",
" -6.5 | \n",
" 2017-01-03 | \n",
"
\n",
" \n",
" 3 | \n",
" 2017 | \n",
" 1 | \n",
" 4 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 13.0 | \n",
" -12.8 | \n",
" 2017-01-04 | \n",
"
\n",
" \n",
" 4 | \n",
" 2017 | \n",
" 1 | \n",
" 5 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 10.0 | \n",
" -17.8 | \n",
" 2017-01-05 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Year Month Day Time Time zone Precipitation Snow Temperature \\\n",
"0 2017 1 1 00:00 UTC -1.0 -1.0 0.6 \n",
"1 2017 1 2 00:00 UTC 4.4 -1.0 -3.9 \n",
"2 2017 1 3 00:00 UTC 6.6 7.0 -6.5 \n",
"3 2017 1 4 00:00 UTC -1.0 13.0 -12.8 \n",
"4 2017 1 5 00:00 UTC -1.0 10.0 -17.8 \n",
"\n",
" Date \n",
"0 2017-01-01 \n",
"1 2017-01-02 \n",
"2 2017-01-03 \n",
"3 2017-01-04 \n",
"4 2017-01-05 "
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh2[\"Date\"] = pd.to_datetime(wh2[[\"Year\", \"Month\", \"Day\"]])\n",
"wh2.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can now drop the useless fields:"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.317094Z",
"start_time": "2020-06-24T19:33:42.307180Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
" Date | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" -1.0 | \n",
" 0.6 | \n",
" 2017-01-01 | \n",
"
\n",
" \n",
" 1 | \n",
" 00:00 | \n",
" UTC | \n",
" 4.4 | \n",
" -1.0 | \n",
" -3.9 | \n",
" 2017-01-02 | \n",
"
\n",
" \n",
" 2 | \n",
" 00:00 | \n",
" UTC | \n",
" 6.6 | \n",
" 7.0 | \n",
" -6.5 | \n",
" 2017-01-03 | \n",
"
\n",
" \n",
" 3 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 13.0 | \n",
" -12.8 | \n",
" 2017-01-04 | \n",
"
\n",
" \n",
" 4 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 10.0 | \n",
" -17.8 | \n",
" 2017-01-05 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Time Time zone Precipitation Snow Temperature Date\n",
"0 00:00 UTC -1.0 -1.0 0.6 2017-01-01\n",
"1 00:00 UTC 4.4 -1.0 -3.9 2017-01-02\n",
"2 00:00 UTC 6.6 7.0 -6.5 2017-01-03\n",
"3 00:00 UTC -1.0 13.0 -12.8 2017-01-04\n",
"4 00:00 UTC -1.0 10.0 -17.8 2017-01-05"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh2=wh2.drop(columns=[\"Year\", \"Month\", \"Day\"])\n",
"wh2.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following method call will set the Date field as the index of the DataFrame."
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.332125Z",
"start_time": "2020-06-24T19:33:42.318949Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
"
\n",
" \n",
" Date | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 2017-01-01 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" -1.0 | \n",
" 0.6 | \n",
"
\n",
" \n",
" 2017-01-02 | \n",
" 00:00 | \n",
" UTC | \n",
" 4.4 | \n",
" -1.0 | \n",
" -3.9 | \n",
"
\n",
" \n",
" 2017-01-03 | \n",
" 00:00 | \n",
" UTC | \n",
" 6.6 | \n",
" 7.0 | \n",
" -6.5 | \n",
"
\n",
" \n",
" 2017-01-04 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 13.0 | \n",
" -12.8 | \n",
"
\n",
" \n",
" 2017-01-05 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 10.0 | \n",
" -17.8 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Time Time zone Precipitation Snow Temperature\n",
"Date \n",
"2017-01-01 00:00 UTC -1.0 -1.0 0.6\n",
"2017-01-02 00:00 UTC 4.4 -1.0 -3.9\n",
"2017-01-03 00:00 UTC 6.6 7.0 -6.5\n",
"2017-01-04 00:00 UTC -1.0 13.0 -12.8\n",
"2017-01-05 00:00 UTC -1.0 10.0 -17.8"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh2 = wh2.set_index(\"Date\")\n",
"wh2.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can now easily get a set of rows using date slices:"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.349938Z",
"start_time": "2020-06-24T19:33:42.333523Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
"
\n",
" \n",
" Date | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 2017-01-15 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" -2.8 | \n",
"
\n",
" \n",
" 2017-01-16 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 8.0 | \n",
" -4.2 | \n",
"
\n",
" \n",
" 2017-01-17 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.2 | \n",
" 8.0 | \n",
" -3.5 | \n",
"
\n",
" \n",
" 2017-01-18 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.9 | \n",
" 8.0 | \n",
" 1.1 | \n",
"
\n",
" \n",
" 2017-01-19 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 5.0 | \n",
" 1.6 | \n",
"
\n",
" \n",
" 2017-01-20 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.3 | \n",
" 5.0 | \n",
" -0.6 | \n",
"
\n",
" \n",
" 2017-01-21 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.4 | \n",
" 5.0 | \n",
" -1.8 | \n",
"
\n",
" \n",
" 2017-01-22 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.2 | \n",
" 5.0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 2017-01-23 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.1 | \n",
" 6.0 | \n",
" 0.1 | \n",
"
\n",
" \n",
" 2017-01-24 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 6.0 | \n",
" -2.2 | \n",
"
\n",
" \n",
" 2017-01-25 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.6 | \n",
" 6.0 | \n",
" -3.8 | \n",
"
\n",
" \n",
" 2017-01-26 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 6.0 | \n",
" 1.9 | \n",
"
\n",
" \n",
" 2017-01-27 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 4.0 | \n",
" 1.6 | \n",
"
\n",
" \n",
" 2017-01-28 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.8 | \n",
" 4.0 | \n",
" 0.8 | \n",
"
\n",
" \n",
" 2017-01-29 | \n",
" 00:00 | \n",
" UTC | \n",
" 2.6 | \n",
" 3.0 | \n",
" 0.6 | \n",
"
\n",
" \n",
" 2017-01-30 | \n",
" 00:00 | \n",
" UTC | \n",
" 5.6 | \n",
" 5.0 | \n",
" 1.0 | \n",
"
\n",
" \n",
" 2017-01-31 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 4.0 | \n",
" 0.2 | \n",
"
\n",
" \n",
" 2017-02-01 | \n",
" 00:00 | \n",
" UTC | \n",
" 1.5 | \n",
" 4.0 | \n",
" -0.6 | \n",
"
\n",
" \n",
" 2017-02-02 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.2 | \n",
" 5.0 | \n",
" -0.8 | \n",
"
\n",
" \n",
" 2017-02-03 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" 6.0 | \n",
" -0.2 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Time Time zone Precipitation Snow Temperature\n",
"Date \n",
"2017-01-15 00:00 UTC -1.0 8.0 -2.8\n",
"2017-01-16 00:00 UTC -1.0 8.0 -4.2\n",
"2017-01-17 00:00 UTC 0.2 8.0 -3.5\n",
"2017-01-18 00:00 UTC 0.9 8.0 1.1\n",
"2017-01-19 00:00 UTC -1.0 5.0 1.6\n",
"2017-01-20 00:00 UTC 0.3 5.0 -0.6\n",
"2017-01-21 00:00 UTC 0.4 5.0 -1.8\n",
"2017-01-22 00:00 UTC 0.2 5.0 1.0\n",
"2017-01-23 00:00 UTC 0.1 6.0 0.1\n",
"2017-01-24 00:00 UTC -1.0 6.0 -2.2\n",
"2017-01-25 00:00 UTC 0.6 6.0 -3.8\n",
"2017-01-26 00:00 UTC -1.0 6.0 1.9\n",
"2017-01-27 00:00 UTC -1.0 4.0 1.6\n",
"2017-01-28 00:00 UTC 1.8 4.0 0.8\n",
"2017-01-29 00:00 UTC 2.6 3.0 0.6\n",
"2017-01-30 00:00 UTC 5.6 5.0 1.0\n",
"2017-01-31 00:00 UTC -1.0 4.0 0.2\n",
"2017-02-01 00:00 UTC 1.5 4.0 -0.6\n",
"2017-02-02 00:00 UTC 0.2 5.0 -0.8\n",
"2017-02-03 00:00 UTC -1.0 6.0 -0.2"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh2[\"2017-01-15\":\"2017-02-03\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"By using the `date_range` function even more complicated sets can be formed. The following gets all the Mondays of July:"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.356425Z",
"start_time": "2020-06-24T19:33:42.351635Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"DatetimeIndex(['2017-07-03', '2017-07-10', '2017-07-17', '2017-07-24',\n",
" '2017-07-31'],\n",
" dtype='datetime64[ns]', freq='W-MON')"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r=pd.date_range(\"2017-07-01\", \"2017-07-31\", freq=\"w-mon\")\n",
"r"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.362187Z",
"start_time": "2020-06-24T19:33:42.357651Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"DatetimeIndex(['2017-01-01', '2017-01-02', '2017-01-03', '2017-01-04',\n",
" '2017-01-05', '2017-01-06', '2017-01-07', '2017-01-08',\n",
" '2017-01-09', '2017-01-10',\n",
" ...\n",
" '2017-12-22', '2017-12-23', '2017-12-24', '2017-12-25',\n",
" '2017-12-26', '2017-12-27', '2017-12-28', '2017-12-29',\n",
" '2017-12-30', '2017-12-31'],\n",
" dtype='datetime64[ns]', length=360, freq=None)"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh2.index.difference(r)"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.373538Z",
"start_time": "2020-06-24T19:33:42.363816Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Time | \n",
" Time zone | \n",
" Precipitation | \n",
" Snow | \n",
" Temperature | \n",
"
\n",
" \n",
" \n",
" \n",
" 2017-07-03 | \n",
" 00:00 | \n",
" UTC | \n",
" 2.2 | \n",
" -1.0 | \n",
" 14.5 | \n",
"
\n",
" \n",
" 2017-07-10 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" -1.0 | \n",
" 18.0 | \n",
"
\n",
" \n",
" 2017-07-17 | \n",
" 00:00 | \n",
" UTC | \n",
" 2.7 | \n",
" -1.0 | \n",
" 15.4 | \n",
"
\n",
" \n",
" 2017-07-24 | \n",
" 00:00 | \n",
" UTC | \n",
" -1.0 | \n",
" -1.0 | \n",
" 15.7 | \n",
"
\n",
" \n",
" 2017-07-31 | \n",
" 00:00 | \n",
" UTC | \n",
" 0.1 | \n",
" -1.0 | \n",
" 17.8 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Time Time zone Precipitation Snow Temperature\n",
"2017-07-03 00:00 UTC 2.2 -1.0 14.5\n",
"2017-07-10 00:00 UTC -1.0 -1.0 18.0\n",
"2017-07-17 00:00 UTC 2.7 -1.0 15.4\n",
"2017-07-24 00:00 UTC -1.0 -1.0 15.7\n",
"2017-07-31 00:00 UTC 0.1 -1.0 17.8"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wh2.loc[r,:]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following finds all the business days (Monday to Friday) of July:"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.380142Z",
"start_time": "2020-06-24T19:33:42.374852Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"DatetimeIndex(['2017-07-03', '2017-07-04', '2017-07-05', '2017-07-06',\n",
" '2017-07-07', '2017-07-10', '2017-07-11', '2017-07-12',\n",
" '2017-07-13', '2017-07-14', '2017-07-17', '2017-07-18',\n",
" '2017-07-19', '2017-07-20', '2017-07-21', '2017-07-24',\n",
" '2017-07-25', '2017-07-26', '2017-07-27', '2017-07-28',\n",
" '2017-07-31'],\n",
" dtype='datetime64[ns]', freq='B')"
]
},
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.date_range(\"2017-07-01\", \"2017-07-31\", freq=\"b\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can get a general idea about the `Temperature` column by plotting it. Note how the index time series is shown nicely on the x-axis."
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.676677Z",
"start_time": "2020-06-24T19:33:42.382006Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"wh2[\"Temperature\"].plot();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The graph looks a bit messy at this level of detail. We can smooth it by taking averages over a sliding window of length 30 days:"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.685941Z",
"start_time": "2020-06-24T19:33:42.677750Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Rolling [window=30,center=True,axis=0]"
]
},
"execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rolling = wh2.Temperature.rolling(30, center=True)\n",
"rolling"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {
"ExecuteTime": {
"end_time": "2020-06-24T19:33:42.937080Z",
"start_time": "2020-06-24T19:33:42.686905Z"
}
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"data = pd.DataFrame({\"Temperature\" : wh2.Temperature, \"Rolling mean\" : rolling.mean()})\n",
"data.plot();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise 8 (bicycle timeseries)
\n",
"\n",
"Write function `bicycle_timeseries` that\n",
"\n",
"* reads the data set\n",
"* cleans it\n",
"* turns its `Päivämäärä` column into (row) DatetimeIndex (that is, to row names) of that DataFrame\n",
"* returns the new DataFrame\n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Exercise 9 (commute)
\n",
"\n",
"In function `commute` do the following:\n",
"\n",
"Use the function `bicycle_timeseries` to get the bicycle data. Restrict to August 2017, group by the weekday, aggregate by summing. Set the `Weekday` column to numbers from one to seven. Then set the column `Weekday` as the (row) index. Return the resulting DataFrame from the function.\n",
"\n",
"In the `main` function plot the DataFrame. Xticklabels should be the weekdays. Don't forget to call `show` function!\n",
"\n",
"If you want the xticklabels to be `['Mon', 'Tue', 'Wed', 'Thu', 'Fr', 'Sat', 'Sun']` instead of numbers (1,..,7), then it may get a bit messy. There seems to be a problem with non-numeric `x` values. You could try the following after plotting, but you don't have to:\n",
"\n",
"```python\n",
"weekdays=\"x mon tue wed thu fri sat sun\".title().split()\n",
"plt.gca().set_xticklabels(weekdays)\n",
"```\n",
"\n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Additional information"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[Pandas cheat sheet](https://github.com/pandas-dev/pandas/blob/master/doc/cheatsheet/Pandas_Cheat_Sheet.pdf) Summary of most important Pandas' functions and methods.\n",
"\n",
"Read the article [Tidy Data](https://www.jstatsoft.org/article/view/v059i10/v59i10.pdf). The article uses the statistical software R as an example, but the ideas are relevant in general. Pandas operations maintain data in the tidy format.\n",
"\n",
"Pandas handles only one dimensional data (Series) and two dimensional data (DataFrame). While you can use [hierarchical indices](http://pandas.pydata.org/pandas-docs/stable/user_guide/advanced.html#hierarchical-indexing-multiindex) to simulate higher dimensional arrays, you should use the [xarray](http://xarray.pydata.org/en/stable/index.html) library, if you need proper higher-dimensional arrays with labels. It is basically a cross between NumPy and Pandas.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"\n",
"\n",
"\n"
]
}
],
"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.9"
},
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}