diff --git a/3_variables_are_stored_in_both_rows_and_columns.ipynb b/3_variables_are_stored_in_both_rows_and_columns.ipynb new file mode 100644 index 0000000..7d0f2f5 --- /dev/null +++ b/3_variables_are_stored_in_both_rows_and_columns.ipynb @@ -0,0 +1,994 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Variables are stored in both Rows and Columns" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## \"Housekeeping\"" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2018-08-26 12:56:31 CEST\n", + "\n", + "CPython 3.6.5\n", + "IPython 6.5.0\n", + "\n", + "numpy 1.15.1\n", + "pandas 0.23.4\n" + ] + } + ], + "source": [ + "% load_ext watermark\n", + "% watermark -d -t -v -z -p numpy,pandas" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "pd.set_option('display.max_columns', 40)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example: Weather\n", + "\n", + "The [Global Historical Climatology Network](https://www.ncdc.noaa.gov/data-access/land-based-station-data/land-based-datasets/global-historical-climatology-network-ghcn) collects daily weather. For this example, data for one weather station (MX17004) in Mexico are used." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load the Data\n", + "\n", + "The raw dataset comes in a format that is a mixture of a fixed-width style with occasional usage of characters as seperators. Some tedious cleaning work is necessary." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# Extract the data as one column and\n", + "# use string slicing to obtain groups of columns.\n", + "weather = pd.read_csv('data/weather.txt', header=None, sep='^')\n", + "\n", + "# First, remove the weird character seperators,\n", + "# then split the columns by whitespace, and\n", + "# finally name them appropriately.\n", + "days = (\n", + " weather[0]\n", + " .map(lambda x: x[21:]).str.replace('OI', ' ')\n", + " .str.replace('OS', ' ').str.replace('SI', ' ').str.replace('I', ' ')\n", + " .str.replace('S', ' ').str.replace('B', ' ').str.replace('D', ' ')\n", + " .map(str.lstrip).str.split(r'\\s+', expand=True)\n", + ")[list(range(31))].rename(columns={i: f'd{i+1}' for i in range(31)})\n", + "\n", + "# The non-temperature columns can be extracted as simple slices.\n", + "weather = pd.DataFrame(data={\n", + " 'id': weather[0].map(lambda x: x[:11]),\n", + " 'year': weather[0].map(lambda x: x[11:15]).astype(int),\n", + " 'month': weather[0].map(lambda x: x[15:17]).astype(int),\n", + " 'element': weather[0].map(lambda x: x[17:21]).str.lower(),\n", + "})\n", + "\n", + "# The temperatures were stored as whole integers\n", + "# with -9999 indicating missing values.\n", + "for i in range(1, 32):\n", + " weather[f'd{i}'] = days[f'd{i}'].astype(float) / 10\n", + "weather = weather.replace(-999.9, np.NaN)\n", + "\n", + "# Discard the non-temperature observations and\n", + "# sort the dataset as in the paper.\n", + "weather = (\n", + " weather[weather['element'].isin(['tmax', 'tmin'])]\n", + " .sort_values(['id', 'year', 'month', 'element'])\n", + " .reset_index(drop=True)\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Messy Data\n", + "\n", + "Below is a dataset assumed to have been provided like this as \"raw\", i.e., the data analyst did not do the above parsing work but some third party instead.\n", + "\n", + "> The most complicated form of messy data occurs when variables are stored in both rows and columns. Table 11 shows daily weather data from the Global Historical Climatology Network for one weather station (MX17004) in Mexico for five months in 2010. It has variables in\n", + "individual columns (*id*, *year*, *month*), spread across columns (day, d1–d31) and across rows (*tmin*, *tmax*) (minimum and maximum temperature). Months with less than 31 days have\n", + "structural missing values for the last day(s) of the month. The *element* column is not a variable; it stores the names of variables." + ] + }, + { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idyearmonthelementd1d2d3d4d5d6d7d8d9d10d11d12d13d14d15d16d17d18d19d20d21d22d23d24d25d26d27d28d29d30d31
1099MX00001700420101tmaxNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN27.8NaN
1100MX00001700420101tminNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN14.5NaN
1101MX00001700420102tmaxNaN27.324.1NaNNaNNaNNaNNaNNaNNaN29.7NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN29.9NaNNaNNaNNaNNaNNaNNaNNaN
1102MX00001700420102tminNaN14.414.4NaNNaNNaNNaNNaNNaNNaN13.4NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN10.7NaNNaNNaNNaNNaNNaNNaNNaN
1103MX00001700420103tmaxNaNNaNNaNNaN32.1NaNNaNNaNNaN34.5NaNNaNNaNNaNNaN31.1NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
1104MX00001700420103tminNaNNaNNaNNaN14.2NaNNaNNaNNaN16.8NaNNaNNaNNaNNaN17.6NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
1105MX00001700420104tmaxNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN36.3NaNNaNNaNNaN
1106MX00001700420104tminNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN16.7NaNNaNNaNNaN
1107MX00001700420105tmaxNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN33.2NaNNaNNaNNaN
1108MX00001700420105tminNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN18.2NaNNaNNaNNaN
\n", + "
" + ], + "text/plain": [ + " id year month element d1 d2 d3 d4 d5 d6 d7 d8 \\\n", + "1099 MX000017004 2010 1 tmax NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1100 MX000017004 2010 1 tmin NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1101 MX000017004 2010 2 tmax NaN 27.3 24.1 NaN NaN NaN NaN NaN \n", + "1102 MX000017004 2010 2 tmin NaN 14.4 14.4 NaN NaN NaN NaN NaN \n", + "1103 MX000017004 2010 3 tmax NaN NaN NaN NaN 32.1 NaN NaN NaN \n", + "1104 MX000017004 2010 3 tmin NaN NaN NaN NaN 14.2 NaN NaN NaN \n", + "1105 MX000017004 2010 4 tmax NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1106 MX000017004 2010 4 tmin NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1107 MX000017004 2010 5 tmax NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1108 MX000017004 2010 5 tmin NaN NaN NaN NaN NaN NaN NaN NaN \n", + "\n", + " d9 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 \\\n", + "1099 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1100 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1101 NaN NaN 29.7 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1102 NaN NaN 13.4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1103 NaN 34.5 NaN NaN NaN NaN NaN 31.1 NaN NaN NaN NaN NaN NaN \n", + "1104 NaN 16.8 NaN NaN NaN NaN NaN 17.6 NaN NaN NaN NaN NaN NaN \n", + "1105 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1106 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1107 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1108 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "\n", + " d23 d24 d25 d26 d27 d28 d29 d30 d31 \n", + "1099 NaN NaN NaN NaN NaN NaN NaN 27.8 NaN \n", + "1100 NaN NaN NaN NaN NaN NaN NaN 14.5 NaN \n", + "1101 29.9 NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1102 10.7 NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1103 NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1104 NaN NaN NaN NaN NaN NaN NaN NaN NaN \n", + "1105 NaN NaN NaN NaN 36.3 NaN NaN NaN NaN \n", + "1106 NaN NaN NaN NaN 16.7 NaN NaN NaN NaN \n", + "1107 NaN NaN NaN NaN 33.2 NaN NaN NaN NaN \n", + "1108 NaN NaN NaN NaN 18.2 NaN NaN NaN NaN " + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "weather[(weather['year'] == 2010)].head(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Molten Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> To tidy this dataset we first melt it with colvars *id*, *year*, *month* and the column that contains variable names, *element* [...]. For presentation, we have dropped the missing values, making them implicit rather than explicit. This is permissible because we know how many days are in each month and can easily reconstruct the explicit missing values." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# Melt the dataset and extract a date column.\n", + "molten_weather = (\n", + " pd.melt(weather, id_vars=['id', 'year', 'month', 'element'], var_name='day')\n", + " .assign(day=lambda x: x['day'].str.extract('(\\d+)').astype(int))\n", + " .assign(date=lambda x: pd.to_datetime(x[['year', 'month', 'day']], errors='coerce'))\n", + ")[['id', 'date', 'element', 'value']]\n", + "\n", + "# Make the missing values implicit.\n", + "molten_weather = molten_weather[molten_weather['value'].notnull()]\n", + "\n", + "# Sort the data as in the paper.\n", + "molten_weather = (\n", + " molten_weather\n", + " .sort_values(['id', 'date', 'element'])\n", + " .reset_index(drop=True)\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> This dataset is mostly tidy, but we have two variables stored in rows: *tmin* and *tmax*, the type of observation." + ] + }, + { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
iddateelementvalue
23183MX0000170042010-01-30tmax27.8
23184MX0000170042010-01-30tmin14.5
23185MX0000170042010-02-02tmax27.3
23186MX0000170042010-02-02tmin14.4
23187MX0000170042010-02-03tmax24.1
23188MX0000170042010-02-03tmin14.4
23189MX0000170042010-02-11tmax29.7
23190MX0000170042010-02-11tmin13.4
23191MX0000170042010-02-23tmax29.9
23192MX0000170042010-02-23tmin10.7
\n", + "
" + ], + "text/plain": [ + " id date element value\n", + "23183 MX000017004 2010-01-30 tmax 27.8\n", + "23184 MX000017004 2010-01-30 tmin 14.5\n", + "23185 MX000017004 2010-02-02 tmax 27.3\n", + "23186 MX000017004 2010-02-02 tmin 14.4\n", + "23187 MX000017004 2010-02-03 tmax 24.1\n", + "23188 MX000017004 2010-02-03 tmin 14.4\n", + "23189 MX000017004 2010-02-11 tmax 29.7\n", + "23190 MX000017004 2010-02-11 tmin 13.4\n", + "23191 MX000017004 2010-02-23 tmax 29.9\n", + "23192 MX000017004 2010-02-23 tmin 10.7" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "molten_weather[(molten_weather['date'].dt.year == 2010)].head(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tidy Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> Fixing this requires the cast, or unstack, operation. This performs the inverse of melting by rotating the element variable back out into the columns\n", + "\n", + "Note that [pd.DataFrame.unstack](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.unstack.html) method uses a DataFrame's index as columns to unstack over." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "tidy_weather = molten_weather.set_index(['id', 'date', 'element']).unstack()\n", + "\n", + "# Make the column headers look as in the paper.\n", + "tidy_weather.columns = tidy_weather.columns.droplevel(0)\n", + "tidy_weather.columns.name = None\n", + "tidy_weather = tidy_weather.reset_index()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> This form is tidy. There is one variable in each column, and each row represents a day’s observations." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "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", + "
iddatetmaxtmin
12087MX0000170042010-01-3027.814.5
12088MX0000170042010-02-0227.314.4
12089MX0000170042010-02-0324.114.4
12090MX0000170042010-02-1129.713.4
12091MX0000170042010-02-2329.910.7
12092MX0000170042010-03-0532.114.2
12093MX0000170042010-03-1034.516.8
12094MX0000170042010-03-1631.117.6
12095MX0000170042010-04-2736.316.7
12096MX0000170042010-05-2733.218.2
\n", + "
" + ], + "text/plain": [ + " id date tmax tmin\n", + "12087 MX000017004 2010-01-30 27.8 14.5\n", + "12088 MX000017004 2010-02-02 27.3 14.4\n", + "12089 MX000017004 2010-02-03 24.1 14.4\n", + "12090 MX000017004 2010-02-11 29.7 13.4\n", + "12091 MX000017004 2010-02-23 29.9 10.7\n", + "12092 MX000017004 2010-03-05 32.1 14.2\n", + "12093 MX000017004 2010-03-10 34.5 16.8\n", + "12094 MX000017004 2010-03-16 31.1 17.6\n", + "12095 MX000017004 2010-04-27 36.3 16.7\n", + "12096 MX000017004 2010-05-27 33.2 18.2" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tidy_weather[(tidy_weather['date'].dt.year == 2010)].head(10)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}