Mobility

Download and process the daily mobility observations published by MITMA:

  • Origin-destination trips and their total trip-kilometres.

  • Overnight stays (version 2).

  • People grouped by number of trips.

  • Selected activity or demographic dimensions and acquisition manifests.

Use Zones to obtain the geography associated with the zone IDs.

class pyspainmobility.mobility.mobility.Mobility(version: int = 2, zones: str = 'municipalities', start_date: str = None, end_date: str = None, output_directory: str = None, use_dask: bool = False, backend: str = 'auto')[source]

This is the object taking care of the data download and preprocessing of (i) daily origin-destination matrices (ii), overnight stays and (iii) number of trips. The data is downloaded from the Spanish Ministry of Transport, Mobility and Urban Agenda (MITMA) Open Data portal. Additional information can be found at https://www.transportes.gob.es/ministerio/proyectos-singulares/estudio-de-movilidad-con-big-data. The data is available for two versions: version 1 (2020-02-14 to 2021-05-09) and version 2 (2022-01-01 onward). Data are available at different levels of granularity: districts (distritos), municipalities (municipios) and large urban areas (grandes áreas urbanas). Concerning version 1, data are LUA are not available. Also, overnight stays are not available for version 1.

Parameters:
  • version (int) – The version of the data to download. Default is 2. Version must be 1 or 2. Version 1 contains the data from 2020 to 2021. Version 2 contains the data from 2022 onwards.

  • zones (str) – The zones to download the data for. Default is municipalities. Zones must be one of the following: districts, dist, distr, distritos, municipalities, muni, municipal, municipios, lua, large_urban_areas, gau, gaus, grandes_areas_urbanas provinces derives provincial products by summing district data. Unmappable zones are excluded explicitly and their counts are reported.

  • start_date (str) – The start date of the data to download. Date must be in the format YYYY-MM-DD. A start date is required

  • end_date (str) – The end date of the data to download. Default is None. Date must be in the format YYYY-MM-DD. if not specified, the end date will be the same as the start date.

  • output_directory (str) – The directory to save the raw data and the processed parquet. Default is None. If not specified, the data will be saved in a folder named ‘data’ in user’s home directory.

  • use_dask (bool) – Whether to use Dask for processing large datasets with the Arrow or pandas backend. Default is False. Ignored by the Polars backend, which already executes the multi-file query in parallel.

  • backend (str) – Dataframe backend used while reading and processing files. The default ‘auto’ selects Polars when installed, then Arrow, then pandas. Use ‘polars’ for a lazy, streaming pipeline, ‘arrow’ for Apache Arrow-backed pandas columns, or ‘pandas’ for classic pandas dtypes. Polars and Arrow both return an Arrow-backed pandas DataFrame when a public method is called with return_df=True.

Examples

>>> from pyspainmobility import Mobility
>>> # instantiate the object
>>> mobility_data = Mobility(version=2, zones='municipalities', start_date='2022-01-01', end_date='2022-01-06', output_directory='/Desktop/spain/data/')
>>> # download and save the origin-destination data
>>> mobility_data.get_od_data(keep_activity=True)
>>> # download and save the overnight stays data
>>> mobility_data.get_overnight_stays_data()
>>> # download and save the number of trips data
>>> mobility_data.get_number_of_trips_data()
__init__(version: int = 2, zones: str = 'municipalities', start_date: str = None, end_date: str = None, output_directory: str = None, use_dask: bool = False, backend: str = 'auto')[source]
get_od_data(keep_activity: bool = False, return_df: bool = False, social_agg: bool = False, allow_partial: bool = False, dimensions: Sequence[str] | None = None)[source]

Function to download and save the origin-destination data.

Parameters:
  • keep_activity (bool) – Default value is False. If True, the columns ‘activity_origin’ and ‘activity_destination’ will be kept in the final dataframe. If False, the columns will be dropped. The columns contain the activity of the origin and destination zones. Version 1 district values are ‘home’, ‘work_or_study’, and ‘other’. Version 2 values are ‘home’, ‘work_or_study’, ‘other_frequent’, and ‘other_non_frequent’. For version 1, activity is available for districts only; municipality source files have no activity columns. Version 1 does not support social_agg. Consider that keeping the activity columns will increase the size of the final dataframe and the saved files significantly.

  • return_df (bool) – Default value is False. If True, the function will return the dataframe in addition to saving it to a file.

  • social_agg (bool) – Default value is False. Adds socio-demographic breakdown.

  • income (•)

  • age (•)

  • gender (•)

  • allow_partial (bool) – If False (default), fail before saving when a requested daily file is missing or has invalid mandatory OD rows. If True, save only fully valid source days with a _partial filename suffix and inspect get_acquisition_manifest() for excluded dates. Missing explicitly requested dimension columns always raise an error.

  • dimensions (sequence of str, optional) – Optional OD columns to retain as grouping keys: activity_origin, activity_destination, residence_province_ine_code, distance, income, age, or gender. Omitted dimensions are aggregated away. Use this instead of keep_activity and social_agg; the older flags remain supported. Every source day must contain the requested columns. Missing values within an existing column are retained; a missing column raises a ValueError identifying the date and dimension.

Examples

>>> from pyspainmobility import Mobility
>>> # instantiate the object
>>> mobility_data = Mobility(version=2, zones='municipalities', start_date='2022-01-01', end_date='2022-01-06', output_directory='/Desktop/spain/data/')
>>> # download and save the origin-destination data
>>> mobility_data.get_od_data(keep_activity=True)
>>> # download and save the od data and return the dataframe
>>> df = mobility_data.get_od_data(keep_activity=False, return_df=True)
>>> print(df.head())
    date  hour id_origin id_destination  n_trips  trips_total_length_km
0  2023-04-01     0     01001          01001    5.006              19.878000
1  2023-04-01     0     01001       01009_AM   14.994              70.697000
2  2023-04-01     0     01001       01058_AM    9.268              87.698000
3  2023-04-01     0     01001          01059   42.835             512.278674
4  2023-04-01     0     01001          48036    2.750             147.724000
get_overnight_stays_data(return_df: bool = False, allow_partial: bool = False)[source]

Function to download and save the overnight stays data.

Parameters:
  • return_df (bool) – Default value is False. If True, the function will return the dataframe in addition to saving it to a file.

  • allow_partial (bool) – Save only valid days with a _partial suffix if a requested download or source file fails. By default, raise before saving.

Examples

>>> from pyspainmobility import Mobility
>>> # instantiate the object
>>> mobility_data = Mobility(version=2, zones='municipalities', start_date='2022-01-01', end_date='2022-01-06', output_directory='/Desktop/spain/data/')
>>> # download and save the overnight stays data and return the dataframe
>>> df = mobility_data.get_overnight_stays_data( return_df=True)
>>> print(df.head())
   date residence_area overnight_stay_area    people
0  2023-04-01          01001               01001  2716.303
1  2023-04-01          01001            01009_AM    14.088
2  2023-04-01          01001            01017_AM     2.476
3  2023-04-01          01001            01058_AM    18.939
4  2023-04-01          01001               01059   144.118
get_number_of_trips_data(return_df: bool = False, allow_partial: bool = False)[source]

Function to download and save the data regarding the number of trips to an area of certain demographic categories.

Parameters:
  • return_df (bool) – Default value is False. If True, the function will return the dataframe in addition to saving it to a file.

  • allow_partial (bool) – Save only valid days with a _partial suffix if a requested download or source file fails. By default, raise before saving.

Examples

>>> from pyspainmobility import Mobility
>>> # instantiate the object
>>> mobility_data = Mobility(version=2, zones='municipalities', start_date='2022-01-01', end_date='2022-01-06', output_directory='/Desktop/spain/data/')
>>> # download and save the overnight stays data and return the dataframe
>>> df = mobility_data.get_number_of_trips_data( return_df=True)
>>> print(df.head())
date overnight_stay_area   age  gender number_of_trips   people
0  2023-04-01               01001  0-25    male               0  128.457
1  2023-04-01               01001  0-25    male               1   38.537
2  2023-04-01               01001  0-25    male               2  129.136
3  2023-04-01               01001  0-25    male              2+  129.913
4  2023-04-01               01001  0-25  female               0  188.744
get_acquisition_manifest(m_type: str = 'Viajes') → DataFrame[source]

Return the pre-filter file-acquisition record for one data type.

The manifest is populated by _donwload_helper() and has one row per requested date. status='available' means a non-empty source file was obtained locally. After a public processing call, parse_status distinguishes valid, genuinely empty, and invalid source files. The OD manifest can be passed to build_temporal_network for coverage-aware averages. Provincial products add per-day input/excluded counts and measures; attrs identifies the derived level and the unmapped source IDs.

Selecting processed OD data

pyspainmobility.mobility.selection.select_od(data, *, filters=None, group_by=None) → LazyFrame[source]

Select processed OD rows, optionally summing flows by chosen columns.

data may be a processed Parquet file, a pandas DataFrame, or a Polars DataFrame/LazyFrame. filters maps existing column names to exact values or collections of values (including None for missing categories). Both OD measures remain additive when group_by is provided. The result stays lazy; call collect() when needed.

Derived provincial products

Use zones="provinces" to sum district-source OD, overnight-stay and trip-count products by province. Dates, hours, selected categories and internal flows are retained. Version 1 has no overnight-stay product.

from pyspainmobility import Mobility

mobility = Mobility(version=2, zones="provinces", start_date="2024-01-01")
od = mobility.get_od_data(return_df=True, dimensions=["age", "gender"])
print(od.attrs["spatial"])
print(mobility.get_acquisition_manifest("Viajes"))
  • Province IDs are two-digit INE codes, including Ceuta (51) and Melilla (52).

  • Zones lacking a unique province are explicitly excluded. DataFrame attrs, per-day acquisition manifests and *.parquet.provenance.json files report excluded processed rows, trips, trip-kilometres or people.

  • Trip-kilometres are summed from the source; distances are not recalculated from province centroids. Trip-count categories retain their original meaning.

  • Files contain provinces_derived in their names. Raw downloads remain district sources and can be reused for district-level analyses.

  • Zones provides the corresponding derived province geometries.

Ordinary provenance publication errors restore the previous Parquet output; overwriting requires hard-link support in the output filesystem. An abrupt process or system interruption between the two atomic file replacements can leave a mismatched pair; rerun the request to regenerate both together. If rollback itself fails, a hidden *.previous file retains the old data.