Mobility for resilience: population density analysis

This notebook shows how to transform raw mobility data to population density maps using mobilkit.

We start loading raw HFLB data using the mobilkit.loader module.

[1]:
%config Completer.use_jedi = False
%matplotlib inline

import os
import csv
import gzip
import numpy as np
import pandas as pd
from math import sin, cos, sqrt, atan2, radians
import copy
import pickle
from datetime import datetime as dt
from datetime import timedelta
from datetime import timezone
import pytz
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import matplotlib.colors as mcolors
import mpl_toolkits.axes_grid1
import matplotlib.gridspec as gridspec
import mpl_toolkits
import dask
from dask import dataframe as dd
from dask.distributed import Client

import mobilkit

Load raw pings for selected IDs

[5]:
# client.close()
client = Client(address="127.0.0.1:8786", )
client.upload_file("dist/mobilkit-0.1-py3.9.egg")
[5]:
{'tcp://127.0.0.1:44845': {'status': 'OK'},
 'tcp://127.0.0.1:45415': {'status': 'OK'},
 'tcp://127.0.0.1:46085': {'status': 'OK'},
 'tcp://127.0.0.1:46423': {'status': 'OK'}}
[6]:
client
[6]:

Client

Cluster

  • Workers: 4
  • Cores: 4
  • Memory: 24.00 GB
[1]:
alldataf = "results/displacement_selectedids_all_data/"
filtered_dataf_reloaded = dd.read_parquet(alldataf) # .repartition(partition_size="200M")
if "datetime" not in filtered_dataf_reloaded.columns:
    # Add datetime column
    import pytz
    tz = pytz.timezone("America/Mexico_City")
    # Filter on dates...
    filtered_dataf_reloaded = mobilkit.loader.filterStartStopDates(filtered_dataf_reloaded,
                                                    start_date="2017-09-04",
                                                    stop_date="2017-09-25",
                                                    tz=tz,)
    filtered_dataf_reloaded = mobilkit.loader.compute_datetime_col(filtered_dataf_reloaded, selected_tz=tz)

Compute day- and night-time locations

First I compute all the day and night time, then I use the function to compute the locations of each users for each day during day and night.

[2]:
# Prepare pings adding day- night- stuff
df_with_dn_time = mobilkit.temporal.filter_daynight_time(
                                                filtered_dataf_reloaded,
                                                filter_from_h=-1,
                                                filter_to_h=25, # To keep all the events
                                                previous_day_until_h=4,
                                                daytime_from_h=8,
                                                daytime_to_h=22,
                                            )
[9]:
# Filter to ROI
df_with_dn_time_roi = mobilkit.spatial.filter_to_box(df_with_dn_time,
                                                       minlon=-99.8761, maxlat=19.7661,
                                                       maxlon=-97.9208, minlat=18.7507)
[10]:
# Sample for speedup
df_sampled = df_with_dn_time_roi.sample(frac=.2)
[3]:
result_density = mobilkit.spatial.compute_population_density(df_sampled, maxpoints=50, max_iter=100)
[13]:
result_density.to_pickle("results/population_density.pkl")

Plot density maps

[14]:
result_density = pd.read_pickle("results/population_density.pkl")
[15]:
normaldays = [dt.strptime(s, "%Y%m%d") for s in ["20170904","20170905","20170906",
                                                 "20170907","20170908","20170911",
                                                "20170912","20170913","20170914","20170915"]]
[16]:
# Prepare some annotations, just in case...
map_annotations = {
    "CDMX": dict(xy=(-98.85,19.5), xycoords='data', color="white", fontsize=14),
    "Puebla": dict(xy=(-98.5,18.8), xycoords='data', color="white", fontsize=14),
    "Toluca": dict(xy=(-99.75,19.5), xycoords='data', color="white", fontsize=14),
    "Cuernavaca": dict(xy=(-99.4,18.65), xycoords='data', color="white", fontsize=14),
}

Daytime population density

[17]:
from importlib import reload
reload(mobilkit)
reload(mobilkit.viz)
reload(mobilkit.spatial)
[17]:
<module 'mobilkit.spatial' from '/home/ubi/Sandbox/mobilkit_dask/mobilkit/spatial.py'>
[18]:
df = result_density.reset_index().copy(deep=True)
[19]:
date = dt(2017,9,20)
daytime = True

df = df[(df["date"]==date) & (df["daytime"]==daytime)]

fig, ax = plt.subplots(1, 1, figsize=(5,5))
ax.set_aspect("equal")
heatmap, ax = mobilkit.viz.plot_density_map(df["lat"], df["lng"], (19.3, -98.9), 200, 1, ax,
                                   annotations=map_annotations)
../_images/examples_M4R_04_Population_Density_Analysis_19_0.png
[20]:
# Select parameters for the analysis
bins = 200
center = (19.3, -98.9)
radius = 1
[21]:
results_day = mobilkit.spatial.stats_density_map(result_density, normaldays, daytime=True,
                                                         bins=bins, center=center, radius=radius)

results_night = mobilkit.spatial.stats_density_map(result_density, normaldays, daytime=False,
                                                         bins=bins, center=center, radius=radius)

Standard deviation

[22]:
mobilkit.viz.shori_density_map(results_day["std"], results_day["x_bins"], results_day["y_bins"],
                               ax=None, annotations=map_annotations,
                               vmin=1e-4, vmax=results_day["std"].max())
/home/ubi/Sandbox/mobilkit_dask/mobilkit/viz.py:100: MatplotlibDeprecationWarning: default base will change from np.e to 10 in 3.4.  To suppress this warning specify the base keyword argument.
  divnorm = mcolors.SymLogNorm(linthresh=1.0, linscale=1.0, vmin=vmin, vmax=vmax)
[22]:
<matplotlib.image.AxesImage at 0x7f1999c0a670>
../_images/examples_M4R_04_Population_Density_Analysis_23_2.png

z-scores

[23]:
# select the day to plot
mobilkit.viz.shori_density_map(results_day["zsc"][0], results_day["x_bins"], results_day["y_bins"],
                               ax=None, annotations=map_annotations,
                               vmin=-3, vmax=3)
[23]:
<matplotlib.image.AxesImage at 0x7f19559761c0>
../_images/examples_M4R_04_Population_Density_Analysis_25_1.png

Compute the zscore in a given day

I just compute the density map for that day and compute its z-score w.r.t. the analysis on the “normal” days.

[24]:
date_selected = dt(2017, 9, 19)
density_earthquake_d, xybins = mobilkit.spatial.stack_density_map(result_density, dates=[date_selected],
                                                       center=center, bins=bins, radius=radius)

density_earthquake_n, xybins = mobilkit.spatial.stack_density_map(result_density, dates=[date_selected], daytime=False,
                                                       center=center, bins=bins, radius=radius)
[25]:
z_score_earthq_d = (density_earthquake_d - results_day["avg"]) / results_day["std"]
z_score_earthq_n = (density_earthquake_n - results_night["avg"]) / results_night["std"]
[26]:
fig, axs = plt.subplots(1,2,figsize=(12,6))

ax = axs[0]
ax.set_title("Daytime")
mobilkit.viz.shori_density_map(z_score_earthq_d[0], results_day["x_bins"], results_day["y_bins"],
                               ax=ax, annotations=map_annotations,
                               vmin=-3, vmax=3)


ax = axs[1]
ax.set_title("Nightime")
mobilkit.viz.shori_density_map(z_score_earthq_n[0], results_day["x_bins"], results_day["y_bins"],
                               ax=ax, annotations=map_annotations,
                               vmin=-3, vmax=3)
[26]:
<matplotlib.image.AxesImage at 0x7f1976bbd280>
../_images/examples_M4R_04_Population_Density_Analysis_29_1.png

Zoom in CDMX

[27]:
center = (19.43, -99.13)
radius = .2
bins = int(500*radius)
[28]:
results_day_mxc = mobilkit.spatial.stats_density_map(result_density, normaldays, daytime=True,
                                                         bins=bins, center=center, radius=radius)

results_night_mxc = mobilkit.spatial.stats_density_map(result_density, normaldays, daytime=False,
                                                         bins=bins, center=center, radius=radius)
[29]:
fig = plt.figure(figsize=(15,10))
gs = gridspec.GridSpec(1,2)
ax = fig.add_subplot(gs[0,0])
ax.set_title("Daytime")
mobilkit.viz.shori_density_map(results_day_mxc["zsc"][0], results_day_mxc["x_bins"], results_day_mxc["y_bins"],
                               ax=ax, vmin=-3, vmax=+3)

ax = fig.add_subplot(gs[0,1])
ax.set_title("Nightime")
mobilkit.viz.shori_density_map(results_night_mxc["zsc"][0], results_night_mxc["x_bins"], results_night_mxc["y_bins"],
                               ax=ax, vmin=-3, vmax=+3)
[29]:
<matplotlib.image.AxesImage at 0x7f197c50ce80>
../_images/examples_M4R_04_Population_Density_Analysis_33_1.png

Compare day and night

[30]:
# Compare event day
date_selected = dt(2017, 9, 19)
density_earthquake_mxc_d, xybins_mxc_d = mobilkit.spatial.stack_density_map(result_density, dates=[date_selected],
                                                       center=center, bins=bins, radius=radius)

density_earthquake_mxc_n, xybins_mxc_n = mobilkit.spatial.stack_density_map(result_density, dates=[date_selected],
                                                                            daytime=False,
                                                                            center=center, bins=bins, radius=radius)
[31]:
z_score_earthq_mxc_d = (density_earthquake_mxc_d - results_day_mxc["avg"]) / results_day_mxc["std"]
z_score_earthq_mxc_n = (density_earthquake_mxc_n - results_night_mxc["avg"]) / results_night_mxc["std"]
[32]:
fig = plt.figure(figsize=(15,10))
gs = gridspec.GridSpec(1,2)
ax = fig.add_subplot(gs[0,0])
ax.set_title("Daytime")
mobilkit.viz.shori_density_map(z_score_earthq_mxc_d[0], results_day_mxc["x_bins"], results_day_mxc["y_bins"],
                               ax=ax, vmin=-3, vmax=3)

ax = fig.add_subplot(gs[0,1])
ax.set_title("Nightime")
mobilkit.viz.shori_density_map(z_score_earthq_mxc_n[0], results_night_mxc["x_bins"], results_night_mxc["y_bins"],
                               ax=ax, vmin=-3, vmax=3)
[32]:
<matplotlib.image.AxesImage at 0x7f1999cf0ca0>
../_images/examples_M4R_04_Population_Density_Analysis_37_1.png

Zoom in Puebla

[33]:
center = (19.03, -98.2)
radius = .2
bins = int(500*radius)
[34]:
results_day_puebla = mobilkit.spatial.stats_density_map(result_density, normaldays, daytime=True,
                                                         bins=bins, center=center, radius=radius)

results_night_puebla = mobilkit.spatial.stats_density_map(result_density, normaldays, daytime=False,
                                                         bins=bins, center=center, radius=radius)
[35]:
fig = plt.figure(figsize=(15,10))
gs = gridspec.GridSpec(1,2)
ax = fig.add_subplot(gs[0,0])
ax.set_title("Daytime")
mobilkit.viz.shori_density_map(results_day_puebla["zsc"][0],
                               results_day_puebla["x_bins"], results_day_puebla["y_bins"],
                               ax=ax, vmin=-3, vmax=+3)

ax = fig.add_subplot(gs[0,1])
ax.set_title("Nightime")
mobilkit.viz.shori_density_map(results_night_puebla["zsc"][0],
                               results_night_puebla["x_bins"], results_night_puebla["y_bins"],
                               ax=ax, vmin=-3, vmax=+3)
[35]:
<matplotlib.image.AxesImage at 0x7f19554309d0>
../_images/examples_M4R_04_Population_Density_Analysis_41_1.png

Compare day and night

[42]:
# Compare event day
date_selected = dt(2017, 9, 19)
density_earthquake_puebla_d, xybins_puebla_d = mobilkit.spatial.stack_density_map(result_density, dates=[date_selected],
                                                       center=center, bins=bins, radius=radius)

density_earthquake_puebla_n, xybins_puebla_n = mobilkit.spatial.stack_density_map(result_density, dates=[date_selected],
                                                                            daytime=False,
                                                                            center=center, bins=bins, radius=radius)
[43]:
z_score_earthq_puebla_d = (density_earthquake_puebla_d - results_day_puebla["avg"]) / results_day_puebla["std"]
z_score_earthq_puebla_n = (density_earthquake_puebla_n - results_night_puebla["avg"]) / results_night_puebla["std"]
[44]:
fig = plt.figure(figsize=(15,10))
gs = gridspec.GridSpec(1,2)
ax = fig.add_subplot(gs[0,0])
ax.set_title("Daytime")
mobilkit.viz.shori_density_map(z_score_earthq_puebla_d[0], results_day_puebla["x_bins"], results_day_puebla["y_bins"],
                               ax=ax, vmin=-3, vmax=3)

ax = fig.add_subplot(gs[0,1])
ax.set_title("Nightime")
mobilkit.viz.shori_density_map(z_score_earthq_puebla_n[0], results_night_puebla["x_bins"], results_night_puebla["y_bins"],
                               ax=ax, vmin=-3, vmax=3)
[44]:
<matplotlib.image.AxesImage at 0x7f195591ce20>
../_images/examples_M4R_04_Population_Density_Analysis_45_1.png
[ ]: