Skip to content

Instantly share code, notes, and snippets.

@jjsantos01
Last active April 5, 2024 01:40
Show Gist options
  • Save jjsantos01/c119eb434e8094583700b850f52ffb6e to your computer and use it in GitHub Desktop.
Save jjsantos01/c119eb434e8094583700b850f52ffb6e to your computer and use it in GitHub Desktop.
Todos los viajes que hice usando Ecobici (CDMX) en un año. Video de la animación: https://youtu.be/3fNVGx_wksk
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Python 3.6.10 |Anaconda, Inc.| (default, Jan 7 2020, 15:18:16) [MSC v.1916 64 bit (AMD64)]\n",
"matplotlib 3.2.1\n",
"geopandas 0.6.3\n",
"pandas 0.24.2\n",
"Using matplotlib backend: Qt5Agg\n"
]
}
],
"source": [
"import sys\n",
"\n",
"import matplotlib.animation as animation\n",
"import matplotlib.pyplot as plt\n",
"import geopandas as gpd\n",
"import pandas as pd\n",
"\n",
"print('Python', sys.version)\n",
"print(plt.matplotlib.__name__, plt.matplotlib.__version__)\n",
"print(gpd.__name__, gpd.__version__)\n",
"print(pd.__name__, pd.__version__)\n",
"\n",
"%matplotlib"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>fecha_de_inicio</th>\n",
" <th>fecha_fin</th>\n",
" <th>tiempo</th>\n",
" <th>estacion_inicio</th>\n",
" <th>estacion_fin</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>16/11/2020 16:43:07351 CALLE 27-AVENIDA REVOLU...</td>\n",
" <td>16/11/2020 16:48:50312 AVENIDA 2-CALLE 7</td>\n",
" <td>00:05:43</td>\n",
" <td>351</td>\n",
" <td>312</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>15/11/2020 06:47:56351 CALLE 27-AVENIDA REVOLU...</td>\n",
" <td>15/11/2020 07:01:3184 CHILPANCINGO-TLAXCALA</td>\n",
" <td>00:13:35</td>\n",
" <td>351</td>\n",
" <td>84</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>14/11/2020 15:58:1077 CHOAPAN-TAMAULIPAS</td>\n",
" <td>14/11/2020 16:19:10351 CALLE 27-AVENIDA REVOLU...</td>\n",
" <td>00:21:00</td>\n",
" <td>77</td>\n",
" <td>351</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>14/11/2020 13:47:17192 RUBEN DARIO-REFORMA</td>\n",
" <td>14/11/2020 14:14:1884 CHILPANCINGO-TLAXCALA</td>\n",
" <td>00:27:01</td>\n",
" <td>192</td>\n",
" <td>84</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>14/11/2020 11:21:49326 EUGENIA-NEBRASKA</td>\n",
" <td>14/11/2020 12:15:53218 HEGEL-IBARBOUROU</td>\n",
" <td>00:54:04</td>\n",
" <td>326</td>\n",
" <td>218</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" fecha_de_inicio \\\n",
"0 16/11/2020 16:43:07351 CALLE 27-AVENIDA REVOLU... \n",
"1 15/11/2020 06:47:56351 CALLE 27-AVENIDA REVOLU... \n",
"2 14/11/2020 15:58:1077 CHOAPAN-TAMAULIPAS \n",
"3 14/11/2020 13:47:17192 RUBEN DARIO-REFORMA \n",
"4 14/11/2020 11:21:49326 EUGENIA-NEBRASKA \n",
"\n",
" fecha_fin tiempo \\\n",
"0 16/11/2020 16:48:50312 AVENIDA 2-CALLE 7 00:05:43 \n",
"1 15/11/2020 07:01:3184 CHILPANCINGO-TLAXCALA 00:13:35 \n",
"2 14/11/2020 16:19:10351 CALLE 27-AVENIDA REVOLU... 00:21:00 \n",
"3 14/11/2020 14:14:1884 CHILPANCINGO-TLAXCALA 00:27:01 \n",
"4 14/11/2020 12:15:53218 HEGEL-IBARBOUROU 00:54:04 \n",
"\n",
" estacion_inicio estacion_fin \n",
"0 351 312 \n",
"1 351 84 \n",
"2 77 351 \n",
"3 192 84 \n",
"4 326 218 "
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"miuso = pd.read_html('datos/mi_uso_20201117.html')[0]\\\n",
" .rename(columns=lambda x: x.lower().replace(' ', '_'))\\\n",
" .drop('unnamed:_0', axis=1)\\\n",
" .assign(estacion_inicio=lambda x: x['fecha_de_inicio'].str.split().str[1].str[8:].astype(int),\n",
" estacion_fin=lambda x: x['fecha_fin'].str.split().str[1].str[8:].astype(int))\n",
"miuso.head()"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>districtcode</th>\n",
" <th>nearbystations_0</th>\n",
" <th>name</th>\n",
" <th>districtname</th>\n",
" <th>zipcode</th>\n",
" <th>location_lat</th>\n",
" <th>addressnumber</th>\n",
" <th>stationtype</th>\n",
" <th>nearbystations_2</th>\n",
" <th>nearbystations_1</th>\n",
" <th>location_lon</th>\n",
" <th>id</th>\n",
" <th>address</th>\n",
" <th>nearbystations_3</th>\n",
" <th>nearbystations_5</th>\n",
" <th>nearbystations_4</th>\n",
" <th>geometry</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>CUA</td>\n",
" <td>3</td>\n",
" <td>1 RIO SENA-RIO BALSAS</td>\n",
" <td>Cuauhtémoc</td>\n",
" <td>06500</td>\n",
" <td>19.433571</td>\n",
" <td>S/N</td>\n",
" <td>BIKE,TPV</td>\n",
" <td>85.0</td>\n",
" <td>8.0</td>\n",
" <td>-99.167809</td>\n",
" <td>1</td>\n",
" <td>001 - Río Sena-Río Balsas</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>POINT (-99.16781 19.43357)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>CUA</td>\n",
" <td>1</td>\n",
" <td>2 RIO GUADALQUIVIR-RIO BALSAS</td>\n",
" <td>Cuauhtémoc</td>\n",
" <td>06500</td>\n",
" <td>19.431386</td>\n",
" <td>S/N</td>\n",
" <td>BIKE</td>\n",
" <td>NaN</td>\n",
" <td>5.0</td>\n",
" <td>-99.171695</td>\n",
" <td>2</td>\n",
" <td>002 - Río Guadalquivir - Río Balsas</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>POINT (-99.17169 19.43139)</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1</td>\n",
" <td>8</td>\n",
" <td>3 REFORMA-INSURGENTES</td>\n",
" <td>Ampliación Granada</td>\n",
" <td>06500</td>\n",
" <td>19.431655</td>\n",
" <td>S/N</td>\n",
" <td>BIKE,TPV</td>\n",
" <td>86.0</td>\n",
" <td>20.0</td>\n",
" <td>-99.158668</td>\n",
" <td>3</td>\n",
" <td>003 - Reforma - Insurgentes</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>POINT (-99.15867 19.43165)</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" districtcode nearbystations_0 name \\\n",
"0 CUA 3 1 RIO SENA-RIO BALSAS \n",
"1 CUA 1 2 RIO GUADALQUIVIR-RIO BALSAS \n",
"2 1 8 3 REFORMA-INSURGENTES \n",
"\n",
" districtname zipcode location_lat addressnumber stationtype \\\n",
"0 Cuauhtémoc 06500 19.433571 S/N BIKE,TPV \n",
"1 Cuauhtémoc 06500 19.431386 S/N BIKE \n",
"2 Ampliación Granada 06500 19.431655 S/N BIKE,TPV \n",
"\n",
" nearbystations_2 nearbystations_1 location_lon id \\\n",
"0 85.0 8.0 -99.167809 1 \n",
"1 NaN 5.0 -99.171695 2 \n",
"2 86.0 20.0 -99.158668 3 \n",
"\n",
" address nearbystations_3 nearbystations_5 \\\n",
"0 001 - Río Sena-Río Balsas NaN NaN \n",
"1 002 - Río Guadalquivir - Río Balsas NaN NaN \n",
"2 003 - Reforma - Insurgentes NaN NaN \n",
"\n",
" nearbystations_4 geometry \n",
"0 NaN POINT (-99.16781 19.43357) \n",
"1 NaN POINT (-99.17169 19.43139) \n",
"2 NaN POINT (-99.15867 19.43165) "
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"estaciones = gpd.read_file('datos/estaciones_ecobici.geojson')\n",
"dicc_puntos_estaciones = estaciones.set_index('id').geometry.apply(lambda p: (p.x, p.y)).to_dict()\n",
"estaciones.head(3)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"colonias = gpd.read_file('datos/colonias_ecobici_bordes.geojson')"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(1, 1, figsize=(10, 10))\n",
"estaciones.plot(markersize=0.5, ax=ax)\n",
"colonias.plot(linewidth=0.25, color='green', ax=ax)\n",
"anotaciones = []\n",
"tt = plt.annotate(s='.', xy=dicc_puntos_estaciones[1], arrowprops={'facecolor': 'black', 'width': 0.5, 'headwidth': 4})\n",
"ax.set_axis_off()\n",
"titulo = ax.set_title('')\n",
"\n",
"def animate(frame):\n",
" row = miuso.loc[frame]\n",
" if anotaciones:\n",
" anotaciones[-1].arrow_patch.set(color='gray', alpha=0.5)\n",
" anotaciones[-1].set(color='gray', alpha=0.5)\n",
" tt = ax.annotate(\n",
" s=row['estacion_inicio'],\n",
" xy=dicc_puntos_estaciones[row['estacion_inicio']],\n",
" xytext=dicc_puntos_estaciones[row['estacion_fin']],\n",
" arrowprops={'facecolor': 'black', 'width': 0.5, 'headwidth': 4, 'alpha': 0.8}\n",
" )\n",
" titulo.set_text(f'Viaje {frame}\\n de estación {row[\"estacion_inicio\"]} a {row[\"estacion_fin\"]}')\n",
" anotaciones.append(tt)\n",
"\n",
"frames = list(range(len(miuso)))[:]\n",
"ani = animation.FuncAnimation(fig, animate, frames=frames, blit=False, interval=400)\n",
"ani.save(\"mi_uso_de_ecobici.mp4\")\n",
"#plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"hide_input": false,
"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.10"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment