Appendix R — Accessibility API

Prototyping of a wrap of accessibility computation into custom classes with simple API.

import geopandas as gpd
import pandas as pd
import xarray as xr
import numpy as np
import joblib

from demoland_engine.indicators import Accessibility
data_folder = "/Users/martin/Library/CloudStorage/OneDrive-SharedLibraries-TheAlanTuringInstitute/Daniel Arribas-Bel - demoland_data"

Load the travel time matrix.

ttm = pd.read_parquet(f"{data_folder}/processed/accessibility/ttm_complete.parquet")

Convert the matrix to boolean xarray.DataArray.

ttm = ttm.set_index(["from_id", "to_id"])
ttm.columns = ["transit", "car", "bike", "walk"]
ttm.columns.name = "mode"
ttm_arr = xr.DataArray.from_series(ttm.stack())
ttm_15 = ttm_arr <= 15
ttm_15.name = "ttm_15"

Load Workplace zone population.

wpz_population = (
    pd.read_csv(
        f"{data_folder}/processed/accessibility/wpz_tynewear_occupation_edited.csv"
    )
    .rename(columns={"wpz11cd": "to_id"})
    .set_index("to_id")["pop"]
)

Merge with the traveltime matrix to create a baseline.

da = xr.DataArray.from_series(wpz_population)
da.name = "wpz_population"
baseline = xr.merge([ttm_15, da])
baseline["wpz_population"] = baseline["wpz_population"].fillna(0)
baseline
<xarray.Dataset>
Dimensions:         (from_id: 3795, to_id: 9254, mode: 4)
Coordinates:
  * from_id         (from_id) object 'E00041363' 'E00041364' ... 'E00175605'
  * to_id           (to_id) object 'E00041363' ... 'idFFE0D1A6-2B10-40AE-8E6E...
  * mode            (mode) object 'transit' 'car' 'bike' 'walk'
Data variables:
    ttm_15          (from_id, to_id, mode) bool True True True ... False False
    wpz_population  (to_id) float64 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0

Load greenspace data.

acc_greenspace = pd.read_csv(
    f"{data_folder}/processed/accessibility/acc_greenspace_allmodes_15min_tynewear.csv",
    index_col=0,
)
acc_greenspace.columns = ["transit", "car", "bike", "walk"]
greenspace = xr.DataArray.from_series(acc_greenspace.stack()).rename(
    {"level_1": "mode"}
)
greenspace.name = "green_accessibility"
baseline = xr.merge([baseline, greenspace])
baseline["green_accessibility"] = baseline["green_accessibility"].fillna(0)

Create a wrapper class.

acc = Accessibility(baseline)

Test the object on example input.

Create random OA data.

oa_data = pd.Series(
    np.random.randint(-100, 100, len(baseline.from_id)),
    index=baseline.from_id.values,
    name="oa",
)
oa_data.index.name = "to_id"
oa_data
to_id
E00041363    54
E00041364    91
E00041366    25
E00041367    12
E00041368    90
             ..
E00175601   -92
E00175602   -48
E00175603     4
E00175604   -84
E00175605   -35
Name: oa, Length: 3795, dtype: int64

Compute accessibility.

acc.job_accessibility(oa_data, "walk")
<xarray.DataArray 'combined' (from_id: 3795)>
array([ 9495., 10409.,  2972., ...,   395.,  1370.,   502.])
Coordinates:
    mode     <U4 'walk'
  * from_id  (from_id) object 'E00041363' 'E00041364' ... 'E00175605'
new_green = pd.Series(
    np.random.randint(-10000, 10000, len(baseline.from_id)),
    index=baseline.from_id.values,
    name="oa",
)
new_green.index.name = "to_id"
acc.greenspace_accessibility(new_green, "walk")
<xarray.DataArray (from_id: 3795)>
array([ 484420.89095001,  519545.30120002,  297545.45855   , ...,
       1828516.73930004, 1742541.35770002,   54213.1107    ])
Coordinates:
    mode     <U4 'walk'
  * from_id  (from_id) object 'E00041363' 'E00041364' ... 'E00175605'

Save the custom class to a compressed joblib.

with open(f"{data_folder}/models/accessibility.joblib", "wb") as f:
    joblib.dump(acc, f, compress=True)

Test loaded class

with open(f"{data_folder}/models/accessibility.joblib", "rb") as f:
    acc2 = joblib.load(f)
acc2
<demoland_engine.indicators.Accessibility at 0x175c43290>
oa_data = pd.Series(
    np.random.randint(-100, 100, len(acc2.baseline.from_id)),
    index=acc2.baseline.from_id.values,
    name="oa",
)
oa_data.index.name = "to_id"
acc2.job_accessibility(oa_data, "walk")
<xarray.DataArray 'combined' (from_id: 3795)>
array([ 9051., 10132.,  2795., ...,   973.,  1547.,  -303.])
Coordinates:
    mode     <U4 'walk'
  * from_id  (from_id) object 'E00041363' 'E00041364' ... 'E00175605'
new_green = pd.Series(
    np.random.randint(-10000, 10000, len(acc2.baseline.from_id)),
    index=acc2.baseline.from_id.values,
    name="oa",
)
new_green.index.name = "to_id"
acc2.greenspace_accessibility(new_green, "walk")
<xarray.DataArray (from_id: 3795)>
array([ 489257.89095001,  528378.30120002,  307546.45855   , ...,
       1775474.73930004, 1768524.35770002,   48372.1107    ])
Coordinates:
    mode     <U4 'walk'
  * from_id  (from_id) object 'E00041363' 'E00041364' ... 'E00175605'