{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "\n", "\"Open\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
AB
0A0B0
1A1B1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
AB
2A2B2
3A3B3
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
CD
0C0D0
1C1D1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BC
2B2C2
3B3C3
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
AB
0A0B0
1A1B1
2A2B2
3A3B3
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
AB
0A0B0
1A1B1
0A0B0
1A1B1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
AB
0A0B0
1A1B1
2A0B0
3A1B1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
AB
first0A0B0
1A1B1
second0A0B0
1A1B1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCD
0A0B0C0D0
1A1B1C1D1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABC
0A0B0NaN
1A1B1NaN
2NaNB2C2
3NaNB3C3
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
B
0B0
1B1
2B2
3B3
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
WageNameAge
01000Jack21
11500John29
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NameOccupation
0JohnPlumber
1JackCarpenter
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
WageNameAgeOccupation
01000Jack21Carpenter
11500John29Plumber
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
NameOccupation
0JohnPlumber
1JackCarpenter
2JamesPainter
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
WageNameAgeOccupation
01000Jack21Carpenter
11500John29Plumber
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
WageNameAgeOccupation
01000.0Jack21.0Carpenter
11500.0John29.0Plumber
2NaNJamesNaNPainter
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TitleAuthor
0War and PeaceTolstoi
1Good OmensTerry Pratchett
2Good OmensNeil Gaiman
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
LibraryTitle
0OodiWar and Peace
1OodiGood Omens
2PasilaGood Omens
3KallioWar and Peace
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TitleAuthorLibrary
0War and PeaceTolstoiOodi
1War and PeaceTolstoiKallio
2Good OmensTerry PratchettOodi
3Good OmensTerry PratchettPasila
4Good OmensNeil GaimanOodi
5Good OmensNeil GaimanPasila
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
YearMonthDayTimeTime zonePrecipitationSnowTemperature
020171100:00UTC-1.0-1.00.6
120171200:00UTC4.4-1.0-3.9
220171300:00UTC6.67.0-6.5
320171400:00UTC-1.013.0-12.8
420171500:00UTC-1.010.0-17.8
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
YearMonthDayTimeTime zonePrecipitationSnowTemperature
3120172100:00UTC1.54.0-0.6
3220172200:00UTC0.25.0-0.8
3320172300:00UTC-1.06.0-0.2
3420172400:00UTC2.76.00.4
3520172500:00UTC-1.07.0-2.5
3620172600:00UTC-1.07.0-7.3
3720172700:00UTC-1.08.0-12.1
3820172800:00UTC-1.08.0-8.8
3920172900:00UTC-1.08.0-10.1
40201721000:00UTC-1.08.0-8.3
41201721100:00UTC-1.08.0-5.4
42201721200:00UTC-1.08.0-2.7
43201721300:00UTC-1.08.01.5
44201721400:00UTC-1.08.04.4
45201721500:00UTC-1.08.00.0
46201721600:00UTC0.98.00.5
47201721700:00UTC0.28.01.5
48201721800:00UTC1.55.01.9
49201721900:00UTC1.15.02.2
50201722000:00UTC2.83.00.4
51201722100:00UTC-1.07.0-2.5
52201722200:00UTC12.26.0-4.6
53201722300:00UTC0.315.0-0.7
54201722400:00UTC-1.013.0-5.3
55201722500:00UTC0.413.0-5.6
56201722600:00UTC2.512.0-2.0
57201722700:00UTC1.014.0-2.3
58201722800:00UTC7.713.02.1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
YearMonthDayTimeTime zonePrecipitationSnowTemperature
020171100:00UTC0.00.00.6
120171200:00UTC4.40.0-3.9
220171300:00UTC6.67.0-6.5
320171400:00UTC0.013.0-12.8
420171500:00UTC0.010.0-17.8
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
YearMonthDayTimeTime zonePrecipitationSnowTemperature
273201710100:00UTC0.00.09.1
274201710200:00UTC6.40.09.2
275201710300:00UTC21.50.08.3
276201710400:00UTC12.70.011.2
277201710500:00UTC0.60.08.8
278201710600:00UTC0.70.07.7
279201710700:00UTC11.70.08.1
280201710800:00UTC14.10.09.3
281201710900:00UTC18.30.08.6
2822017101000:00UTC24.20.08.1
2832017101100:00UTC1.50.06.9
2842017101200:00UTC18.10.06.0
2852017101300:00UTC0.00.07.5
2862017101400:00UTC5.00.07.2
2872017101500:00UTC3.30.08.3
2882017101600:00UTC0.00.010.7
2892017101700:00UTC1.60.08.5
2902017101800:00UTC0.00.08.3
2912017101900:00UTC0.90.04.6
2922017102000:00UTC0.00.02.0
2932017102100:00UTC0.00.00.2
2942017102200:00UTC0.00.00.1
2952017102300:00UTC0.00.01.3
2962017102400:00UTC0.00.00.8
2972017102500:00UTC8.50.02.1
2982017102600:00UTC12.32.00.3
2992017102700:00UTC2.77.0-0.3
3002017102800:00UTC17.14.03.3
3012017102900:00UTC3.30.02.1
3022017103000:00UTC0.00.01.2
3032017103100:00UTC0.00.0-0.4
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
YearMonthDayPrecipitationSnowTemperature
0201711-1.254839-6.9032262.916129
12017123.145161-6.903226-1.583871
22017135.3451610.096774-4.183871
3201714-1.2548396.096774-10.483871
4201715-1.2548393.096774-15.483871
5201716-0.9548393.096774-15.483871
62017174.0451613.096774-1.483871
7201718-1.2548395.0967741.816129
8201719-0.1548395.0967742.816129
92017110-0.9548392.0967744.016129
102017111-1.2548390.0967740.716129
1120171126.7451610.096774-0.483871
122017113-1.1548396.0967743.416129
132017114-1.1548391.0967743.116129
142017115-1.2548391.096774-0.483871
152017116-1.2548391.096774-1.883871
162017117-1.0548391.096774-1.183871
172017118-0.3548391.0967743.416129
182017119-1.254839-1.9032263.916129
192017120-0.954839-1.9032261.716129
202017121-0.854839-1.9032260.516129
212017122-1.054839-1.9032263.316129
222017123-1.154839-0.9032262.416129
232017124-1.254839-0.9032260.116129
242017125-0.654839-0.903226-1.483871
252017126-1.254839-0.9032264.216129
262017127-1.254839-2.9032263.916129
2720171280.545161-2.9032263.116129
2820171291.345161-3.9032262.916129
2920171304.345161-1.9032263.316129
.....................
33520171220.7645163.516129-0.341935
33620171232.664516-1.4838713.258065
3372017124-4.535484-1.483871-0.441935
3382017125-3.835484-1.483871-1.741935
3392017126-4.535484-1.483871-2.941935
340201712711.764516-1.483871-2.541935
3412017128-2.535484-1.4838713.458065
3422017129-4.335484-1.4838712.458065
34320171210-4.535484-1.4838710.258065
34420171211-3.235484-1.483871-0.341935
3452017121230.464516-1.483871-0.141935
34620171213-0.3354843.516129-0.141935
347201712140.6645162.516129-0.141935
348201712155.4645168.516129-0.041935
34920171216-3.2354844.5161290.658065
35020171217-4.5354843.516129-1.641935
35120171218-1.0354843.5161290.258065
35220171219-4.3354841.516129-0.741935
35320171220-0.9354841.5161290.858065
35420171221-4.535484-1.4838710.758065
35520171222-4.535484-1.483871-1.841935
356201712233.064516-1.483871-0.541935
35720171224-4.535484-1.483871-2.041935
358201712251.364516-1.483871-1.441935
359201712263.264516-1.4838710.158065
36020171227-3.435484-1.4838712.058065
36120171228-0.835484-1.4838711.058065
362201712293.264516-1.4838712.058065
36320171230-0.435484-1.4838710.758065
36420171231-1.335484-1.483871-0.141935
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
YearMonthDayTimeTime zonePrecipitationSnowTemperature
Month
1420171500:00UTC0.010.0-17.8
520171600:00UTC0.310.0-17.8
320171400:00UTC0.013.0-12.8
220171300:00UTC6.67.0-6.5
15201711600:00UTC0.08.0-4.2
120171200:00UTC4.40.0-3.9
24201712500:00UTC0.66.0-3.8
620171700:00UTC5.310.0-3.8
16201711700:00UTC0.28.0-3.5
11201711200:00UTC8.07.0-2.8
14201711500:00UTC0.08.0-2.8
23201712400:00UTC0.06.0-2.2
20201712100:00UTC0.45.0-1.8
10201711100:00UTC0.07.0-1.6
19201712000:00UTC0.35.0-0.6
720171800:00UTC0.012.0-0.5
22201712300:00UTC0.16.00.1
30201713100:00UTC0.04.00.2
820171900:00UTC1.112.00.5
28201712900:00UTC2.63.00.6
020171100:00UTC0.00.00.6
13201711400:00UTC0.18.00.8
27201712800:00UTC1.84.00.8
29201713000:00UTC5.65.01.0
21201712200:00UTC0.25.01.0
12201711300:00UTC0.113.01.1
17201711800:00UTC0.98.01.1
18201711900:00UTC0.05.01.6
26201712700:00UTC0.04.01.6
9201711000:00UTC0.39.01.7
..............................
12340201712700:00UTC16.30.0-0.8
3572017122400:00UTC0.00.0-0.3
3552017122200:00UTC0.00.0-0.1
338201712500:00UTC0.70.00.0
3502017121700:00UTC0.05.00.1
3582017122500:00UTC5.90.00.3
334201712100:00UTC3.40.00.9
3522017121900:00UTC0.23.01.0
3562017122300:00UTC7.60.01.2
337201712400:00UTC0.00.01.3
335201712200:00UTC5.35.01.4
3442017121100:00UTC1.30.01.4
3642017123100:00UTC3.20.01.6
3462017121300:00UTC4.25.01.6
3452017121200:00UTC35.00.01.6
3472017121400:00UTC5.24.01.6
3482017121500:00UTC10.010.01.7
3592017122600:00UTC7.80.01.9
3512017121800:00UTC3.55.02.0
3432017121000:00UTC0.00.02.0
3492017121600:00UTC1.36.02.4
3632017123000:00UTC4.10.02.5
3542017122100:00UTC0.00.02.5
3532017122000:00UTC3.63.02.6
3612017122800:00UTC3.70.02.8
3602017122700:00UTC1.10.03.8
3622017122900:00UTC7.80.03.8
342201712900:00UTC0.20.04.2
336201712300:00UTC7.20.05.0
341201712800:00UTC2.00.05.2
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
YearMonthDayTimeTime zonePrecipitationSnowTemperatureDate
020171100:00UTC-1.0-1.00.62017-01-01
120171200:00UTC4.4-1.0-3.92017-01-02
220171300:00UTC6.67.0-6.52017-01-03
320171400:00UTC-1.013.0-12.82017-01-04
420171500:00UTC-1.010.0-17.82017-01-05
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimeTime zonePrecipitationSnowTemperatureDate
000:00UTC-1.0-1.00.62017-01-01
100:00UTC4.4-1.0-3.92017-01-02
200:00UTC6.67.0-6.52017-01-03
300:00UTC-1.013.0-12.82017-01-04
400:00UTC-1.010.0-17.82017-01-05
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimeTime zonePrecipitationSnowTemperature
Date
2017-01-0100:00UTC-1.0-1.00.6
2017-01-0200:00UTC4.4-1.0-3.9
2017-01-0300:00UTC6.67.0-6.5
2017-01-0400:00UTC-1.013.0-12.8
2017-01-0500:00UTC-1.010.0-17.8
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimeTime zonePrecipitationSnowTemperature
Date
2017-01-1500:00UTC-1.08.0-2.8
2017-01-1600:00UTC-1.08.0-4.2
2017-01-1700:00UTC0.28.0-3.5
2017-01-1800:00UTC0.98.01.1
2017-01-1900:00UTC-1.05.01.6
2017-01-2000:00UTC0.35.0-0.6
2017-01-2100:00UTC0.45.0-1.8
2017-01-2200:00UTC0.25.01.0
2017-01-2300:00UTC0.16.00.1
2017-01-2400:00UTC-1.06.0-2.2
2017-01-2500:00UTC0.66.0-3.8
2017-01-2600:00UTC-1.06.01.9
2017-01-2700:00UTC-1.04.01.6
2017-01-2800:00UTC1.84.00.8
2017-01-2900:00UTC2.63.00.6
2017-01-3000:00UTC5.65.01.0
2017-01-3100:00UTC-1.04.00.2
2017-02-0100:00UTC1.54.0-0.6
2017-02-0200:00UTC0.25.0-0.8
2017-02-0300:00UTC-1.06.0-0.2
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
TimeTime zonePrecipitationSnowTemperature
2017-07-0300:00UTC2.2-1.014.5
2017-07-1000:00UTC-1.0-1.018.0
2017-07-1700:00UTC2.7-1.015.4
2017-07-2400:00UTC-1.0-1.015.7
2017-07-3100:00UTC0.1-1.017.8
\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", "\"Open\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 }