{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Pandas Part 2\n", "\n", "Part 1 assumed that the `data.frame` is in a tidy format, with one observation per row and one variable per column. Real-world data is often not so obliging, and we have to clean and wrangle it before we can analyze the data efficiently.\n", "\n", "Data cleaning operations \n", "\n", "- Move column to index\n", "- Move index to column\n", "- Rearranging column order\n", "- Change or rename values in the table\n", "- Dealing with missing data\n", "- Dealing with duplicate data\n", "\n", "Special operations (strings and categorical variables)\n", "\n", "- Splitting single string column into multiple columns\n", "- Joining multiple string columns into single column\n", "- Creating dummy variables from categorical variables for regression or machine learning\n", "\n", "Data wrangling (Generally involve changes of shapes)\n", "\n", "- Moving data from multiple columns to single column (melt)\n", "- Moving multiple categories in a column to separate columns (pivot)\n", "- Pivoting with aggregation (pivot_table)\n", "- Combining multiple data frames" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", "from pandas import Series, DataFrame" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data cleaning" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Swapping columns and indexes" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = DataFrame({'pid': ['101','102','103'],\n", " 'age': [23,34,45],\n", " 'wt': [150,160,170]})" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agepidwt
023101150
134102160
245103170
\n", "
" ], "text/plain": [ " age pid wt\n", "0 23 101 150\n", "1 34 102 160\n", "2 45 103 170" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agewt
pid
10123150
10234160
10345170
\n", "
" ], "text/plain": [ " age wt\n", "pid \n", "101 23 150\n", "102 34 160\n", "103 45 170" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = df.set_index('pid')\n", "df1" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidagewt
010123150
110234160
210345170
\n", "
" ], "text/plain": [ " pid age wt\n", "0 101 23 150\n", "1 102 34 160\n", "2 103 45 170" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.reset_index()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Transforming values with a map " ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agepidwt
0young101150
1old102160
2old103170
\n", "
" ], "text/plain": [ " age pid wt\n", "0 young 101 150\n", "1 old 102 160\n", "2 old 103 170" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df['age'] = df['age'].map(lambda x: 'young' if x <= 30 else 'old') \n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Explicit replacement" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agepidwt
0young101150
1old102160
2old103170
\n", "
" ], "text/plain": [ " age pid wt\n", "0 young 101 150\n", "1 old 102 160\n", "2 old 103 170" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.replace({23: 'young', 34: 'old', 45: 'old'})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Missing data" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting assay.txt\n" ] } ], "source": [ "%%file assay.txt\n", "pid,mon,tue,wed\n", "101,10,11,12\n", "102,11,-99,13\n", "103,-99,?,10\n", "104,?,?,?" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = pd.read_csv('assay.txt', na_values=['-99', '?'], index_col=0)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
montuewed
pid
10110.011.012.0
10211.0NaN13.0
103NaNNaN10.0
104NaNNaNNaN
\n", "
" ], "text/plain": [ " mon tue wed\n", "pid \n", "101 10.0 11.0 12.0\n", "102 11.0 NaN 13.0\n", "103 NaN NaN 10.0\n", "104 NaN NaN NaN" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
montuewed
pid
101FalseFalseFalse
102FalseTrueFalse
103TrueTrueFalse
104TrueTrueTrue
\n", "
" ], "text/plain": [ " mon tue wed\n", "pid \n", "101 False False False\n", "102 False True False\n", "103 True True False\n", "104 True True True" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.isnull()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
montuewed
pid
101TrueTrueTrue
102TrueFalseTrue
103FalseFalseTrue
104FalseFalseFalse
\n", "
" ], "text/plain": [ " mon tue wed\n", "pid \n", "101 True True True\n", "102 True False True\n", "103 False False True\n", "104 False False False" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.notnull()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Drop any row containing missing data" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
montuewed
pid
10110.011.012.0
\n", "
" ], "text/plain": [ " mon tue wed\n", "pid \n", "101 10.0 11.0 12.0" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.dropna()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Drop only rows where all data is missing" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
montuewed
pid
10110.011.012.0
10211.0NaN13.0
103NaNNaN10.0
\n", "
" ], "text/plain": [ " mon tue wed\n", "pid \n", "101 10.0 11.0 12.0\n", "102 11.0 NaN 13.0\n", "103 NaN NaN 10.0" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.dropna(how='all')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Drop any column with missing data" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
wed
pid
10112.0
10213.0
10310.0
\n", "
" ], "text/plain": [ " wed\n", "pid \n", "101 12.0\n", "102 13.0\n", "103 10.0" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.dropna(how='all').dropna(axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Simple imputation" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
montuewed
pid
10110.011.012.0
10211.0NaN13.0
103NaNNaN10.0
104NaNNaNNaN
\n", "
" ], "text/plain": [ " mon tue wed\n", "pid \n", "101 10.0 11.0 12.0\n", "102 11.0 NaN 13.0\n", "103 NaN NaN 10.0\n", "104 NaN NaN NaN" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Fill with column mean" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
montuewed
pid
10110.011.012.000000
10211.011.013.000000
10310.511.010.000000
10410.511.011.666667
\n", "
" ], "text/plain": [ " mon tue wed\n", "pid \n", "101 10.0 11.0 12.000000\n", "102 11.0 11.0 13.000000\n", "103 10.5 11.0 10.000000\n", "104 10.5 11.0 11.666667" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.fillna(df.mean(0))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Fill wiht specific values" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
montuewed
pid
10110.011.012.0
10211.00.013.0
1030.00.010.0
1040.00.00.0
\n", "
" ], "text/plain": [ " mon tue wed\n", "pid \n", "101 10.0 11.0 12.0\n", "102 11.0 0.0 13.0\n", "103 0.0 0.0 10.0\n", "104 0.0 0.0 0.0" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.fillna(0)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
montuewed
pid
10110.011.012.0
10211.011.013.0
10310.011.010.0
10410.011.012.0
\n", "
" ], "text/plain": [ " mon tue wed\n", "pid \n", "101 10.0 11.0 12.0\n", "102 11.0 11.0 13.0\n", "103 10.0 11.0 10.0\n", "104 10.0 11.0 12.0" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.fillna({'mon': 10, 'tue': 11, 'wed': 12})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Duplicate data" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting assay2.txt\n" ] } ], "source": [ "%%file assay2.txt\n", "pid,mon,tue,wed\n", "101,10,11,12\n", "102,11,12,13\n", "103,10,10,10\n", "102,11,12,13 # duplicate row\n", "102,10,11,14 # duplicate pid\n", "101,10,11,12 # duplicate row" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = pd.read_csv('assay2.txt', comment='#')" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidmontuewed
0101101112
1102111213
2103101010
3102111213
4102101114
5101101112
\n", "
" ], "text/plain": [ " pid mon tue wed\n", "0 101 10 11 12\n", "1 102 11 12 13\n", "2 103 10 10 10\n", "3 102 11 12 13\n", "4 102 10 11 14\n", "5 101 10 11 12" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 False\n", "1 False\n", "2 False\n", "3 True\n", "4 False\n", "5 True\n", "dtype: bool" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.duplicated()" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 False\n", "1 False\n", "2 False\n", "3 True\n", "4 True\n", "5 True\n", "dtype: bool" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.duplicated(subset=['pid'])" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidmontuewed
0101101112
1102111213
2103101010
4102101114
\n", "
" ], "text/plain": [ " pid mon tue wed\n", "0 101 10 11 12\n", "1 102 11 12 13\n", "2 103 10 10 10\n", "4 102 10 11 14" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.drop_duplicates()" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidmontuewed
0101101112
1102111213
2103101010
\n", "
" ], "text/plain": [ " pid mon tue wed\n", "0 101 10 11 12\n", "1 102 11 12 13\n", "2 103 10 10 10" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.drop_duplicates(subset=['pid'], keep='first')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Special operations on strings and factors" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Strings" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting assay3.txt\n" ] } ], "source": [ "%%file assay3.txt\n", "id,mon,tue,wed\n", "101:duke:2017,10,11,12\n", "102:duke:2017,11,12,13\n", "103:duke:2017,10,10,10\n", "102:unc:2016,11,12,13\n", "102:unc:2017,10,11,14\n", "101:unc:2017,10,11,12" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = pd.read_csv('assay3.txt')" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idmontuewed
0101:duke:2017101112
1102:duke:2017111213
2103:duke:2017101010
3102:unc:2016111213
4102:unc:2017101114
5101:unc:2017101112
\n", "
" ], "text/plain": [ " id mon tue wed\n", "0 101:duke:2017 10 11 12\n", "1 102:duke:2017 11 12 13\n", "2 103:duke:2017 10 10 10\n", "3 102:unc:2016 11 12 13\n", "4 102:unc:2017 10 11 14\n", "5 101:unc:2017 10 11 12" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 [101, duke, 2017]\n", "1 [102, duke, 2017]\n", "2 [103, duke, 2017]\n", "3 [102, unc, 2016]\n", "4 [102, unc, 2017]\n", "5 [101, unc, 2017]\n", "Name: id, dtype: object" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.id.str.split(':')" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 2017\n", "1 2017\n", "2 2017\n", "3 2016\n", "4 2017\n", "5 2017\n", "Name: id, dtype: object" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.id.str.split(':').str[-1]" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idmontuewedpidsiteyear
0101:duke:2017101112101duke2017
1102:duke:2017111213102duke2017
2103:duke:2017101010103duke2017
3102:unc:2016111213102unc2016
4102:unc:2017101114102unc2017
5101:unc:2017101112101unc2017
\n", "
" ], "text/plain": [ " id mon tue wed pid site year\n", "0 101:duke:2017 10 11 12 101 duke 2017\n", "1 102:duke:2017 11 12 13 102 duke 2017\n", "2 103:duke:2017 10 10 10 103 duke 2017\n", "3 102:unc:2016 11 12 13 102 unc 2016\n", "4 102:unc:2017 10 11 14 102 unc 2017\n", "5 101:unc:2017 10 11 12 101 unc 2017" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[['pid', 'site', 'year']] = df.id.str.split(':', expand=True)\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Rearrange and drop old id column" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidsiteyearmontuewed
0101duke2017101112
1102duke2017111213
2103duke2017101010
3102unc2016111213
4102unc2017101114
5101unc2017101112
\n", "
" ], "text/plain": [ " pid site year mon tue wed\n", "0 101 duke 2017 10 11 12\n", "1 102 duke 2017 11 12 13\n", "2 103 duke 2017 10 10 10\n", "3 102 unc 2016 11 12 13\n", "4 102 unc 2017 10 11 14\n", "5 101 unc 2017 10 11 12" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.iloc[:, np.r_[4:7, 1:4]]" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
0duke2017
1duke2017
2duke2017
3unc2016
4unc2017
5unc2017
\n", "
" ], "text/plain": [ " 0 1\n", "0 duke 2017\n", "1 duke 2017\n", "2 duke 2017\n", "3 unc 2016\n", "4 unc 2017\n", "5 unc 2017" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.id.str.extract(r'.*:(.*):(.*)', expand=True)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idmontuewedpidsiteyear
3102:unc:2016111213102unc2016
4102:unc:2017101114102unc2017
5101:unc:2017101112101unc2017
\n", "
" ], "text/plain": [ " id mon tue wed pid site year\n", "3 102:unc:2016 11 12 13 102 unc 2016\n", "4 102:unc:2017 10 11 14 102 unc 2017\n", "5 101:unc:2017 10 11 12 101 unc 2017" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[df.id.str.contains('unc')]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Joining multiple string columns" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 101:duke:2017\n", "1 102:duke:2017\n", "2 103:duke:2017\n", "3 102:unc:2016\n", "4 102:unc:2017\n", "5 101:unc:2017\n", "dtype: object" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pid + ':' + df.site + ':' + df.year" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Another method if you are combining LOTS of columns" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 101:duke:2017\n", "1 102:duke:2017\n", "2 103:duke:2017\n", "3 102:unc:2016\n", "4 102:unc:2017\n", "5 101:unc:2017\n", "dtype: object" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.iloc[:, -3:].astype('str').add(':').sum(axis=1).str[:-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Categorical variables" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidsiteyearmontuewed
0101duke2017101112
1102duke2017111213
2103duke2017101010
3102unc2016111213
4102unc2017101114
5101unc2017101112
\n", "
" ], "text/plain": [ " pid site year mon tue wed\n", "0 101 duke 2017 10 11 12\n", "1 102 duke 2017 11 12 13\n", "2 103 duke 2017 10 10 10\n", "3 102 unc 2016 11 12 13\n", "4 102 unc 2017 10 11 14\n", "5 101 unc 2017 10 11 12" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = df.iloc[:, np.r_[4:7, 1:4]]\n", "df" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pd.options.mode.chained_assignment = None # turns off harmless warning\n", "df['pid'] = df['pid'].astype('category')\n", "df['site'] = df['site'].astype('category')" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 duke\n", "1 duke\n", "2 duke\n", "3 unc\n", "4 unc\n", "5 unc\n", "Name: site, dtype: category\n", "Categories (2, object): [duke, unc]" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.site" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 0\n", "1 0\n", "2 0\n", "3 1\n", "4 1\n", "5 1\n", "dtype: int8" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.site.cat.codes" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Index(['duke', 'unc'], dtype='object')" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.site.cat.categories" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 duke\n", "1 duke\n", "2 duke\n", "3 unc\n", "4 unc\n", "5 unc\n", "Name: site, dtype: category\n", "Categories (2, object): [unc < duke]" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.site.cat.reorder_categories(['unc', 'duke'], ordered=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### One-hot encoding\n", "\n", "For regression models, it is often necessary to convert a single column of categorical variables into dummy variable, with one dummy variable for each possible category. In machine learning applications, this is known as one-hot encoding. " ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": true }, "outputs": [], "source": [ "n = 10\n", "race = np.random.choice(['white', 'black', 'brown', 'yellow'], n)\n", "vals = np.random.random(n)\n", "df = DataFrame(dict(race=race, vals=vals))" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
racevals
0brown0.260416
1white0.079823
2black0.912978
3black0.711759
4white0.059453
5brown0.024857
6white0.960330
7brown0.870268
8yellow0.008312
9brown0.345326
\n", "
" ], "text/plain": [ " race vals\n", "0 brown 0.260416\n", "1 white 0.079823\n", "2 black 0.912978\n", "3 black 0.711759\n", "4 white 0.059453\n", "5 brown 0.024857\n", "6 white 0.960330\n", "7 brown 0.870268\n", "8 yellow 0.008312\n", "9 brown 0.345326" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df['race'] = df['race'].astype('category')" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 brown\n", "1 white\n", "2 black\n", "3 black\n", "4 white\n", "5 brown\n", "6 white\n", "7 brown\n", "8 yellow\n", "9 brown\n", "Name: race, dtype: category\n", "Categories (4, object): [black, brown, white, yellow]" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.race" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
blackbrownwhiteyellow
00100
10010
21000
31000
40010
50100
60010
70100
80001
90100
\n", "
" ], "text/plain": [ " black brown white yellow\n", "0 0 1 0 0\n", "1 0 0 1 0\n", "2 1 0 0 0\n", "3 1 0 0 0\n", "4 0 0 1 0\n", "5 0 1 0 0\n", "6 0 0 1 0\n", "7 0 1 0 0\n", "8 0 0 0 1\n", "9 0 1 0 0" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = pd.get_dummies(df.race)\n", "df1" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
racevalsblackbrownwhiteyellow
0brown0.2604160100
1white0.0798230010
2black0.9129781000
3black0.7117591000
4white0.0594530010
5brown0.0248570100
6white0.9603300010
7brown0.8702680100
8yellow0.0083120001
9brown0.3453260100
\n", "
" ], "text/plain": [ " race vals black brown white yellow\n", "0 brown 0.260416 0 1 0 0\n", "1 white 0.079823 0 0 1 0\n", "2 black 0.912978 1 0 0 0\n", "3 black 0.711759 1 0 0 0\n", "4 white 0.059453 0 0 1 0\n", "5 brown 0.024857 0 1 0 0\n", "6 white 0.960330 0 0 1 0\n", "7 brown 0.870268 0 1 0 0\n", "8 yellow 0.008312 0 0 0 1\n", "9 brown 0.345326 0 1 0 0" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.join(df1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data Wrangling" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Hierarchical indexing" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": true }, "outputs": [], "source": [ "birth_weight = np.random.normal(7, 1, 8)\n", "df = DataFrame(birth_weight,\n", " index=[['anne']*3 + ['bella']*3 + ['carrie']*2,\n", " [1,2,3,1,2,3,1,2]],\n", " columns=['weight'])\n", "df.index.names = ['women', 'pregnancy']" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
womenpregnancy
anne18.661477
26.524455
37.052574
bella17.183759
27.095648
39.075680
carrie16.659004
28.807852
\n", "
" ], "text/plain": [ " weight\n", "women pregnancy \n", "anne 1 8.661477\n", " 2 6.524455\n", " 3 7.052574\n", "bella 1 7.183759\n", " 2 7.095648\n", " 3 9.075680\n", "carrie 1 6.659004\n", " 2 8.807852" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "MultiIndex(levels=[['anne', 'bella', 'carrie'], [1, 2, 3]],\n", " labels=[[0, 0, 0, 1, 1, 1, 2, 2], [0, 1, 2, 0, 1, 2, 0, 1]],\n", " names=['women', 'pregnancy'])" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.index" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Swapping levels" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
pregnancywomen
1anne8.661477
bella7.183759
carrie6.659004
2anne6.524455
bella7.095648
carrie8.807852
3anne7.052574
bella9.075680
\n", "
" ], "text/plain": [ " weight\n", "pregnancy women \n", "1 anne 8.661477\n", " bella 7.183759\n", " carrie 6.659004\n", "2 anne 6.524455\n", " bella 7.095648\n", " carrie 8.807852\n", "3 anne 7.052574\n", " bella 9.075680" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.swaplevel().sort_index(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Partial indexing" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
pregnancy
17.183759
27.095648
39.075680
\n", "
" ], "text/plain": [ " weight\n", "pregnancy \n", "1 7.183759\n", "2 7.095648\n", "3 9.075680" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.loc['bella']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Unstack\n", "\n", "This rotates from the rows to the columns." ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
womenannebellacarrie
pregnancy
18.6614777.1837596.659004
26.5244557.0956488.807852
37.0525749.075680NaN
\n", "
" ], "text/plain": [ " weight \n", "women anne bella carrie\n", "pregnancy \n", "1 8.661477 7.183759 6.659004\n", "2 6.524455 7.095648 8.807852\n", "3 7.052574 9.075680 NaN" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.unstack(level=0)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
pregnancy123
women
anne8.6614776.5244557.052574
bella7.1837597.0956489.075680
carrie6.6590048.807852NaN
\n", "
" ], "text/plain": [ " weight \n", "pregnancy 1 2 3\n", "women \n", "anne 8.661477 6.524455 7.052574\n", "bella 7.183759 7.095648 9.075680\n", "carrie 6.659004 8.807852 NaN" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.unstack(level=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Stack\n", "\n", "This rotates from the columns to the rows" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": true }, "outputs": [], "source": [ "s1 = df.unstack(level=0)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
womenannebellacarrie
pregnancy
18.6614777.1837596.659004
26.5244557.0956488.807852
37.0525749.075680NaN
\n", "
" ], "text/plain": [ " weight \n", "women anne bella carrie\n", "pregnancy \n", "1 8.661477 7.183759 6.659004\n", "2 6.524455 7.095648 8.807852\n", "3 7.052574 9.075680 NaN" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s1" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
womenannebellacarrie
pregnancy
1weight8.6614777.1837596.659004
2weight6.5244557.0956488.807852
3weight7.0525749.075680NaN
\n", "
" ], "text/plain": [ "women anne bella carrie\n", "pregnancy \n", "1 weight 8.661477 7.183759 6.659004\n", "2 weight 6.524455 7.095648 8.807852\n", "3 weight 7.052574 9.075680 NaN" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s1.stack(level=0)" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
pregnancywomen
1anne8.661477
bella7.183759
carrie6.659004
2anne6.524455
bella7.095648
carrie8.807852
3anne7.052574
bella9.075680
\n", "
" ], "text/plain": [ " weight\n", "pregnancy women \n", "1 anne 8.661477\n", " bella 7.183759\n", " carrie 6.659004\n", "2 anne 6.524455\n", " bella 7.095648\n", " carrie 8.807852\n", "3 anne 7.052574\n", " bella 9.075680" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s1.stack(level=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### \"Flattening\" a hierarchical index" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
womenpregnancyweight
0anne18.661477
1anne26.524455
2anne37.052574
3bella17.183759
4bella27.095648
5bella39.075680
6carrie16.659004
7carrie28.807852
\n", "
" ], "text/plain": [ " women pregnancy weight\n", "0 anne 1 8.661477\n", "1 anne 2 6.524455\n", "2 anne 3 7.052574\n", "3 bella 1 7.183759\n", "4 bella 2 7.095648\n", "5 bella 3 9.075680\n", "6 carrie 1 6.659004\n", "7 carrie 2 8.807852" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.reset_index()" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
womenweight
pregnancy
1anne8.661477
2anne6.524455
3anne7.052574
1bella7.183759
2bella7.095648
3bella9.075680
1carrie6.659004
2carrie8.807852
\n", "
" ], "text/plain": [ " women weight\n", "pregnancy \n", "1 anne 8.661477\n", "2 anne 6.524455\n", "3 anne 7.052574\n", "1 bella 7.183759\n", "2 bella 7.095648\n", "3 bella 9.075680\n", "1 carrie 6.659004\n", "2 carrie 8.807852" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.reset_index(level=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Summary by level" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
womenpregnancy
anne18.661477
26.524455
37.052574
bella17.183759
27.095648
39.075680
carrie16.659004
28.807852
\n", "
" ], "text/plain": [ " weight\n", "women pregnancy \n", "anne 1 8.661477\n", " 2 6.524455\n", " 3 7.052574\n", "bella 1 7.183759\n", " 2 7.095648\n", " 3 9.075680\n", "carrie 1 6.659004\n", " 2 8.807852" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
women
anne7.412835
bella7.785029
carrie7.733428
\n", "
" ], "text/plain": [ " weight\n", "women \n", "anne 7.412835\n", "bella 7.785029\n", "carrie 7.733428" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.mean(level=0)" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weight
pregnancy
17.501413
27.475985
38.064127
\n", "
" ], "text/plain": [ " weight\n", "pregnancy \n", "1 7.501413\n", "2 7.475985\n", "3 8.064127" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.mean(level=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Reshape and pivot data" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%load_ext rpy2.ipython" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "collapsed": true }, "outputs": [], "source": [ "iris = %R iris" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Sepal.LengthSepal.WidthPetal.LengthPetal.WidthSpecies
15.13.51.40.2setosa
24.93.01.40.2setosa
34.73.21.30.2setosa
44.63.11.50.2setosa
55.03.61.40.2setosa
\n", "
" ], "text/plain": [ " Sepal.Length Sepal.Width Petal.Length Petal.Width Species\n", "1 5.1 3.5 1.4 0.2 setosa\n", "2 4.9 3.0 1.4 0.2 setosa\n", "3 4.7 3.2 1.3 0.2 setosa\n", "4 4.6 3.1 1.5 0.2 setosa\n", "5 5.0 3.6 1.4 0.2 setosa" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### From wide to long\n", "\n", "This is often necessary for plotting routines" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Speciesvariablevalue
0setosaSepal.Length5.1
1setosaSepal.Length4.9
2setosaSepal.Length4.7
3setosaSepal.Length4.6
4setosaSepal.Length5.0
\n", "
" ], "text/plain": [ " Species variable value\n", "0 setosa Sepal.Length 5.1\n", "1 setosa Sepal.Length 4.9\n", "2 setosa Sepal.Length 4.7\n", "3 setosa Sepal.Length 4.6\n", "4 setosa Sepal.Length 5.0" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris1 = pd.melt(iris, id_vars=['Species'])\n", "iris1.head()" ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import seaborn as sns\n", "sns.set_context('notebook', font_scale=1.5)" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nIYQQwqP8P9yM3U+9gPn1AAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "g = sns.factorplot(data=iris1, x='Species', y='value', \n", " col='variable', col_wrap=2,\n", " kind='swarm')\n", "g.set_titles('{col_name}')\n", "pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Pivot\n", "\n", "Pivot splits a column into multiple columns" ] }, { "cell_type": "code", "execution_count": 73, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pid = np.r_[0:5, 0:5]\n", "time = ['A']*5 + ['B']*5\n", "val = np.random.normal(10,1,10)\n", "df = DataFrame(dict(pid=pid, time=time, val=val), \n", " columns=['pid', 'time', 'val'])" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidtimeval
00A9.066841
11A9.113788
22A10.965594
33A9.848895
44A9.194968
50B10.819055
61B9.900527
72B11.007177
83B9.586152
94B9.486819
\n", "
" ], "text/plain": [ " pid time val\n", "0 0 A 9.066841\n", "1 1 A 9.113788\n", "2 2 A 10.965594\n", "3 3 A 9.848895\n", "4 4 A 9.194968\n", "5 0 B 10.819055\n", "6 1 B 9.900527\n", "7 2 B 11.007177\n", "8 3 B 9.586152\n", "9 4 B 9.486819" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
val
pid01234
time
A9.0668419.11378810.9655949.8488959.194968
B10.8190559.90052711.0071779.5861529.486819
\n", "
" ], "text/plain": [ " val \n", "pid 0 1 2 3 4\n", "time \n", "A 9.066841 9.113788 10.965594 9.848895 9.194968\n", "B 10.819055 9.900527 11.007177 9.586152 9.486819" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot(index='time', columns='pid')" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timeAB
pid
09.06684110.819055
19.1137889.900527
210.96559411.007177
39.8488959.586152
49.1949689.486819
\n", "
" ], "text/plain": [ "time A B\n", "pid \n", "0 9.066841 10.819055\n", "1 9.113788 9.900527\n", "2 10.965594 11.007177\n", "3 9.848895 9.586152\n", "4 9.194968 9.486819" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot(index='pid', columns='time', values='val')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that `pivot` is `set_index` followed by `unstack" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
val
pidtime
0A9.066841
1A9.113788
2A10.965594
3A9.848895
4A9.194968
0B10.819055
1B9.900527
2B11.007177
3B9.586152
4B9.486819
\n", "
" ], "text/plain": [ " val\n", "pid time \n", "0 A 9.066841\n", "1 A 9.113788\n", "2 A 10.965594\n", "3 A 9.848895\n", "4 A 9.194968\n", "0 B 10.819055\n", "1 B 9.900527\n", "2 B 11.007177\n", "3 B 9.586152\n", "4 B 9.486819" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.set_index(['pid', 'time'])" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
val
timeAB
pid
09.06684110.819055
19.1137889.900527
210.96559411.007177
39.8488959.586152
49.1949689.486819
\n", "
" ], "text/plain": [ " val \n", "time A B\n", "pid \n", "0 9.066841 10.819055\n", "1 9.113788 9.900527\n", "2 10.965594 11.007177\n", "3 9.848895 9.586152\n", "4 9.194968 9.486819" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.set_index(['pid', 'time']).unstack('time')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`pivot` can be reversed by `melt`." ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timeAB
pid
09.06684110.819055
19.1137889.900527
210.96559411.007177
39.8488959.586152
49.1949689.486819
\n", "
" ], "text/plain": [ "time A B\n", "pid \n", "0 9.066841 10.819055\n", "1 9.113788 9.900527\n", "2 10.965594 11.007177\n", "3 9.848895 9.586152\n", "4 9.194968 9.486819" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = df.pivot(index='pid', columns='time', values='val')\n", "df1" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timepidAB
009.06684110.819055
119.1137889.900527
2210.96559411.007177
339.8488959.586152
449.1949689.486819
\n", "
" ], "text/plain": [ "time pid A B\n", "0 0 9.066841 10.819055\n", "1 1 9.113788 9.900527\n", "2 2 10.965594 11.007177\n", "3 3 9.848895 9.586152\n", "4 4 9.194968 9.486819" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = df1.reset_index()\n", "df1" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidtimevalue
00A9.066841
11A9.113788
22A10.965594
33A9.848895
44A9.194968
50B10.819055
61B9.900527
72B11.007177
83B9.586152
94B9.486819
\n", "
" ], "text/plain": [ " pid time value\n", "0 0 A 9.066841\n", "1 1 A 9.113788\n", "2 2 A 10.965594\n", "3 3 A 9.848895\n", "4 4 A 9.194968\n", "5 0 B 10.819055\n", "6 1 B 9.900527\n", "7 2 B 11.007177\n", "8 3 B 9.586152\n", "9 4 B 9.486819" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.melt(df1, ['pid'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Pivot tables and cross-tabulation\n", "\n", "Pivot tables can be an alternative to using `groupby`. They are also useful for calculating marginals." ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [], "source": [ "pid = np.r_[0:4, 0:4]\n", "time = ['A']*4 + ['B']*4\n", "grp = np.tile(['Case', 'Control'], 4)\n", "val = np.random.normal(10,1,8)\n", "df = DataFrame(dict(pid=pid, grp=grp, time=time, val=val), \n", " columns=['pid', 'grp', 'time', 'val'])" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidgrptimeval
00CaseA9.081981
11ControlA9.068653
22CaseA9.346933
33ControlA8.895022
40CaseB11.139738
51ControlB10.489634
62CaseB9.913781
73ControlB9.703207
\n", "
" ], "text/plain": [ " pid grp time val\n", "0 0 Case A 9.081981\n", "1 1 Control A 9.068653\n", "2 2 Case A 9.346933\n", "3 3 Control A 8.895022\n", "4 0 Case B 11.139738\n", "5 1 Control B 10.489634\n", "6 2 Case B 9.913781\n", "7 3 Control B 9.703207" ] }, "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
val
pidgrp
0Case10.110860
1Control9.779143
2Case9.630357
3Control9.299114
\n", "
" ], "text/plain": [ " val\n", "pid grp \n", "0 Case 10.110860\n", "1 Control 9.779143\n", "2 Case 9.630357\n", "3 Control 9.299114" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot_table(index=['pid', 'grp'])" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
val
pidtime
0A9.081981
B11.139738
1A9.068653
B10.489634
2A9.346933
B9.913781
3A8.895022
B9.703207
\n", "
" ], "text/plain": [ " val\n", "pid time \n", "0 A 9.081981\n", " B 11.139738\n", "1 A 9.068653\n", " B 10.489634\n", "2 A 9.346933\n", " B 9.913781\n", "3 A 8.895022\n", " B 9.703207" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot_table(index=['pid', 'time'])" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
val
grpCaseControl
pid
010.110860NaN
1NaN9.779143
29.630357NaN
3NaN9.299114
\n", "
" ], "text/plain": [ " val \n", "grp Case Control\n", "pid \n", "0 10.110860 NaN\n", "1 NaN 9.779143\n", "2 9.630357 NaN\n", "3 NaN 9.299114" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot_table(index='pid', columns=['grp'])" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
val
pid
010.110860
19.779143
29.630357
39.299114
\n", "
" ], "text/plain": [ " val\n", "pid \n", "0 10.110860\n", "1 9.779143\n", "2 9.630357\n", "3 9.299114" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot_table(index='pid')" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Sepal.LengthSepal.WidthPetal.LengthPetal.WidthSpecies
15.13.51.40.2setosa
24.93.01.40.2setosa
34.73.21.30.2setosa
44.63.11.50.2setosa
55.03.61.40.2setosa
\n", "
" ], "text/plain": [ " Sepal.Length Sepal.Width Petal.Length Petal.Width Species\n", "1 5.1 3.5 1.4 0.2 setosa\n", "2 4.9 3.0 1.4 0.2 setosa\n", "3 4.7 3.2 1.3 0.2 setosa\n", "4 4.6 3.1 1.5 0.2 setosa\n", "5 5.0 3.6 1.4 0.2 setosa" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris.head()" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Petal.LengthPetal.WidthSepal.LengthSepal.Width
Species
setosa1.4620.2465.0063.428
versicolor4.2601.3265.9362.770
virginica5.5522.0266.5882.974
\n", "
" ], "text/plain": [ " Petal.Length Petal.Width Sepal.Length Sepal.Width\n", "Species \n", "setosa 1.462 0.246 5.006 3.428\n", "versicolor 4.260 1.326 5.936 2.770\n", "virginica 5.552 2.026 6.588 2.974" ] }, "execution_count": 89, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris.pivot_table(index='Species', aggfunc='mean')" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Petal.LengthPetal.Width
Species
setosa1.4620.246
versicolor4.2601.326
virginica5.5522.026
\n", "
" ], "text/plain": [ " Petal.Length Petal.Width\n", "Species \n", "setosa 1.462 0.246\n", "versicolor 4.260 1.326\n", "virginica 5.552 2.026" ] }, "execution_count": 90, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris.pivot_table(index='Species', \n", " values=['Petal.Length', 'Petal.Width'], \n", " aggfunc='mean')" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Petal.LengthPetal.Width
Species
setosa1.4620.246000
versicolor4.2601.326000
virginica5.5522.026000
All3.7581.199333
\n", "
" ], "text/plain": [ " Petal.Length Petal.Width\n", "Species \n", "setosa 1.462 0.246000\n", "versicolor 4.260 1.326000\n", "virginica 5.552 2.026000\n", "All 3.758 1.199333" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris.pivot_table(index='Species', \n", " values=['Petal.Length', 'Petal.Width'], \n", " aggfunc='mean',\n", " margins=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Simple cross tabulation of margins" ] }, { "cell_type": "code", "execution_count": 92, "metadata": { "collapsed": true }, "outputs": [], "source": [ "deaths = [10, 12, 15, 18]\n", "sex = ['m', 'f', 'm', 'f']\n", "smoker = ['n', 'n', 'y', 'y']\n", "df = DataFrame(dict(deaths=deaths, sex=sex, smoker=smoker))" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
deathssexsmoker
010mn
112fn
215my
318fy
\n", "
" ], "text/plain": [ " deaths sex smoker\n", "0 10 m n\n", "1 12 f n\n", "2 15 m y\n", "3 18 f y" ] }, "execution_count": 93, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
deaths
sexfmAll
smoker
n121022
y181533
All302555
\n", "
" ], "text/plain": [ " deaths \n", "sex f m All\n", "smoker \n", "n 12 10 22\n", "y 18 15 33\n", "All 30 25 55" ] }, "execution_count": 94, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot_table(index='smoker', columns='sex', aggfunc='sum', margins=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Cross-tabulation" ] }, { "cell_type": "code", "execution_count": 95, "metadata": { "collapsed": true }, "outputs": [], "source": [ "smoker = np.random.choice(['y', 'n'], 100)\n", "status = np.random.choice(['alive', 'dead'], 100)" ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
col_0alivedeadAll
row_0
n222951
y262349
All4852100
\n", "
" ], "text/plain": [ "col_0 alive dead All\n", "row_0 \n", "n 22 29 51\n", "y 26 23 49\n", "All 48 52 100" ] }, "execution_count": 96, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.crosstab(smoker, status, margins=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### We cna do this with pivot_table but it takes a bit more work" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [], "source": [ "df = DataFrame(dict(smoker=smoker, status=status, val=np.ones(100)))" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
smokerstatusval
0yalive1.0
1ndead1.0
2nalive1.0
3ydead1.0
4yalive1.0
\n", "
" ], "text/plain": [ " smoker status val\n", "0 y alive 1.0\n", "1 n dead 1.0\n", "2 n alive 1.0\n", "3 y dead 1.0\n", "4 y alive 1.0" ] }, "execution_count": 98, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 99, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
val
statusalivedeadAll
smoker
n222951
y262349
All4852100
\n", "
" ], "text/plain": [ " val \n", "status alive dead All\n", "smoker \n", "n 22 29 51\n", "y 26 23 49\n", "All 48 52 100" ] }, "execution_count": 99, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.pivot_table(index='smoker', columns='status', aggfunc='count', margins=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Merging data" ] }, { "cell_type": "code", "execution_count": 100, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pids1 = [101, 102, 103]\n", "vals1 = [10, 20, 30]\n", "pids2 = [104,105,106]\n", "vals2 = [40, 50, 60]\n", "pids3 = [101, 103, 105]\n", "vals3 = [70, 80, 90]" ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [], "source": [ "df1 = DataFrame(dict(pid=pids1, x=vals1))\n", "df2 = DataFrame(dict(pid=pids2, x=vals2))\n", "df3 = DataFrame(dict(pid=pids1, y=vals2))\n", "df4 = DataFrame(dict(pid=pids3, y=vals3))\n", "df5 = DataFrame(dict(pid=pids1, z=vals2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Appending rows" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidx
010110
110220
210330
\n", "
" ], "text/plain": [ " pid x\n", "0 101 10\n", "1 102 20\n", "2 103 30" ] }, "execution_count": 102, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1" ] }, { "cell_type": "code", "execution_count": 103, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidx
010440
110550
210660
\n", "
" ], "text/plain": [ " pid x\n", "0 104 40\n", "1 105 50\n", "2 106 60" ] }, "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidx
010110
110220
210330
010440
110550
210660
\n", "
" ], "text/plain": [ " pid x\n", "0 101 10\n", "1 102 20\n", "2 103 30\n", "0 104 40\n", "1 105 50\n", "2 106 60" ] }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([df1, df2])" ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidx
010110
110220
210330
310440
410550
510660
\n", "
" ], "text/plain": [ " pid x\n", "0 101 10\n", "1 102 20\n", "2 103 30\n", "3 104 40\n", "4 105 50\n", "5 106 60" ] }, "execution_count": 105, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([df1, df2]).reset_index(drop=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Database style joins" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidx
010110
110220
210330
\n", "
" ], "text/plain": [ " pid x\n", "0 101 10\n", "1 102 20\n", "2 103 30" ] }, "execution_count": 106, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidy
010140
110250
210360
\n", "
" ], "text/plain": [ " pid y\n", "0 101 40\n", "1 102 50\n", "2 103 60" ] }, "execution_count": 107, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df3" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
smokerstatusval
0yalive1.0
1ndead1.0
2nalive1.0
3ydead1.0
4yalive1.0
5yalive1.0
6ydead1.0
7nalive1.0
8yalive1.0
9yalive1.0
10yalive1.0
11ydead1.0
12ydead1.0
13ndead1.0
14ndead1.0
15nalive1.0
16ydead1.0
17ydead1.0
18yalive1.0
19ydead1.0
20ndead1.0
21nalive1.0
22ndead1.0
23ndead1.0
24ndead1.0
25ydead1.0
26ndead1.0
27ndead1.0
28yalive1.0
29yalive1.0
............
70ndead1.0
71nalive1.0
72nalive1.0
73ndead1.0
74nalive1.0
75ndead1.0
76yalive1.0
77ydead1.0
78ndead1.0
79ndead1.0
80ndead1.0
81nalive1.0
82ydead1.0
83ydead1.0
84ydead1.0
85yalive1.0
86ndead1.0
87ndead1.0
88nalive1.0
89nalive1.0
90yalive1.0
91yalive1.0
92ydead1.0
93ndead1.0
94ydead1.0
95ndead1.0
96nalive1.0
97nalive1.0
98ydead1.0
99ydead1.0
\n", "

100 rows × 3 columns

\n", "
" ], "text/plain": [ " smoker status val\n", "0 y alive 1.0\n", "1 n dead 1.0\n", "2 n alive 1.0\n", "3 y dead 1.0\n", "4 y alive 1.0\n", "5 y alive 1.0\n", "6 y dead 1.0\n", "7 n alive 1.0\n", "8 y alive 1.0\n", "9 y alive 1.0\n", "10 y alive 1.0\n", "11 y dead 1.0\n", "12 y dead 1.0\n", "13 n dead 1.0\n", "14 n dead 1.0\n", "15 n alive 1.0\n", "16 y dead 1.0\n", "17 y dead 1.0\n", "18 y alive 1.0\n", "19 y dead 1.0\n", "20 n dead 1.0\n", "21 n alive 1.0\n", "22 n dead 1.0\n", "23 n dead 1.0\n", "24 n dead 1.0\n", "25 y dead 1.0\n", "26 n dead 1.0\n", "27 n dead 1.0\n", "28 y alive 1.0\n", "29 y alive 1.0\n", ".. ... ... ...\n", "70 n dead 1.0\n", "71 n alive 1.0\n", "72 n alive 1.0\n", "73 n dead 1.0\n", "74 n alive 1.0\n", "75 n dead 1.0\n", "76 y alive 1.0\n", "77 y dead 1.0\n", "78 n dead 1.0\n", "79 n dead 1.0\n", "80 n dead 1.0\n", "81 n alive 1.0\n", "82 y dead 1.0\n", "83 y dead 1.0\n", "84 y dead 1.0\n", "85 y alive 1.0\n", "86 n dead 1.0\n", "87 n dead 1.0\n", "88 n alive 1.0\n", "89 n alive 1.0\n", "90 y alive 1.0\n", "91 y alive 1.0\n", "92 y dead 1.0\n", "93 n dead 1.0\n", "94 y dead 1.0\n", "95 n dead 1.0\n", "96 n alive 1.0\n", "97 n alive 1.0\n", "98 y dead 1.0\n", "99 y dead 1.0\n", "\n", "[100 rows x 3 columns]" ] }, "execution_count": 108, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Merge joins on a column or columns \n", "\n", "If `on` argument not specified, merge on all columns with same name." ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidxy
01011040
11022050
21033060
\n", "
" ], "text/plain": [ " pid x y\n", "0 101 10 40\n", "1 102 20 50\n", "2 103 30 60" ] }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df3)" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidxy
01011070
11033080
\n", "
" ], "text/plain": [ " pid x y\n", "0 101 10 70\n", "1 103 30 80" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df4, on='pid', how='inner')" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidxy
01011070.0
110220NaN
21033080.0
\n", "
" ], "text/plain": [ " pid x y\n", "0 101 10 70.0\n", "1 102 20 NaN\n", "2 103 30 80.0" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df4, on='pid', how='left')" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidxy
010110.070
110330.080
2105NaN90
\n", "
" ], "text/plain": [ " pid x y\n", "0 101 10.0 70\n", "1 103 30.0 80\n", "2 105 NaN 90" ] }, "execution_count": 112, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df4, on='pid', how='right')" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidxy
010110.070.0
110220.0NaN
210330.080.0
3105NaN90.0
\n", "
" ], "text/plain": [ " pid x y\n", "0 101 10.0 70.0\n", "1 102 20.0 NaN\n", "2 103 30.0 80.0\n", "3 105 NaN 90.0" ] }, "execution_count": 113, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df4, on='pid', how='outer')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Joining on common index" ] }, { "cell_type": "code", "execution_count": 114, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df1.set_index('pid', inplace=True)\n", "df4.set_index('pid', inplace=True)\n", "df5.set_index('pid', inplace=True)" ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
x
pid
10110
10220
10330
\n", "
" ], "text/plain": [ " x\n", "pid \n", "101 10\n", "102 20\n", "103 30" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1" ] }, { "cell_type": "code", "execution_count": 116, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
y
pid
10170
10380
10590
\n", "
" ], "text/plain": [ " y\n", "pid \n", "101 70\n", "103 80\n", "105 90" ] }, "execution_count": 116, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df4" ] }, { "cell_type": "code", "execution_count": 117, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
z
pid
10140
10250
10360
\n", "
" ], "text/plain": [ " z\n", "pid \n", "101 40\n", "102 50\n", "103 60" ] }, "execution_count": 117, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the data frames share a common index, `join` can combine mulitple data frames at once." ] }, { "cell_type": "code", "execution_count": 118, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
xyz
pid
10110.070.040.0
10220.0NaN50.0
10330.080.060.0
105NaN90.0NaN
\n", "
" ], "text/plain": [ " x y z\n", "pid \n", "101 10.0 70.0 40.0\n", "102 20.0 NaN 50.0\n", "103 30.0 80.0 60.0\n", "105 NaN 90.0 NaN" ] }, "execution_count": 118, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.join([df4, df5], how='outer')" ] } ], "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.1" } }, "nbformat": 4, "nbformat_minor": 2 }