diff --git a/clustering/Compute_clusters_hourly.ipynb b/clustering/Compute_clusters_hourly.ipynb index 65c6005..8da6dd2 100644 --- a/clustering/Compute_clusters_hourly.ipynb +++ b/clustering/Compute_clusters_hourly.ipynb @@ -1,1393 +1,3199 @@ { "cells": [ { "cell_type": "code", - "execution_count": 21, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/walch/.local/lib/python3.6/site-packages/dask/config.py:129: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.\n", + " data = yaml.load(f.read()) or {}\n", + "/home/walch/.local/lib/python3.6/site-packages/distributed/config.py:20: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.\n", + " defaults = yaml.load(f)\n" + ] + } + ], "source": [ "import pandas as pd\n", "import xarray as xr\n", "import numpy as np\n", "\n", "import os\n", "import time\n", "\n", - "from demand_mapping import *" + "from demand_mapping import *\n", + "\n", + "%matplotlib notebook\n", + "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "scratch_fp = '/scratch/walch/cluster_hubs'" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "CANTON = 'GE'\n", "cluster_data = pd.read_csv(os.path.join(scratch_fp, '%s_BLD_data_w_clusters.csv' %CANTON), index_col = 0)\n", "PV_data = pd.read_csv(os.path.join(scratch_fp, '%s_roofs_PV.csv' %CANTON))\n", "GWR_data = pd.read_csv(os.path.join(scratch_fp, '%s_GWR_demand.csv' %CANTON))" ] }, { "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BLD_IDxypeak_demand_Wannual_demand_kWhpv_potential_kWh_aavailable_areaclusterID
0150000000.02.499220e+061.110868e+06966.4583323698.6196533554.808018.3299150
1150000001.02.499198e+061.110882e+06966.4583323698.6196533418.227317.4021330
2150000002.02.499252e+061.110894e+06966.4583323698.6196531985.994810.1317360
5150000005.02.499174e+061.110957e+06966.4583323698.61965328279.8473185.5652020
7150000007.02.492126e+061.111043e+061340.9067065633.7475737649.999543.7668741
\n", "
" ], "text/plain": [ " BLD_ID x y peak_demand_W annual_demand_kWh \\\n", "0 150000000.0 2.499220e+06 1.110868e+06 966.458332 3698.619653 \n", "1 150000001.0 2.499198e+06 1.110882e+06 966.458332 3698.619653 \n", "2 150000002.0 2.499252e+06 1.110894e+06 966.458332 3698.619653 \n", "5 150000005.0 2.499174e+06 1.110957e+06 966.458332 3698.619653 \n", "7 150000007.0 2.492126e+06 1.111043e+06 1340.906706 5633.747573 \n", "\n", " pv_potential_kWh_a available_area clusterID \n", "0 3554.8080 18.329915 0 \n", "1 3418.2273 17.402133 0 \n", "2 1985.9948 10.131736 0 \n", "5 28279.8473 185.565202 0 \n", "7 7649.9995 43.766874 1 " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cluster_data.head()" ] }, { "cell_type": "code", - "execution_count": 114, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "clusterID\n", " 471 0.000000e+00\n", " 86 1.985401e+04\n", " 827 2.797131e+04\n", " 91 2.869968e+04\n", " 81 2.884662e+04\n", " ... \n", " 58 3.550708e+06\n", " 646 3.913752e+06\n", " 316 4.723911e+06\n", " 713 4.881039e+06\n", "-1 3.250961e+07\n", "Name: pv_potential_kWh_a, Length: 714, dtype: float64" ] }, - "execution_count": 114, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cluster_data.groupby('clusterID').sum().pv_potential_kWh_a.sort_values()" ] }, { "cell_type": "code", - "execution_count": 5, + "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
DF_UIDpv_potential_kWh_apv_potential_kWh_a_stdradiation_kWh_m2_aradiation_kWh_m2_a_stdavailable_areaFLAECHENEIGUNGAUSRICHTUNGBLD_IDsuitable
048174104655.67241927.682388915.779135217.17667037.00266371.48704710127.0310012102.01
148174250.0000576.9770691297.643387315.5971510.00000036.8598363733.0310012087.00
248174260.0000672.6058981361.228740333.0069560.00000051.33386431-57.0310012087.00
348174270.0000292.359850704.052711150.1581880.00000036.86144737-147.0310012087.00
448174280.00001711.567742810.469179186.4092770.00000081.25655528123.0310012087.00
\n", "
" ], "text/plain": [ " DF_UID pv_potential_kWh_a pv_potential_kWh_a_std radiation_kWh_m2_a \\\n", "0 4817410 4655.6724 1927.682388 915.779135 \n", "1 4817425 0.0000 576.977069 1297.643387 \n", "2 4817426 0.0000 672.605898 1361.228740 \n", "3 4817427 0.0000 292.359850 704.052711 \n", "4 4817428 0.0000 1711.567742 810.469179 \n", "\n", " radiation_kWh_m2_a_std available_area FLAECHE NEIGUNG AUSRICHTUNG \\\n", "0 217.176670 37.002663 71.487047 10 127.0 \n", "1 315.597151 0.000000 36.859836 37 33.0 \n", "2 333.006956 0.000000 51.333864 31 -57.0 \n", "3 150.158188 0.000000 36.861447 37 -147.0 \n", "4 186.409277 0.000000 81.256555 28 123.0 \n", "\n", " BLD_ID suitable \n", "0 310012102.0 1 \n", "1 310012087.0 0 \n", "2 310012087.0 0 \n", "3 310012087.0 0 \n", "4 310012087.0 0 " ] }, - "execution_count": 5, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "PV_data.head()" ] }, { "cell_type": "code", - "execution_count": 6, + "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", " \n", "
EGIDGKODEGKODNGKATGKLASBLD_IDN_DWL_RESSER_AREApeak_demand_Wannual_demand_kWh
016314572492426.751115937.501020.01110.0150013089.01.0NaN966.4583323698.619653
116314582492420.001115924.631020.01110.0150013089.01.0NaN966.4583323698.619653
216314592492413.001115911.691020.01110.0150013089.01.0NaN966.4583323698.619653
316314602492393.251115932.311020.01110.0150001743.01.0NaN966.4583323698.619653
416314612492389.501115918.881020.01110.0150001743.01.0NaN966.4583323698.619653
\n", "
" ], "text/plain": [ " EGID GKODE GKODN GKAT GKLAS BLD_ID N_DWL_RES \\\n", "0 1631457 2492426.75 1115937.50 1020.0 1110.0 150013089.0 1.0 \n", "1 1631458 2492420.00 1115924.63 1020.0 1110.0 150013089.0 1.0 \n", "2 1631459 2492413.00 1115911.69 1020.0 1110.0 150013089.0 1.0 \n", "3 1631460 2492393.25 1115932.31 1020.0 1110.0 150001743.0 1.0 \n", "4 1631461 2492389.50 1115918.88 1020.0 1110.0 150001743.0 1.0 \n", "\n", " SER_AREA peak_demand_W annual_demand_kWh \n", "0 NaN 966.458332 3698.619653 \n", "1 NaN 966.458332 3698.619653 \n", "2 NaN 966.458332 3698.619653 \n", "3 NaN 966.458332 3698.619653 \n", "4 NaN 966.458332 3698.619653 " ] }, - "execution_count": 6, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "GWR_data.head()" ] }, { "cell_type": "code", - "execution_count": 116, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "count 714.000000\n", "mean 35.500000\n", "std 44.372839\n", "min 1.000000\n", "25% 6.000000\n", "50% 16.000000\n", "75% 52.750000\n", "max 433.000000\n", "Name: BLD_ID, dtype: float64" ] }, - "execution_count": 116, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cluster_data.groupby('clusterID').BLD_ID.count().describe()" ] }, { "cell_type": "code", - "execution_count": 119, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "cluster_count = cluster_data.groupby('clusterID').BLD_ID.count()\n", "clusters = cluster_data.groupby('clusterID').sum()" ] }, { "cell_type": "code", - "execution_count": 136, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "clusterID\n", "19 False\n", "69 False\n", "92 False\n", "429 False\n", "454 True\n", "487 False\n", "503 False\n", "539 False\n", "558 False\n", "614 False\n", "660 False\n", "694 False\n", "842 False\n", "Name: annual_demand_kWh, dtype: bool" ] }, - "execution_count": 136, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "clusters[cluster_count == 16].annual_demand_kWh == clusters[cluster_count == 16].annual_demand_kWh.median()" ] }, { "cell_type": "code", - "execution_count": 137, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "clusterID\n", "86 6\n", "454 16\n", "309 52\n", "Name: BLD_ID, dtype: int64" ] }, - "execution_count": 137, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cluster_count.loc[[86,454,309]]" ] }, { "cell_type": "code", - "execution_count": 138, + "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
BLD_IDxypeak_demand_Wannual_demand_kWhpv_potential_kWh_aavailable_area
clusterID
924.960153e+094.007723e+071.814913e+0717178.6883926.674679e+04128803.6169770.136534861.800005e+091.499959e+076.752649e+065798.7499922.219172e+041.985401e+04131.287635
4542.560131e+094.000629e+071.787293e+07445807.0194352.493338e+06577026.50395.770265e+053291.527139
4101.579191e+102.146994e+089.605129e+07145282.5233765.590065e+05692458.95354207.6193633097.800609e+091.298831e+085.813734e+07956085.9416454.219583e+061.313736e+067644.651790
\n", "
" ], "text/plain": [ " BLD_ID x y peak_demand_W \\\n", "clusterID \n", - "92 4.960153e+09 4.007723e+07 1.814913e+07 17178.688392 \n", + "86 1.800005e+09 1.499959e+07 6.752649e+06 5798.749992 \n", "454 2.560131e+09 4.000629e+07 1.787293e+07 445807.019435 \n", - "410 1.579191e+10 2.146994e+08 9.605129e+07 145282.523376 \n", + "309 7.800609e+09 1.298831e+08 5.813734e+07 956085.941645 \n", "\n", " annual_demand_kWh pv_potential_kWh_a available_area \n", "clusterID \n", - "92 6.674679e+04 128803.6169 770.136534 \n", - "454 2.493338e+06 577026.5039 3291.527139 \n", - "410 5.590065e+05 692458.9535 4207.619363 " + "86 2.219172e+04 1.985401e+04 131.287635 \n", + "454 2.493338e+06 5.770265e+05 3291.527139 \n", + "309 4.219583e+06 1.313736e+06 7644.651790 " ] }, - "execution_count": 138, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "clusters.loc[[92,454,410]]" + "clusters.loc[[86,454,309]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Select demand" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Residential sector" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "demand_fp = '/work/hyenergy/output/demand' #\n", "residential_demand = xr.open_dataset(os.path.join(demand_fp, 'electricity_demand_residential.nc')) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Service sector" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "demand_fp = '/work/hyenergy/output/demand' # \n", "service_demand = xr.open_dataset(os.path.join(demand_fp, 'electricity_demand_services.nc')) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Mapping" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "GWR_clusters = GWR_data.merge(cluster_data[['BLD_ID', 'clusterID']], on = 'BLD_ID', how = 'inner')" ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "RES = GWR_clusters[GWR_clusters.N_DWL_RES > 0]\n", "SER = GWR_clusters[np.logical_not(GWR_clusters.SER_AREA.isna())]" ] }, { "cell_type": "code", - "execution_count": 146, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "SER_demand, SER_services = get_cluster_demand_SER(SER, service_demand, grouping_col = 'clusterID')\n", "\n", "RES_demand, N_units = get_cluster_demand_RES( RES.reset_index(), residential_demand, grouping_col = 'clusterID', \n", " dwell_nb = 'N_DWL_RES' )\n", "\n", "hourly_profiles = xr.merge([RES_demand.rename('residential_W'), SER_demand.rename('service_W')]).fillna(0) \n", "hourly_profiles['both_W'] = hourly_profiles.residential_W + hourly_profiles.service_W" ] }, { "cell_type": "code", - "execution_count": 147, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ - "for cluster in [86]: # , 309, 454]: # GWR_clusters.clusterID.unique():\n", + "for cluster in [86, 309, 454]: # GWR_clusters.clusterID.unique():\n", " demand_df = hourly_profiles.sel(daytype = 'weekday', clusterID = cluster).squeeze().to_dataframe()[['both_W']]\n", " \n", " demand_df['month'] = pd.to_datetime(demand_df.index).month\n", " demand_df['hour' ] = pd.to_datetime(demand_df.index).hour\n", " \n", " demand_out = pd.concat([demand_df.iloc[:,-2:], demand_df.iloc[:,:-2]], axis = 1).set_index(['month','hour'])\n", " demand_out = demand_out.rename({'both_W' : 'demand_W'}, axis = 1)\n", " \n", " demand_out.to_csv(os.path.join(scratch_fp, 'cluster_demand_%d.csv' %cluster))" ] }, { "cell_type": "code", - "execution_count": 148, + "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", "
demand_W
monthhour
101789.4202791.869937e+06
11566.9565141.830241e+06
21512.0289781.787251e+06
31470.2898481.855713e+06
41528.8405672.042774e+06
.........
12194952.1739202.519858e+06
203971.4492712.373494e+06
213507.1014442.152071e+06
222777.6811632.054749e+06
232264.9275232.063211e+06
\n", "

288 rows × 1 columns

\n", "
" ], "text/plain": [ - " demand_W\n", - "month hour \n", - "1 0 1789.420279\n", - " 1 1566.956514\n", - " 2 1512.028978\n", - " 3 1470.289848\n", - " 4 1528.840567\n", - "... ...\n", - "12 19 4952.173920\n", - " 20 3971.449271\n", - " 21 3507.101444\n", - " 22 2777.681163\n", - " 23 2264.927523\n", + " demand_W\n", + "month hour \n", + "1 0 1.869937e+06\n", + " 1 1.830241e+06\n", + " 2 1.787251e+06\n", + " 3 1.855713e+06\n", + " 4 2.042774e+06\n", + "... ...\n", + "12 19 2.519858e+06\n", + " 20 2.373494e+06\n", + " 21 2.152071e+06\n", + " 22 2.054749e+06\n", + " 23 2.063211e+06\n", "\n", "[288 rows x 1 columns]" ] }, - "execution_count": 148, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "demand_out" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Map PV potential" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "PV_fp = '/work/hyenergy/output/solar_potential/technical_potential'\n", "PV_hourly = xr.open_dataset(os.path.join(PV_fp, 'pv_potential_hourly_shared_v2.nc'))" ] }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "PV_clusters = PV_data.merge(cluster_data[['BLD_ID', 'clusterID']], on = 'BLD_ID', how = 'inner')" ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "PV_hourly_select = PV_hourly.sel(DF_UID = PV_clusters.DF_UID.values)" ] }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "def aspect_bin(x):\n", " if abs(x.AUSRICHTUNG) < 22.5: return 0\n", " elif abs(x.AUSRICHTUNG - 45) < 22.5: return 1\n", " elif abs(x.AUSRICHTUNG - 90) < 22.5: return 2\n", " elif abs(x.AUSRICHTUNG + 45) < 22.5: return 3\n", " elif abs(x.AUSRICHTUNG + 90) < 22.5: return 4\n", " else: return 5\n", "\n", "def get_bin(x):\n", " if x.NEIGUNG == 0: return 0\n", " elif x.NEIGUNG <= 10: return 1\n", " elif x.NEIGUNG <= 30: return 2 + aspect_bin(x)\n", - " elif x.NEIGUNG <= 60: return 7 + aspect_bin(x)\n", - " else: return 12 + aspect_bin(x)" + " elif x.NEIGUNG <= 60: return 8 + aspect_bin(x)\n", + " else: return 14 + aspect_bin(x)" ] }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "PV_clusters['bin'] = PV_clusters.apply(get_bin, axis = 1)" ] }, { "cell_type": "code", - "execution_count": 92, + "execution_count": 25, + "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", + "
DF_UIDpv_potential_kWh_apv_potential_kWh_a_stdradiation_kWh_m2_aradiation_kWh_m2_a_stdavailable_areaFLAECHENEIGUNGAUSRICHTUNGBLD_IDsuitableclusterIDbin
048174104655.67241927.682388915.779135217.17667037.00266371.48704710127.0310012102.01931
148174250.0000576.9770691297.643387315.5971510.00000036.8598363733.0310012087.00939
248174260.0000672.6058981361.228740333.0069560.00000051.33386431-57.0310012087.009311
348174270.0000292.359850704.052711150.1581880.00000036.86144737-147.0310012087.009313
448174280.00001711.567742810.469179186.4092770.00000081.25655528123.0310012087.00937
\n", + "
" + ], + "text/plain": [ + " DF_UID pv_potential_kWh_a pv_potential_kWh_a_std radiation_kWh_m2_a \\\n", + "0 4817410 4655.6724 1927.682388 915.779135 \n", + "1 4817425 0.0000 576.977069 1297.643387 \n", + "2 4817426 0.0000 672.605898 1361.228740 \n", + "3 4817427 0.0000 292.359850 704.052711 \n", + "4 4817428 0.0000 1711.567742 810.469179 \n", + "\n", + " radiation_kWh_m2_a_std available_area FLAECHE NEIGUNG AUSRICHTUNG \\\n", + "0 217.176670 37.002663 71.487047 10 127.0 \n", + "1 315.597151 0.000000 36.859836 37 33.0 \n", + "2 333.006956 0.000000 51.333864 31 -57.0 \n", + "3 150.158188 0.000000 36.861447 37 -147.0 \n", + "4 186.409277 0.000000 81.256555 28 123.0 \n", + "\n", + " BLD_ID suitable clusterID bin \n", + "0 310012102.0 1 93 1 \n", + "1 310012087.0 0 93 9 \n", + "2 310012087.0 0 93 11 \n", + "3 310012087.0 0 93 13 \n", + "4 310012087.0 0 93 7 " + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "PV_clusters.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "PV_frame = pd.DataFrame(index = range(288), columns = range(20)).fillna(0)\n", "PV_frame['month'] = sum([24 * [m] for m in range(1,13)], [])\n", "PV_frame['hour' ] = 12 * list(range(24))\n", "PV_frame = pd.concat([PV_frame.iloc[:,-2:], PV_frame.iloc[:,:-2]], axis = 1).set_index(['month','hour'])" ] }, { "cell_type": "code", - "execution_count": 141, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "for cluster in [86, 309, 454]: # PV_clusters.clusterID.unique():\n", " clust = PV_clusters[PV_clusters.clusterID == cluster]\n", + " # Get available area\n", + " av_area_clust = pd.DataFrame(index = range(20))\n", + " av_area_clust.index.name = 'bin'\n", + " av_area_clust['available_area'] = clust.groupby('bin').available_area.sum()\n", + " \n", + " av_area_clust.fillna(0).to_csv(os.path.join(scratch_fp, 'cluster_PV_area_%d.csv' %cluster))\n", + " \n", + " # Get MMH PV\n", " PV_sel = PV_hourly_select.sel(DF_UID = clust.DF_UID.values)\n", " \n", " PV_df = PV_sel.pv_potential_W.to_pandas().reset_index()\n", " \n", " PV_df = PV_df.merge(PV_clusters[['DF_UID', 'bin']], \n", " on = 'DF_UID').drop(columns = ['DF_UID']).groupby('bin').sum().T\n", " \n", " PV_df['month'] = pd.to_datetime(PV_df.index).month\n", " PV_df['hour' ] = pd.to_datetime(PV_df.index).hour\n", " \n", " PV_out = pd.concat([PV_df.iloc[:,-2:], PV_df.iloc[:,:-2]], axis = 1).set_index(['month','hour'])\n", " PV_out = (PV_frame + PV_out).fillna(0)\n", " \n", " PV_out.to_csv(os.path.join(scratch_fp, 'cluster_potential_%d.csv' %cluster))" ] }, { "cell_type": "code", - "execution_count": 103, + "execution_count": 29, "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", "
012345678910111213141516171819
monthhour
100.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
10.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
20.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
30.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
40.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
..................................................................
12190.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
200.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
210.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
220.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
230.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
\n", "

288 rows × 20 columns

\n", "
" ], "text/plain": [ " 0 1 2 3 4 5 6 7 8 9 10 11 12 \\\n", "month hour \n", "1 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 2 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 3 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 4 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", "... ... ... ... ... ... ... ... ... ... ... ... ... ... \n", "12 19 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 20 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 21 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 22 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 23 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", "\n", " 13 14 15 16 17 18 19 \n", "month hour \n", "1 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 2 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 3 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 4 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", "... ... ... ... ... ... ... ... \n", "12 19 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 20 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 21 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 22 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", " 23 0.0 0.0 0.0 0.0 0.0 0.0 0.0 \n", "\n", "[288 rows x 20 columns]" ] }, - "execution_count": 103, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "PV_out" ] }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support. ' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " fig.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
');\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "PV_out.plot(figsize = (10,4), cmap = 'tab20')\n", + "plt.tight_layout()\n", + "plt.legend(ncol = 3)" + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "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.7" } }, "nbformat": 4, "nbformat_minor": 4 }