{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Tabular Read-Write\n", "\n", "This notebook is an introduction to the PAM tabular read-write methods. It has two parts:\n", "\n", "1. [Read](#read-tabular-format)\n", "2. [Write](#write-tabular-data)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2020-05-18T14:31:06.631005Z", "start_time": "2020-05-18T14:31:06.133057Z" }, "execution": { "iopub.execute_input": "2023-09-22T10:52:12.682460Z", "iopub.status.busy": "2023-09-22T10:52:12.682315Z", "iopub.status.idle": "2023-09-22T10:52:13.624391Z", "shell.execute_reply": "2023-09-22T10:52:13.624086Z" } }, "outputs": [], "source": [ "import os\n", "\n", "import pandas as pd\n", "\n", "from pam import read" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Read Tabular Format\n", "\n", "PAM can read from either tabular or MATSim formats. Tabular formats use the `pam.read.load_travel_diary` function, which will try to automatically infer trips and activities from commonly formatted travel diary data.\n", "\n", "Tabular data should include a trips table and then optionally, atributes tables for persons and/or households. Tabular data is expected as pandas DataFrames with column names as described in the docs and/or as in the following example.\n", "\n", "The following demonstration data is available in the [`data/example_data`](https://github.com/arup-group/pam/tree/main/examples/data/example_data) directory. All data paths in this example are relative to the [notebook directory](https://github.com/arup-group/pam/tree/main/examples) in the PAM repository.\n", "\n", "#### Step 1\n", "\n", "Load your trips (and attributes) data into pandas DataFrames. Reformat and rename the columns as required (please read the docs). The following example already has the required data types and column names:\n", "\n", "**trips:**\n", "\n", "Each row represents a trip, where:\n", "\n", "- **pid**: person id of trip\n", "- **hid**: household id of trip (**optional**)\n", "- **seq**: sequence of trip within day (optional if order is already correct)\n", "- **hzone**: home zone of person (**optional**)\n", "- **ozone**: origin zone of trip\n", "- **dzone**: destination zone of trip\n", "- **purp**: purpose of trip (note that other ways of classifying purpose are supported - read the docs!)\n", "- **mode**: trip mode\n", "- **tst**: (integer) trip start time in minutes from start of day (typically from midnight)\n", "- **tet**: (integer) trip end time as above\n", "- **freq**: sample weighting (**optional**)\n", "\n", "**persons:**\n", "\n", "Each row represents a persons attributes. These can be arbitrary key - value pairs, with most types supported. The following are examples:\n", "\n", "- **pid**: person id, must be consistent with trips data (**required**)\n", "- gender: gender of person (example)\n", "- job: employment status of person (example)\n", "- occ: employment type of person (example)\n", "- inc: income of person (example)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2020-05-18T13:40:08.588305Z", "start_time": "2020-05-18T13:40:08.557000Z" }, "execution": { "iopub.execute_input": "2023-09-22T10:52:13.626292Z", "iopub.status.busy": "2023-09-22T10:52:13.626133Z", "iopub.status.idle": "2023-09-22T10:52:13.637252Z", "shell.execute_reply": "2023-09-22T10:52:13.636957Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
pidhidseqhzoneozonedzonepurpmodetsttetfreq
uid
0census_0census_00HarrowHarrowCamdenworkpt4444731000
1census_0census_01HarrowCamdenHarrowworkpt8909191000
2census_1census_10GreenwichGreenwichTower Hamletsworkpt5075281000
3census_1census_11GreenwichTower HamletsGreenwichworkpt106510861000
4census_2census_20CroydonCroydonCroydonworkpt4224251000
5census_2census_21CroydonCroydonCroydonworkpt9179201000
6census_3census_30HaringeyHaringeyRedbridgeworkpt4284471000
7census_3census_31HaringeyRedbridgeHaringeyworkpt100710261000
8census_4census_40HounslowHounslowWestminster,City of Londonworkcar4835161000
9census_4census_41HounslowWestminster,City of LondonHounslowworkcar101710501000
\n", "
" ], "text/plain": [ " pid hid seq hzone ozone \\\n", "uid \n", "0 census_0 census_0 0 Harrow Harrow \n", "1 census_0 census_0 1 Harrow Camden \n", "2 census_1 census_1 0 Greenwich Greenwich \n", "3 census_1 census_1 1 Greenwich Tower Hamlets \n", "4 census_2 census_2 0 Croydon Croydon \n", "5 census_2 census_2 1 Croydon Croydon \n", "6 census_3 census_3 0 Haringey Haringey \n", "7 census_3 census_3 1 Haringey Redbridge \n", "8 census_4 census_4 0 Hounslow Hounslow \n", "9 census_4 census_4 1 Hounslow Westminster,City of London \n", "\n", " dzone purp mode tst tet freq \n", "uid \n", "0 Camden work pt 444 473 1000 \n", "1 Harrow work pt 890 919 1000 \n", "2 Tower Hamlets work pt 507 528 1000 \n", "3 Greenwich work pt 1065 1086 1000 \n", "4 Croydon work pt 422 425 1000 \n", "5 Croydon work pt 917 920 1000 \n", "6 Redbridge work pt 428 447 1000 \n", "7 Haringey work pt 1007 1026 1000 \n", "8 Westminster,City of London work car 483 516 1000 \n", "9 Hounslow work car 1017 1050 1000 " ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "trips = pd.read_csv(\n", " os.path.join(\"data\", \"example_data\", \"example_travel_diaries.csv\"), index_col=\"uid\"\n", ")\n", "persons = pd.read_csv(\n", " os.path.join(\"data\", \"example_data\", \"example_attributes.csv\"), index_col=\"pid\"\n", ")\n", "trips.head(10)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2023-09-22T10:52:13.638783Z", "iopub.status.busy": "2023-09-22T10:52:13.638688Z", "iopub.status.idle": "2023-09-22T10:52:13.642330Z", "shell.execute_reply": "2023-09-22T10:52:13.642036Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
genderjoboccinc
pid
census_0femaleworkwhitelow
census_1femaleworkwhitelow
census_2maleworkbluehigh
census_3maleworkbluelow
census_4maleworkbluemedium
census_5othereducationwhitemedium
census_6femaleworkbluelow
census_7maleeducationwhitehigh
census_8femaleworkbluemedium
census_9femaleworkwhitelow
\n", "
" ], "text/plain": [ " gender job occ inc\n", "pid \n", "census_0 female work white low\n", "census_1 female work white low\n", "census_2 male work blue high\n", "census_3 male work blue low\n", "census_4 male work blue medium\n", "census_5 other education white medium\n", "census_6 female work blue low\n", "census_7 male education white high\n", "census_8 female work blue medium\n", "census_9 female work white low" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "persons.head(10)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "#### Step 2:\n", "\n", "Load the travel diary data:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2020-05-18T13:40:17.617442Z", "start_time": "2020-05-18T13:40:08.632419Z" }, "execution": { "iopub.execute_input": "2023-09-22T10:52:13.646304Z", "iopub.status.busy": "2023-09-22T10:52:13.646136Z", "iopub.status.idle": "2023-09-22T10:52:13.689782Z", "shell.execute_reply": "2023-09-22T10:52:13.689482Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Using tour based purpose parser (recommended)\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Adding pid->hh mapping to persons_attributes from trips.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Adding home locations to persons attributes using trips attributes.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Using freq of 'None' for all trips.\n" ] } ], "source": [ "population = read.load_travel_diary(trips, persons, trip_freq_as_person_freq=True)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2020-04-09T14:32:22.432201Z", "start_time": "2020-04-09T14:32:15.568791Z" } }, "source": [ "#### Step 3:\n", "\n", "Check everything is as expected. PAM will try to infer activities from trip data, including for arbitrarily complex sequences of nested tours.\n", "\n", "However, trip purpose can be encoded in a variety of ways. PAM will try to make sensible inference based on the data provided. If something looks wrong then check the docs, then consider raising an issue. The team are keen to support you!" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2020-05-18T13:40:17.640594Z", "start_time": "2020-05-18T13:40:17.621499Z" }, "execution": { "iopub.execute_input": "2023-09-22T10:52:13.691340Z", "iopub.status.busy": "2023-09-22T10:52:13.691257Z", "iopub.status.idle": "2023-09-22T10:52:13.693510Z", "shell.execute_reply": "2023-09-22T10:52:13.693223Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Person: census_12\n", "{'gender': 'female', 'job': 'education', 'occ': 'white', 'inc': 'high', 'hzone': 'Croydon'}\n", "0:\tActivity(act:home, location:Croydon, time:00:00:00 --> 07:06:00, duration:7:06:00)\n", "1:\tLeg(mode:pt, area:Croydon --> Tower Hamlets, time:07:06:00 --> 07:45:00, duration:0:39:00)\n", "2:\tActivity(act:education, location:Tower Hamlets, time:07:45:00 --> 15:54:00, duration:8:09:00)\n", "3:\tLeg(mode:pt, area:Tower Hamlets --> Croydon, time:15:54:00 --> 16:33:00, duration:0:39:00)\n", "4:\tActivity(act:home, location:Croydon, time:16:33:00 --> 00:00:00, duration:7:27:00)\n" ] } ], "source": [ "household = population.households[\"census_12\"]\n", "person = household.people[\"census_12\"]\n", "person.print()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2023-09-22T10:52:13.694877Z", "iopub.status.busy": "2023-09-22T10:52:13.694784Z", "iopub.status.idle": "2023-09-22T10:52:13.800437Z", "shell.execute_reply": "2023-09-22T10:52:13.800168Z" } }, "outputs": [ { "data": { "image/png": "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OlpFixZN9fqenp6PvD0hIUGvvPKKTZ327t2rI0eOWIc50qO3qWrVqjp+/LhGjx6tP/74Q88++6zat28vSXJyevCnzl/rlHiKsEQRERE6efKk+vbtqzNnzqhRo0bpvuD7wxw8eFANGzZUjx499Pbbb2foYwMAAAA5EUdqAAAAAGnk5eWlEiVKJFletmxZubu7KyYmxuZUU6lVqlQplSpVSv369dPzzz+vOXPmqG3btipbtqy2bt1qs+62bdtUqlQp61EamWnDhg3av3+/+vXrl+r7VKxYUadOndLhw4eTPVqjatWqOnDgQLJ1TIvcuXMrMjJSkZGRat++vZo3b64rV67I399fknT27FnrUTJ/vWh4In9/f0VFRSkqKkp169bVwIED9f777z9WpkQHDhxQw4YN1bVrV40ZMyZDHhMAAADI6RhqAAAAABnEx8dHAwYMUL9+/ZSQkKA6deroxo0b2rZtm7y9vdW1a9dk7/fHH39o4MCBat++vYoWLapTp05px44deuaZZyRJb7zxhqpXr67Ro0crMjJSP/74oz7++GNNmzYtw7fh7t27OnfunOLj43X+/HmtXr1a48aNU8uWLfXCCy9Y1xs8eLBOnz6tefPmJfs49evXV7169fTMM89o8uTJKlGihH777TdZLBY1b95cgwYNUo0aNdSrVy/16NFDXl5eio6O1rp16zR16tRUZf3ggw8UFBSkypUry8nJSV999ZUCAwOVN29eOTk5qUaNGho/frxCQ0N16dKlJEdKDB8+XNWqVVO5cuV09+5drVixwnraq5TExMToypUriomJUXx8vHVgUqJECXl7e+vAgQNq0KCBmjZtqv79++vcuXOSJGdnZ+vABQAAAEDaMdQAAAAAMtDo0aMVEBCgcePG6dixY8qbN6+qVq2qIUOGPPQ+zs7Ounz5sl544QWdP39efn5+ateund555x1JD45qWLx4sYYPH67Ro0crKChIo0aNsrlIeEZZvXq1goKC5OLionz58qlSpUqaMmWKunbtaj2lk/TgCIiYmJhHPtbXX3+tAQMG6Pnnn1dsbKxKlCih8ePHS3pwJMfmzZs1dOhQ1a1bV4ZhqHjx4oqMjEx1Vm9vb02YMEFHjhyRs7Ozqlevru+++86a87PPPlP37t0VHh6u0qVLa+LEiTbX3HBzc9PgwYN14sQJeXp6qm7dulq4cGGq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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "person.plot()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Write Tabular Data\n", "\n", "PAM can write into a preferred tabular formats using `pam.write.to_csv`. This outputs trip legs, household attributes and person attributes tables. Where sufficient geometries are found, PAM will write spatial data as geojson." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2020-05-18T13:40:19.159176Z", "start_time": "2020-05-18T13:40:19.133774Z" }, "execution": { "iopub.execute_input": "2023-09-22T10:52:13.801863Z", "iopub.status.busy": "2023-09-22T10:52:13.801765Z", "iopub.status.idle": "2023-09-22T10:52:13.834658Z", "shell.execute_reply": "2023-09-22T10:52:13.834253Z" } }, "outputs": [], "source": [ "from pam import write\n", "\n", "write.to_csv(population, dir=\"tmp\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "PAM can also write directly to O-D matrices using `pam.write.write_od_matrices`. This can optionally be segmented (read the docs). But does not currently support trip weighting (frequency).\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2023-09-22T10:52:13.836946Z", "iopub.status.busy": "2023-09-22T10:52:13.836776Z", "iopub.status.idle": "2023-09-22T10:52:13.851430Z", "shell.execute_reply": "2023-09-22T10:52:13.850697Z" } }, "outputs": [], "source": [ "write.write_od_matrices(population, \"tmp\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Pickle\n", "\n", "Not a tabular format but if you've read this far - you might like to know that there is a Population.pickle method:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2020-05-18T13:40:23.298011Z", "start_time": "2020-05-18T13:40:22.714290Z" }, "execution": { "iopub.execute_input": "2023-09-22T10:52:13.853673Z", "iopub.status.busy": "2023-09-22T10:52:13.853534Z", "iopub.status.idle": "2023-09-22T10:52:13.860152Z", "shell.execute_reply": "2023-09-22T10:52:13.859767Z" } }, "outputs": [], "source": [ "population.pickle(os.path.join(\"tmp\", \"population.pickle\"))" ] } ], "metadata": { "kernelspec": { "display_name": "pam", "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.11.5" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": true, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "248.333px" }, "toc_section_display": true, "toc_window_display": false }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }