{ "cells": [ { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import geopandas as gpd\n", "\n", "import folium\n", "import branca" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### read input data" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | year | \n", "quarter | \n", "hour_of_day | \n", "segment_id | \n", "start_junction_id | \n", "end_junction_id | \n", "osm_way_id | \n", "osm_start_node_id | \n", "osm_end_node_id | \n", "speed_kph_mean | \n", "speed_kph_stddev | \n", "speed_kph_p50 | \n", "speed_kph_p85 | \n", "
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", "2019 | \n", "2 | \n", "0 | \n", "d0034ae2336f81ef5933a211f2ce2d979f0aff2a | \n", "66081f9fe2860af2a498e1248334cb51d6ea5073 | \n", "9c00a9375aeaba9c08f4f2fd507cc1808ba83b89 | \n", "9932085 | \n", "1236497729 | \n", "1236497752 | \n", "41.258 | \n", "9.239 | \n", "41.330 | \n", "46.680 | \n", "
1 | \n", "2019 | \n", "2 | \n", "23 | \n", "d0034ae2336f81ef5933a211f2ce2d979f0aff2a | \n", "66081f9fe2860af2a498e1248334cb51d6ea5073 | \n", "9c00a9375aeaba9c08f4f2fd507cc1808ba83b89 | \n", "9932085 | \n", "1236497729 | \n", "1236497752 | \n", "35.794 | \n", "6.706 | \n", "35.832 | \n", "41.398 | \n", "
2 | \n", "2019 | \n", "2 | \n", "22 | \n", "d0034ae2336f81ef5933a211f2ce2d979f0aff2a | \n", "66081f9fe2860af2a498e1248334cb51d6ea5073 | \n", "9c00a9375aeaba9c08f4f2fd507cc1808ba83b89 | \n", "9932085 | \n", "1236497729 | \n", "1236497752 | \n", "32.766 | \n", "13.401 | \n", "35.171 | \n", "43.469 | \n", "
3 | \n", "2019 | \n", "2 | \n", "23 | \n", "277640ca389fc7f0fc8a583386e6063df80485f0 | \n", "ad26106a25d52c3409bd0165f05de3047a4e96b5 | \n", "9c00a9375aeaba9c08f4f2fd507cc1808ba83b89 | \n", "9932085 | \n", "81398215 | \n", "1236497752 | \n", "34.507 | \n", "4.639 | \n", "35.207 | \n", "38.160 | \n", "
4 | \n", "2019 | \n", "2 | \n", "1 | \n", "277640ca389fc7f0fc8a583386e6063df80485f0 | \n", "ad26106a25d52c3409bd0165f05de3047a4e96b5 | \n", "9c00a9375aeaba9c08f4f2fd507cc1808ba83b89 | \n", "9932085 | \n", "81398215 | \n", "1236497752 | \n", "41.512 | \n", "6.049 | \n", "41.128 | \n", "47.681 | \n", "
\n", " | id | \n", "@id | \n", "cycleway:right | \n", "highway | \n", "lanes | \n", "lit | \n", "maxspeed | \n", "name | \n", "oneway | \n", "postal_code | \n", "... | \n", "after_construction:lanes | \n", "after_construction:parking:condition:right | \n", "after_construction:parking:lane:right | \n", "construction | \n", "construction:end_date | \n", "disused:cycleway:left | \n", "protected_bike_lane:right | \n", "cycleway:right:buffer | \n", "geometry | \n", "osm_way_id | \n", "
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | \n", "way/4045243 | \n", "way/4045243 | \n", "track | \n", "primary | \n", "3 | \n", "yes | \n", "50 | \n", "Frankfurter Allee | \n", "yes | \n", "10247 | \n", "... | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "LINESTRING (13.45421 52.51571, 13.45439 52.515... | \n", "4045243 | \n", "
1 | \n", "way/4045656 | \n", "way/4045656 | \n", "None | \n", "secondary | \n", "2 | \n", "None | \n", "50 | \n", "Hauptstraße | \n", "None | \n", "None | \n", "... | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "LINESTRING (13.37282 52.59334, 13.37281 52.593... | \n", "4045656 | \n", "
2 | \n", "way/4054013 | \n", "way/4054013 | \n", "track | \n", "primary | \n", "3 | \n", "yes | \n", "50 | \n", "Michael-Brückner-Straße | \n", "yes | \n", "12439 | \n", "... | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "LINESTRING (13.51476 52.45303, 13.51528 52.452... | \n", "4054013 | \n", "
3 | \n", "way/4067882 | \n", "way/4067882 | \n", "track | \n", "secondary | \n", "None | \n", "yes | \n", "50 | \n", "Olympische Straße | \n", "yes | \n", "14052 | \n", "... | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "LINESTRING (13.24937 52.51535, 13.24967 52.515... | \n", "4067882 | \n", "
4 | \n", "way/4067883 | \n", "way/4067883 | \n", "None | \n", "secondary | \n", "4 | \n", "yes | \n", "50 | \n", "Jafféstraße | \n", "None | \n", "14052 | \n", "... | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "None | \n", "LINESTRING (13.26152 52.50771, 13.26179 52.507... | \n", "4067883 | \n", "
5 rows × 431 columns
\n", "' syntax is deprecated. ':' is the preferred initialization method.\n",
" return _prepare_from_string(\" \".join(pjargs))\n"
]
}
],
"source": [
"#production\n",
"\n",
"for h in uber_data.hour_of_day.unique():\n",
"\n",
" #get ready\n",
" uber_data_h=uber_data[uber_data.hour_of_day==h].copy()\n",
" uber_data_h=uber_data_h.groupby('osm_way_id')['speed_kph_mean'].mean().reset_index().copy()\n",
"\n",
" #merge uber and osm\n",
" data_merg= pd.merge(osm_links[['geometry','osm_way_id','name','postal_code', 'maxspeed']],uber_data_h[['speed_kph_mean','osm_way_id']] )\n",
"\n",
" data_merg.maxspeed= data_merg.maxspeed.apply(lambda x: 50 if x=='DE:urban' else x)\n",
" data_merg.maxspeed=data_merg.maxspeed.astype(float)\n",
"\n",
"\n",
"\n",
"\n",
" #plot map\n",
" df=data_merg[(data_merg.speed_kph_mean<33) & (data_merg.maxspeed>=50) ]\n",
" field='speed_kph_mean'\n",
"\n",
" colorscale = branca.colormap.LinearColormap(['green','lightgreen','orange','red'], \n",
" index=[20,30,50,55], \n",
" vmin=0, \n",
" vmax=33, \n",
" caption='')\n",
"\n",
" def style_function(feature):\n",
" col=feature['properties'][field]\n",
" return {\n",
" #'fillOpacity': 0.5,\n",
" 'weight': 3,\n",
" 'color': 'grey' if col is None else colorscale(col)\n",
" }\n",
"\n",
" def highlight_function(feature):\n",
" return {\n",
" 'color': 'grey',\n",
" 'weight': 5,\n",
" 'dashArray': '5, 5'\n",
" }\n",
"\n",
" m = folium.Map(location=[52.5, 13.4],\n",
" tiles=\"cartodbpositron\",\n",
" name=\"CartoDB light\",\n",
" zoom_start=13)\n",
"\n",
" folium.GeoJson(\n",
" df,\n",
" name=str(h)+' Uhr',\n",
" style_function=style_function,\n",
" highlight_function=highlight_function,\n",
" tooltip=folium.GeoJsonTooltip(fields=['name','speed_kph_mean','maxspeed'],\n",
" aliases=['name','speed_kph_mean','maxspeed']),\n",
" ).add_to(m)\n",
"\n",
" \n",
" \n",
" folium.map.Marker(\n",
" #[34.0302, -118.2352],\n",
" [52.449463, 13.404811],\n",
" icon=DivIcon(\n",
" size=(150,36),\n",
" anchor=(150,0),\n",
" html=str(h)+' Uhr',\n",
" style=\"\"\"\n",
" font-size:36px;\n",
" background-color: transparent;\n",
" border-color: transparent;\n",
" text-align: right;\n",
" \"\"\"\n",
" )\n",
" ).add_to(m) \n",
" \n",
" \n",
" \n",
"\n",
" #m\n",
" folium.LayerControl(position='bottomright',collapsed=False).add_to(m)\n",
" \n",
" colorscale.caption = 'Speed'\n",
" m.add_child(colorscale)\n",
"\n",
" m.save(\"output/map_\"+str(h)+\".html\")\n",
" #m"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### create plot from htmls"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from selenium import webdriver #requires chromesdriver\n",
"from PIL import Image\n",
"import os"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [],
"source": [
"options = webdriver.ChromeOptions()\n",
"#options.add_argument('--headless')\n",
"driver = webdriver.Chrome(options=options)\n",
"\n",
"for h in uber_data.hour_of_day.unique():\n",
" driver.get(os.getcwd() + '\\\\output\\\\map_'+str(h)+'.html')\n",
" driver.save_screenshot('output\\\\map_'+str(h)+'.png')\n",
" \n",
" # newImg = Image.open('map_'+str(h)+'.png')\n",
" # newImg.save('map_'+str(h)+'_compressed.png', 'PNG', dpi=[200,200])\n",
"\n",
"driver.close()"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"#for h in uber_data.hour_of_day.unique():\n",
"# newImg = Image.open('map_'+str(h)+'.png')\n",
"# newImg = newImg.resize((400,400),Image.ANTIALIAS)\n",
"# newImg.save('map_'+str(h)+'_compressed_o.png', 'PNG', optimize=True, dpi=(300,300))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### produce gif from images, finally compress gif"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['output\\\\map_0.png',\n",
" 'output\\\\map_1.png',\n",
" 'output\\\\map_10.png',\n",
" 'output\\\\map_11.png',\n",
" 'output\\\\map_12.png',\n",
" 'output\\\\map_13.png',\n",
" 'output\\\\map_14.png',\n",
" 'output\\\\map_15.png',\n",
" 'output\\\\map_16.png',\n",
" 'output\\\\map_17.png',\n",
" 'output\\\\map_18.png',\n",
" 'output\\\\map_19.png',\n",
" 'output\\\\map_2.png',\n",
" 'output\\\\map_20.png',\n",
" 'output\\\\map_21.png',\n",
" 'output\\\\map_22.png',\n",
" 'output\\\\map_23.png',\n",
" 'output\\\\map_3.png',\n",
" 'output\\\\map_4.png',\n",
" 'output\\\\map_5.png',\n",
" 'output\\\\map_6.png',\n",
" 'output\\\\map_7.png',\n",
" 'output\\\\map_8.png',\n",
" 'output\\\\map_9.png']"
]
},
"execution_count": 64,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import glob\n",
"\n",
"filenames= glob.glob(\"output\\\\map*.png\")\n",
"filenames"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['output\\\\map_0.png', 'output\\\\map_1.png', 'output\\\\map_2.png', 'output\\\\map_3.png', 'output\\\\map_4.png', 'output\\\\map_5.png', 'output\\\\map_6.png', 'output\\\\map_7.png', 'output\\\\map_8.png', 'output\\\\map_9.png', 'output\\\\map_10.png', 'output\\\\map_11.png', 'output\\\\map_12.png', 'output\\\\map_13.png', 'output\\\\map_14.png', 'output\\\\map_15.png', 'output\\\\map_16.png', 'output\\\\map_17.png', 'output\\\\map_18.png', 'output\\\\map_19.png', 'output\\\\map_20.png', 'output\\\\map_21.png', 'output\\\\map_22.png', 'output\\\\map_23.png']\n"
]
}
],
"source": [
"# sort by hour\n",
"import re\n",
"\n",
"def atoi(text):\n",
" return int(text) if text.isdigit() else text\n",
"\n",
"def natural_keys(text):\n",
" '''\n",
" alist.sort(key=natural_keys) sorts in human order\n",
" http://nedbatchelder.com/blog/200712/human_sorting.html\n",
" (See Toothy's implementation in the comments)\n",
" '''\n",
" return [ atoi(c) for c in re.split(r'(\\d+)', text) ]\n",
"\n",
"\n",
"filenames.sort(key=natural_keys)\n",
"print(filenames)"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [],
"source": [
"import imageio\n",
"\n",
"images = []\n",
"for filename in filenames:\n",
" images.append(imageio.imread(filename))\n",
"imageio.mimsave('output\\\\uber_berlin2019Q2_50to30_24h.gif', images, format='GIF', duration=0.2)\n",
"#imageio.mimsave(exportname, frames, format='GIF', duration=5)"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#compress gif with gifsicle (install gifsicle first)\n",
"os.system(\"C:\\ProgramData\\gifsicle-1.92-win64\\gifsicle-1.92\\gifsicle.exe -O3 output\\\\uber_berlin2019Q2_50to30_24h.gif -o output\\\\uber_berlin2019Q2_50to30_24h.gif\")"
]
},
{
"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.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}