Skip to content

Instantly share code, notes, and snippets.

@knaaptime
Created February 3, 2022 18:42
Show Gist options
  • Save knaaptime/7ad17a69f4e54109582616b10931e00a to your computer and use it in GitHub Desktop.
Save knaaptime/7ad17a69f4e54109582616b10931e00a to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "27c78e5f-8e17-4a67-93de-3f449c6ac177",
"metadata": {
"execution": {
"iopub.execute_input": "2022-02-03T18:40:11.229595Z",
"iopub.status.busy": "2022-02-03T18:40:11.229316Z",
"iopub.status.idle": "2022-02-03T18:40:11.501165Z",
"shell.execute_reply": "2022-02-03T18:40:11.500845Z",
"shell.execute_reply.started": "2022-02-03T18:40:11.229524Z"
},
"tags": []
},
"outputs": [],
"source": [
"import pandas as pd\n",
"from access import Access, weights as w"
]
},
{
"cell_type": "markdown",
"id": "ca18314f-d6ad-4d07-80e2-c3789572d146",
"metadata": {},
"source": [
"## accessibility should be different at all three nodes in all three scenarios"
]
},
{
"cell_type": "markdown",
"id": "812ec6d6-50fe-4940-83ea-5db256f1676d",
"metadata": {},
"source": [
"The city is depicted by three tracts. We've got one high density employment tract in the city center (node 3) that also contains some housing. We've got two suburban tracts (nodes 1 and 3) with housing and some employment, one on either side of the metro\n",
"\n",
"(this is essentially the classic monocentric model with a slight relaxation)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "b7934117-61bb-47e1-a9a3-16c0c73eace4",
"metadata": {
"execution": {
"iopub.execute_input": "2022-02-03T18:40:11.501878Z",
"iopub.status.busy": "2022-02-03T18:40:11.501804Z",
"iopub.status.idle": "2022-02-03T18:40:11.506288Z",
"shell.execute_reply": "2022-02-03T18:40:11.506034Z",
"shell.execute_reply.started": "2022-02-03T18:40:11.501869Z"
}
},
"outputs": [],
"source": [
"tracts = pd.DataFrame(\n",
" [\n",
" {\"geoid\": 1, \"pop\": 100, \"doc\": 15},\n",
" {\"geoid\": 2, \"pop\": 50, \"doc\": 20},\n",
" {\"geoid\": 3, \"pop\": 10, \"doc\": 100},\n",
" ]\n",
")"
]
},
{
"cell_type": "markdown",
"id": "4ecfa237-f9c3-4a13-b33c-e022a72284d0",
"metadata": {},
"source": [
"There are three scenarios that are identical in their population and employment allocation across tracts. The only thing that changes between scenarios is the transportation system. By changing the speed with which consumers can travel around the metro, we should induce changes in accessibility at all three nodes (because 2SFCA should account for both supply and demand at each location and both quantities are in flux when we change the transport system)"
]
},
{
"cell_type": "markdown",
"id": "db05b528-4dcb-4a16-987f-fe454271ab49",
"metadata": {},
"source": [
"![Slide1.png](https://drive.google.com/uc?id=1RfuTMASKBOhZzKaXGPM05H7QKgIy5Aiv)\n",
"\n",
"![Slide2.png](https://drive.google.com/uc?id=1wAkKON9RVnnYylemTcEZY_SgFcmudjso)\n",
"\n",
"![Slide3.png](https://drive.google.com/uc?id=1vXg0XAjGevrisMVfVKTq6cWVV8oRlgLM)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "f10e7502-9389-4f2b-9320-d627865b127f",
"metadata": {
"execution": {
"iopub.execute_input": "2022-02-03T18:40:11.507251Z",
"iopub.status.busy": "2022-02-03T18:40:11.507191Z",
"iopub.status.idle": "2022-02-03T18:40:11.513334Z",
"shell.execute_reply": "2022-02-03T18:40:11.512875Z",
"shell.execute_reply.started": "2022-02-03T18:40:11.507243Z"
},
"tags": []
},
"outputs": [],
"source": [
"\n",
"# Gridlock. travel is congested in both directions\n",
"scenario_1 = pd.DataFrame(\n",
" [\n",
" {\"origin\": 1, \"dest\": 3, \"cost\": 40},\n",
" {\"origin\": 2, \"dest\": 3, \"cost\": 40},\n",
" {\"origin\": 3, \"dest\": 1, \"cost\": 40},\n",
" {\"origin\": 3, \"dest\": 2, \"cost\": 40},\n",
" {\"origin\": 3, \"dest\": 3, \"cost\": 1},\n",
" {\"origin\": 2, \"dest\": 2, \"cost\": 1},\n",
" {\"origin\": 1, \"dest\": 1, \"cost\": 1},\n",
" {\"origin\": 1, \"dest\": 2, \"cost\": 80},\n",
" {\"origin\": 2, \"dest\": 1, \"cost\": 80},\n",
" ]\n",
")\n",
"\n",
"\n",
"# Commuter toll lane into the city (similar dynamics to PM peak)\n",
"scenario_2 = pd.DataFrame(\n",
" [\n",
" {\"origin\": 1, \"dest\": 3, \"cost\": 20}, # faster commute 1-->3\n",
" {\"origin\": 2, \"dest\": 3, \"cost\": 20}, # faster commute 2-->3\n",
" {\"origin\": 3, \"dest\": 1, \"cost\": 40}, \n",
" {\"origin\": 3, \"dest\": 2, \"cost\": 40}, \n",
" {\"origin\": 3, \"dest\": 3, \"cost\": 1},\n",
" {\"origin\": 2, \"dest\": 2, \"cost\": 1},\n",
" {\"origin\": 1, \"dest\": 1, \"cost\": 1},\n",
" {\"origin\": 1, \"dest\": 2, \"cost\": 80},\n",
" {\"origin\": 2, \"dest\": 1, \"cost\": 80},\n",
" ]\n",
")\n",
"\n",
"# Commuter toll lane out of the city (similar dynamics to AM peak)\n",
"scenario_3 = pd.DataFrame(\n",
" [\n",
" {\"origin\": 1, \"dest\": 3, \"cost\": 40}, \n",
" {\"origin\": 2, \"dest\": 3, \"cost\": 40}, \n",
" {\"origin\": 3, \"dest\": 1, \"cost\": 20}, # faster commute 3-->1\n",
" {\"origin\": 3, \"dest\": 2, \"cost\": 20}, # faster commute 3-->2\n",
" {\"origin\": 3, \"dest\": 3, \"cost\": 1},\n",
" {\"origin\": 2, \"dest\": 2, \"cost\": 1},\n",
" {\"origin\": 1, \"dest\": 1, \"cost\": 1},\n",
" {\"origin\": 1, \"dest\": 2, \"cost\": 80},\n",
" {\"origin\": 2, \"dest\": 1, \"cost\": 80},\n",
" ]\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "456fde03-a754-4b05-9882-42e107db619a",
"metadata": {
"execution": {
"iopub.execute_input": "2022-02-03T18:40:11.514060Z",
"iopub.status.busy": "2022-02-03T18:40:11.513975Z",
"iopub.status.idle": "2022-02-03T18:40:11.540043Z",
"shell.execute_reply": "2022-02-03T18:40:11.539382Z",
"shell.execute_reply.started": "2022-02-03T18:40:11.514051Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" scenario_1_doc scenario_2_doc scenario_3_doc\n",
"geoid \n",
"1 0.40000 0.65000 0.4000\n",
"2 0.65000 0.90000 0.6500\n",
"3 10.01375 10.01375 10.0275\n"
]
}
],
"source": [
"\n",
" # input parameters fixed across scenarios\n",
"params= dict(\n",
" demand_df=tracts,\n",
" demand_index=\"geoid\",\n",
" demand_value=\"pop\",\n",
" \n",
" supply_df=tracts,\n",
" supply_index=\"geoid\",\n",
" supply_value=[\"doc\"],\n",
" \n",
" cost_origin=\"origin\",\n",
" cost_dest=\"dest\",\n",
" cost_name=\"cost\",\n",
" \n",
" neighbor_cost_origin=\"origin\",\n",
" neighbor_cost_dest=\"dest\",\n",
" neighbor_cost_name=\"cost\",\n",
")\n",
"\n",
"\n",
"# Scenario 1 is gridlock\n",
"scen_1 = Access(\n",
" **params,\n",
" cost_df= scenario_1, \n",
" neighbor_cost_df= scenario_1,\n",
")\n",
"\n",
"\n",
"# Scenario 2 is faster treavel to the city\n",
"scen_2 = Access(\n",
" **params,\n",
" cost_df= scenario_2, \n",
" neighbor_cost_df= scenario_2, \n",
")\n",
"\n",
"\n",
"# Scenario 3 is faster travel out of the city\n",
"scen_3 = Access(\n",
" **params,\n",
" cost_df= scenario_3, \n",
" neighbor_cost_df= scenario_3, \n",
")\n",
"\n",
"\n",
"scen_1.two_stage_fca(name=\"scenario_1\", weight_fn=w.gravity(1, -1), max_cost=61)\n",
"scen_2.two_stage_fca(name=\"scenario_2\", weight_fn=w.gravity(1, -1), max_cost=61)\n",
"scen_3.two_stage_fca(name=\"scenario_3\", weight_fn=w.gravity(1, -1), max_cost=61)\n",
"\n",
"results = pd.concat([scen_1.access_df.drop(columns=['pop']), \n",
" scen_2.access_df.drop(columns=['pop']),\n",
" scen_3.access_df.drop(columns=['pop'])], axis=1)\n",
"\n",
"print(results)"
]
},
{
"cell_type": "markdown",
"id": "67a62e27-2ab6-4ece-90d3-571f4980d42b",
"metadata": {
"execution": {
"iopub.execute_input": "2022-02-03T05:21:04.141129Z",
"iopub.status.busy": "2022-02-03T05:21:04.140335Z",
"iopub.status.idle": "2022-02-03T05:21:04.163990Z",
"shell.execute_reply": "2022-02-03T05:21:04.163626Z",
"shell.execute_reply.started": "2022-02-03T05:21:04.141074Z"
},
"tags": []
},
"source": [
"\n",
"Accessibility at all three nodes should be different in all three scenarios, but it's not. You can see that only the outward edges are considered in each scenario. Any time the incoming edges (impedances) are different, they're ignored:\n",
" \n",
"scenario 1 is the baseline. We compare others to this"
]
},
{
"cell_type": "markdown",
"id": "667c200e-e49f-468e-bd01-23c5052010ad",
"metadata": {},
"source": [
"## Testing Secnario 2\n",
"\n",
"scenario 2 is faster travel to the city. \n",
"\n",
"Versus the baseline, we should see access *decrease* at 3 and *increase* at 1&2. \n",
"\n",
"\n",
"- access at 1 should increase. There is more supply available from 3 since people can get there faster\n",
"- access at 2 should increase. There is more supply available from 3 since people can get there faster\n",
"- access at 3 should decrease. There is more demand coming from 1,2 since people come from there faster"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "f17c93fd-0249-44f9-9aad-d736a7b5a311",
"metadata": {
"execution": {
"iopub.execute_input": "2022-02-03T18:40:11.540965Z",
"iopub.status.busy": "2022-02-03T18:40:11.540813Z",
"iopub.status.idle": "2022-02-03T18:40:11.551553Z",
"shell.execute_reply": "2022-02-03T18:40:11.551198Z",
"shell.execute_reply.started": "2022-02-03T18:40:11.540951Z"
},
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"geoid\n",
"1 False\n",
"2 False\n",
"3 True\n",
"dtype: bool"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results.scenario_1_doc == results.scenario_2_doc"
]
},
{
"cell_type": "markdown",
"id": "1cd14fab-b2a2-47d0-9cfd-f3c5fee0b70b",
"metadata": {
"execution": {
"iopub.execute_input": "2022-02-03T15:12:50.603742Z",
"iopub.status.busy": "2022-02-03T15:12:50.602515Z",
"iopub.status.idle": "2022-02-03T15:12:50.621170Z",
"shell.execute_reply": "2022-02-03T15:12:50.620178Z",
"shell.execute_reply.started": "2022-02-03T15:12:50.603676Z"
}
},
"source": [
"Here, we only see the change in the suburbs. \n",
"\n",
"The incoming change to 3 is ignored (results are the same as baseline). We're not accounting for the additional demand at 3, which should lower the accessibility score. It's the same value as scenario 1"
]
},
{
"cell_type": "markdown",
"id": "8841a59e-4c7b-4e7c-9723-91956ed57205",
"metadata": {},
"source": [
"## Testing Scenario 3\n",
"scenario 3 is faster travel out of the city. \n",
"\n",
"Versus the baseline, we should see access *decrease* at 1&2 and *increase* at 3. \n",
"\n",
"- access at 1 should decrease. There is more demand coming from 3 since people can come from there faster\n",
"- access at 2 should decrease. There is more demand coming from 3 since people can come from there faster\n",
"- access at 3 should increase. There is more supply available from 1,2 since people can get there faster"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "27229fed-b7fa-41c8-823e-be94580b5547",
"metadata": {
"execution": {
"iopub.execute_input": "2022-02-03T18:40:11.552303Z",
"iopub.status.busy": "2022-02-03T18:40:11.552220Z",
"iopub.status.idle": "2022-02-03T18:40:11.562266Z",
"shell.execute_reply": "2022-02-03T18:40:11.560791Z",
"shell.execute_reply.started": "2022-02-03T18:40:11.552293Z"
},
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"geoid\n",
"1 True\n",
"2 True\n",
"3 False\n",
"dtype: bool"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results.scenario_1_doc == results.scenario_3_doc"
]
},
{
"cell_type": "markdown",
"id": "e864981e-416b-40ea-9019-c7a5a1c48428",
"metadata": {
"execution": {
"iopub.execute_input": "2022-02-03T15:13:56.039663Z",
"iopub.status.busy": "2022-02-03T15:13:56.038885Z",
"iopub.status.idle": "2022-02-03T15:13:56.050538Z",
"shell.execute_reply": "2022-02-03T15:13:56.049586Z",
"shell.execute_reply.started": "2022-02-03T15:13:56.039602Z"
}
},
"source": [
"Here, we only see change in the city (3). \n",
"\n",
"The incoming changes to 1&2 are ignored (results are the same as baseline). We're not accounting for additional demand at 1&2, which should lower the accessibility score. Those values are the same as scenario 1"
]
},
{
"cell_type": "markdown",
"id": "1aa330ef-ee16-4cf5-b532-e3fd7110b0b6",
"metadata": {},
"source": [
"## Summarizing\n",
"\n",
"We're failing to account for changes to demand because our search only includes outbound impedances. \n",
"\n",
"This is a critical implementation error."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cacdc768-1859-4ab9-8780-63d146049f0e",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda env:access]",
"language": "python",
"name": "conda-env-access-py"
},
"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.10.2"
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"state": {},
"version_major": 2,
"version_minor": 0
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment