Collective Measures
| API | Description |
|---|---|
homes_per_location |
Return the number of users whose home is at each distinct location. |
mean_square_displacement |
Return the mean square displacement (km^2) across all users. |
random_location_entropy |
Return the random entropy for each distinct location across all users. |
uncorrelated_location_entropy |
Return the uncorrelated entropy for each distinct location across all users. |
visits_per_location |
Return the total number of visits for each distinct location. |
visits_per_time_unit |
Return the number of trajectory points per time unit across all users. |
od_matrix |
Compute an Origin-Destination matrix from a trips DataFrame. |
od_metrics_per_area |
Compute per-area mobility metrics from a long-format OD DataFrame. |
fastmob.measures.collective.homes_per_location
homes_per_location(traj, *, start_night=22, end_night=7, datetime_col=None, lat_col=None, lng_col=None, uid_col=None)
Return the number of users whose home is at each distinct location.
The number of home locations at location \(j\) is computed as [PRS2016]_:
where \(h_u\) indicates the home location of individual \(u\)
(see :func:~fastmob.measures.individual.home_location) and \(U\)
is the set of all individuals.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
DataFrame - like
|
Trajectory dataframe; any Narwhals-compatible eager backend (pandas, polars, …). Must have datetime, latitude, and longitude columns. |
required |
start_night
|
int
|
Hour (0–23) at which the nighttime window begins. Default: 22. |
22
|
end_night
|
int
|
Hour (0–23) at which the nighttime window ends (exclusive). Default: 7. |
7
|
datetime_col
|
str or None
|
Explicit datetime column name. Auto-detected when None. |
None
|
lat_col
|
str or None
|
Explicit latitude column name. Auto-detected when None. |
None
|
lng_col
|
str or None
|
Explicit longitude column name. Auto-detected when None. |
None
|
uid_col
|
str or None
|
Explicit user-ID column name. Auto-detected when None. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame or DataFrame
|
One row per distinct home location with columns
|
Examples:
>>> import pandas as pd
>>> import fastmob
>>> url = fastmob.utils.constants.BRIGHTKITE_SAMPLE
>>> df = pd.read_csv(
... url,
... sep="\t",
... header=0,
... nrows=5000,
... names=["uid", "datetime", "lat", "lng", "location id"],
... )
>>> df["datetime"] = pd.to_datetime(df["datetime"], errors="coerce")
>>> df["location_id"] = df["location id"].astype("string")
>>> df = df.dropna(subset=["uid", "datetime", "lat", "lng"])[
... ["uid", "datetime", "lat", "lng", "location_id"]
... ]
>>> print(df.head().to_string(index=False))
uid datetime lat lng location_id
0 2010-10-16 06:02:04+00:00 39.891383 -105.070814 7a0f88982aa015062b95e3b4843f9ca2
0 2010-10-16 03:48:54+00:00 39.891077 -105.068532 dd7cd3d264c2d063832db506fba8bf79
0 2010-10-14 18:25:51+00:00 39.750469 -104.999073 9848afcc62e500a01cf6fbf24b797732f8963683
0 2010-10-14 00:21:47+00:00 39.752713 -104.996337 2ef143e12038c870038df53e0478cefc
0 2010-10-13 23:31:51+00:00 39.752508 -104.996637 424eb3dd143292f9e013efa00486c907
>>> from fastmob import homes_per_location
>>> result = homes_per_location(df)
>>> print(result.round({"lat": 3, "lng": 3}).head().to_string(index=False))
lat lng n_homes
39.891 -105.069 1
37.630 -122.411 1
39.739 -104.985 1
References
- [PRS2016] Pappalardo, L., Rinzivillo, S. & Simini, F. (2016) Human Mobility Modelling: exploration and preferential return meet the gravity model. Procedia Computer Science 83, 934-939, http://dx.doi.org/10.1016/j.procs.2016.04.188
See Also
visits_per_location : Total visit count per location across all users. home_location : Inferred home location from nighttime visits (individual measure).
fastmob.measures.collective.mean_square_displacement
mean_square_displacement(traj, *, days=0, hours=1, minutes=0, datetime_col=None, lat_col=None, lng_col=None, uid_col=None)
Return the mean square displacement (km²) across all users.
The mean squared displacement (MSD) measures the average deviation of position from a reference point over time [FS2002] [BHG2006] [SKWB2010]_:
where \(N\) is the number of individuals, \(r^{(i)}(0)\) is the reference position (first recorded point) of individual \(i\), and \(r^{(i)}(t)\) is their position at time offset \(t\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
DataFrame - like
|
Trajectory dataframe; any Narwhals-compatible eager backend (pandas, polars, …). Must have datetime, latitude, and longitude columns. |
required |
days
|
int
|
Days component of the time offset from each user's start time. Defaults to 0. |
0
|
hours
|
int
|
Hours component of the time offset. Defaults to 1. |
1
|
minutes
|
int
|
Minutes component of the time offset. Defaults to 0. |
0
|
datetime_col
|
str or None
|
Explicit datetime column name. Auto-detected when None. |
None
|
lat_col
|
str or None
|
Explicit latitude column name. Auto-detected when None. |
None
|
lng_col
|
str or None
|
Explicit longitude column name. Auto-detected when None. |
None
|
uid_col
|
str or None
|
Explicit user-ID column name. Auto-detected when None. |
None
|
Returns:
| Type | Description |
|---|---|
float
|
Mean square displacement in km². Returns 0.0 when the trajectory is empty or every user's displacement window is trivially at the start. |
Examples:
>>> import pandas as pd
>>> import fastmob
>>> url = fastmob.utils.constants.BRIGHTKITE_SAMPLE
>>> df = pd.read_csv(
... url,
... sep="\t",
... header=0,
... nrows=5000,
... names=["uid", "datetime", "lat", "lng", "location id"],
... )
>>> df["datetime"] = pd.to_datetime(df["datetime"], errors="coerce")
>>> df["location_id"] = df["location id"].astype("string")
>>> df = df.dropna(subset=["uid", "datetime", "lat", "lng"])[
... ["uid", "datetime", "lat", "lng", "location_id"]
... ]
>>> print(df.head().to_string(index=False))
uid datetime lat lng location_id
0 2010-10-16 06:02:04+00:00 39.891383 -105.070814 7a0f88982aa015062b95e3b4843f9ca2
0 2010-10-16 03:48:54+00:00 39.891077 -105.068532 dd7cd3d264c2d063832db506fba8bf79
0 2010-10-14 18:25:51+00:00 39.750469 -104.999073 9848afcc62e500a01cf6fbf24b797732f8963683
0 2010-10-14 00:21:47+00:00 39.752713 -104.996337 2ef143e12038c870038df53e0478cefc
0 2010-10-13 23:31:51+00:00 39.752508 -104.996637 424eb3dd143292f9e013efa00486c907
>>> from fastmob import mean_square_displacement
>>> result = mean_square_displacement(df)
>>> print(round(result, 3))
128.583
References
- [FS2002] Frenkel, D. & Smit, B. (2002) Understanding molecular simulation: From algorithms to applications. Academic Press, 196 (2nd Ed.), https://www.sciencedirect.com/book/9780122673511/understanding-molecular-simulation.
- [BHG2006] Brockmann, D., Hufnagel, L. & Geisel, T. (2006) The scaling laws of human travel. Nature 439, 462-465, https://www.nature.com/articles/nature04292
- [SKWB2010] Song, C., Koren, T., Wang, P. & Barabasi, A.L. (2010) Modelling the scaling properties of human mobility. Nature Physics 6, 818-823, https://www.nature.com/articles/nphys1760
fastmob.measures.collective.random_location_entropy
random_location_entropy(traj, *, datetime_col=None, lat_col=None, lng_col=None, uid_col=None)
Return the random entropy for each distinct location across all users.
Random location entropy is \(\log_2(n)\), where \(n\) is the number of
distinct users who visited the location. A location is a unique exact
(lat, lng) pair — matching the skmob convention.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
DataFrame - like
|
Trajectory dataframe; any Narwhals-compatible eager backend (pandas, polars, …). Must have datetime, latitude, and longitude columns. A user-ID column is optional; when absent all rows are treated as coming from a single individual (entropy will be 0 everywhere). |
required |
datetime_col
|
str or None
|
Explicit datetime column name. Auto-detected when None. |
None
|
lat_col
|
str or None
|
Explicit latitude column name. Auto-detected when None. |
None
|
lng_col
|
str or None
|
Explicit longitude column name. Auto-detected when None. |
None
|
uid_col
|
str or None
|
Explicit user-ID column name. Auto-detected when None. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame or DataFrame
|
One row per distinct |
Examples:
>>> import pandas as pd
>>> import fastmob
>>> url = fastmob.utils.constants.BRIGHTKITE_SAMPLE
>>> df = pd.read_csv(
... url,
... sep="\t",
... header=0,
... nrows=5000,
... names=["uid", "datetime", "lat", "lng", "location id"],
... )
>>> df["datetime"] = pd.to_datetime(df["datetime"], errors="coerce")
>>> df["location_id"] = df["location id"].astype("string")
>>> df = df.dropna(subset=["uid", "datetime", "lat", "lng"])[
... ["uid", "datetime", "lat", "lng", "location_id"]
... ]
>>> print(df.head().to_string(index=False))
uid datetime lat lng location_id
0 2010-10-16 06:02:04+00:00 39.891383 -105.070814 7a0f88982aa015062b95e3b4843f9ca2
0 2010-10-16 03:48:54+00:00 39.891077 -105.068532 dd7cd3d264c2d063832db506fba8bf79
0 2010-10-14 18:25:51+00:00 39.750469 -104.999073 9848afcc62e500a01cf6fbf24b797732f8963683
0 2010-10-14 00:21:47+00:00 39.752713 -104.996337 2ef143e12038c870038df53e0478cefc
0 2010-10-13 23:31:51+00:00 39.752508 -104.996637 424eb3dd143292f9e013efa00486c907
>>> from fastmob import random_location_entropy
>>> result = random_location_entropy(df)
>>> print(result.round({"random_entropy": 3}).head().to_string(index=False))
lat lng random_entropy
0.000000 0.000000 1.585
29.532220 -98.300914 0.000
29.942673 -90.064455 0.000
29.948116 -90.063436 0.000
29.948125 -90.063510 0.000
See Also
uncorrelated_location_entropy : Location entropy weighted by visitor frequency.
fastmob.measures.collective.uncorrelated_location_entropy
uncorrelated_location_entropy(traj, *, datetime_col=None, lat_col=None, lng_col=None, uid_col=None)
Return the uncorrelated entropy for each distinct location across all users.
For each location l, computes the Shannon entropy over the distribution
of visit probabilities:
where \(p(u, l)\) is the fraction of all visits to \(l\) that belong to
user \(u\). A location is a unique exact (lat, lng) pair.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
DataFrame - like
|
Trajectory dataframe; any Narwhals-compatible eager backend (pandas, polars, …). Must have datetime, latitude, and longitude columns. A user-ID column is optional; when absent all rows are treated as coming from a single individual (entropy will be 0 everywhere). |
required |
datetime_col
|
str or None
|
Explicit datetime column name. Auto-detected when None. |
None
|
lat_col
|
str or None
|
Explicit latitude column name. Auto-detected when None. |
None
|
lng_col
|
str or None
|
Explicit longitude column name. Auto-detected when None. |
None
|
uid_col
|
str or None
|
Explicit user-ID column name. Auto-detected when None. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame or DataFrame
|
One row per distinct |
Examples:
>>> import pandas as pd
>>> import fastmob
>>> url = fastmob.utils.constants.BRIGHTKITE_SAMPLE
>>> df = pd.read_csv(
... url,
... sep="\t",
... header=0,
... nrows=5000,
... names=["uid", "datetime", "lat", "lng", "location id"],
... )
>>> df["datetime"] = pd.to_datetime(df["datetime"], errors="coerce")
>>> df["location_id"] = df["location id"].astype("string")
>>> df = df.dropna(subset=["uid", "datetime", "lat", "lng"])[
... ["uid", "datetime", "lat", "lng", "location_id"]
... ]
>>> print(df.head().to_string(index=False))
uid datetime lat lng location_id
0 2010-10-16 06:02:04+00:00 39.891383 -105.070814 7a0f88982aa015062b95e3b4843f9ca2
0 2010-10-16 03:48:54+00:00 39.891077 -105.068532 dd7cd3d264c2d063832db506fba8bf79
0 2010-10-14 18:25:51+00:00 39.750469 -104.999073 9848afcc62e500a01cf6fbf24b797732f8963683
0 2010-10-14 00:21:47+00:00 39.752713 -104.996337 2ef143e12038c870038df53e0478cefc
0 2010-10-13 23:31:51+00:00 39.752508 -104.996637 424eb3dd143292f9e013efa00486c907
>>> from fastmob import uncorrelated_location_entropy
>>> result = uncorrelated_location_entropy(df)
>>> print(result.round({"uncorrelated_entropy": 3}).head().to_string(index=False))
lat lng uncorrelated_entropy
0.000000 0.000000 0.911
29.532220 -98.300914 0.000
29.942673 -90.064455 0.000
29.948116 -90.063436 0.000
29.948125 -90.063510 0.000
References
- [CML2011] Cho, E., Myers, S. A. & Leskovec, J. (2011) Friendship and mobility: user movement in location-based social networks. In Proceedings of the 17th ACM SIGKDD international conference on Knowledge discovery and data mining, 1082-1090, https://dl.acm.org/citation.cfm?id=2020579
See Also
random_location_entropy : Baseline entropy assuming uniform visitation across users.
fastmob.measures.collective.visits_per_location
visits_per_location(traj, *, datetime_col=None, lat_col=None, lng_col=None, uid_col=None)
Return the total number of visits for each distinct location.
Counts all trajectory rows (visits) per unique (lat, lng) pair across
all users. This is the population-level analogue of per-user
location_frequency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
DataFrame - like
|
Trajectory dataframe; any Narwhals-compatible eager backend (pandas, polars, …). Must have datetime, latitude, and longitude columns. |
required |
datetime_col
|
str or None
|
Explicit datetime column name. Auto-detected when None. |
None
|
lat_col
|
str or None
|
Explicit latitude column name. Auto-detected when None. |
None
|
lng_col
|
str or None
|
Explicit longitude column name. Auto-detected when None. |
None
|
uid_col
|
str or None
|
Explicit user-ID column name. Auto-detected when None (not used for aggregation, but retained for consistent preprocessing). |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame or DataFrame
|
One row per distinct |
Examples:
>>> import pandas as pd
>>> import fastmob
>>> url = fastmob.utils.constants.BRIGHTKITE_SAMPLE
>>> df = pd.read_csv(
... url,
... sep="\t",
... header=0,
... nrows=5000,
... names=["uid", "datetime", "lat", "lng", "location id"],
... )
>>> df["datetime"] = pd.to_datetime(df["datetime"], errors="coerce")
>>> df["location_id"] = df["location id"].astype("string")
>>> df = df.dropna(subset=["uid", "datetime", "lat", "lng"])[
... ["uid", "datetime", "lat", "lng", "location_id"]
... ]
>>> print(df.head().to_string(index=False))
uid datetime lat lng location_id
0 2010-10-16 06:02:04+00:00 39.891383 -105.070814 7a0f88982aa015062b95e3b4843f9ca2
0 2010-10-16 03:48:54+00:00 39.891077 -105.068532 dd7cd3d264c2d063832db506fba8bf79
0 2010-10-14 18:25:51+00:00 39.750469 -104.999073 9848afcc62e500a01cf6fbf24b797732f8963683
0 2010-10-14 00:21:47+00:00 39.752713 -104.996337 2ef143e12038c870038df53e0478cefc
0 2010-10-13 23:31:51+00:00 39.752508 -104.996637 424eb3dd143292f9e013efa00486c907
>>> from fastmob import visits_per_location
>>> result = visits_per_location(df)
>>> print(result.head().to_string(index=False))
lat lng n_visits
39.739154 -104.984703 340
37.630490 -122.411084 297
37.580304 -122.343679 297
37.584103 -122.366083 249
39.762146 -104.982480 232
References
- [PF2018] Pappalardo, L. & Simini, F. (2018) Data-driven generation of spatio-temporal routines in human mobility. Data Mining and Knowledge Discovery 32, 787-829, https://link.springer.com/article/10.1007/s10618-017-0548-4
See Also
homes_per_location : Number of users whose home is at each location. location_frequency : Per-user visit frequency (individual measure).
fastmob.measures.collective.visits_per_time_unit
visits_per_time_unit(traj, time_unit=None, *, freq='1h', datetime_col=None, lat_col=None, lng_col=None, uid_col=None)
Return the number of trajectory points per time unit across all users.
Groups all trajectory records by time bins of width freq and counts
the number of records (visits) in each bin. The result covers only bins
that contain at least one record.
The freq parameter follows pandas offset alias syntax (e.g. "1h",
"1D", "15min"). Results are returned using the same dataframe
backend as the input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
DataFrame - like
|
Trajectory dataframe; any Narwhals-compatible eager backend (pandas, polars, …). Must have datetime, latitude, and longitude columns. |
required |
time_unit
|
str or None
|
Alias for |
None
|
freq
|
str
|
Pandas-compatible offset alias for the time bin width. Default: |
'1h'
|
datetime_col
|
str or None
|
Explicit datetime column name. Auto-detected when None. |
None
|
lat_col
|
str or None
|
Explicit latitude column name. Auto-detected when None. |
None
|
lng_col
|
str or None
|
Explicit longitude column name. Auto-detected when None. |
None
|
uid_col
|
str or None
|
Explicit user-ID column name. Auto-detected when None. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame or DataFrame
|
One row per non-empty time bin with columns
|
Examples:
>>> import pandas as pd
>>> import fastmob
>>> url = fastmob.utils.constants.BRIGHTKITE_SAMPLE
>>> df = pd.read_csv(
... url,
... sep="\t",
... header=0,
... nrows=5000,
... names=["uid", "datetime", "lat", "lng", "location id"],
... )
>>> df["datetime"] = pd.to_datetime(df["datetime"], errors="coerce")
>>> df["location_id"] = df["location id"].astype("string")
>>> df = df.dropna(subset=["uid", "datetime", "lat", "lng"])[
... ["uid", "datetime", "lat", "lng", "location_id"]
... ]
>>> print(df.head().to_string(index=False))
uid datetime lat lng location_id
0 2010-10-16 06:02:04+00:00 39.891383 -105.070814 7a0f88982aa015062b95e3b4843f9ca2
0 2010-10-16 03:48:54+00:00 39.891077 -105.068532 dd7cd3d264c2d063832db506fba8bf79
0 2010-10-14 18:25:51+00:00 39.750469 -104.999073 9848afcc62e500a01cf6fbf24b797732f8963683
0 2010-10-14 00:21:47+00:00 39.752713 -104.996337 2ef143e12038c870038df53e0478cefc
0 2010-10-13 23:31:51+00:00 39.752508 -104.996637 424eb3dd143292f9e013efa00486c907
>>> from fastmob import visits_per_time_unit
>>> result = visits_per_time_unit(df)
>>> print(result.head().to_string(index=False))
datetime n_visits
2008-06-21 17:00:00+00:00 1
2008-06-22 01:00:00+00:00 1
2008-06-22 05:00:00+00:00 1
2008-06-22 17:00:00+00:00 1
2008-06-22 18:00:00+00:00 1
References
- [PRS2016] Pappalardo, L., Rinzivillo, S. & Simini, F. (2016) Human Mobility Modelling: exploration and preferential return meet the gravity model. Procedia Computer Science 83, 934-939, http://dx.doi.org/10.1016/j.procs.2016.04.188
fastmob.measures.collective.od_matrix(trips, origin_col=None, destination_col=None)
Compute an Origin-Destination matrix from a trips DataFrame.
Groups trips by (origin, destination) pairs and counts them. Returns a long-format DataFrame with one row per observed origin-destination pair, in the same backend as the input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trips
|
DataFrame - like
|
A DataFrame (pandas, polars, or any Narwhals-compatible backend) with at least two columns representing origin and destination areas. |
required |
origin_col
|
str or None
|
Column name for the origin area. Auto-detected if None. |
None
|
destination_col
|
str or None
|
Column name for the destination area. Auto-detected if None. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame or DataFrame
|
Long-format OD counts with columns
|
Examples:
>>> import pandas as pd
>>> from fastmob.measures.collective import od_matrix
>>> trips = pd.DataFrame(
... {
... "origin_area": ["A", "A", "A", "B", "B", "C"],
... "destination_area": ["A", "B", "B", "A", "C", "A"],
... }
... )
>>> result = od_matrix(trips)
>>> print(result.to_string(index=False))
origin_area destination_area count
A A 1
A B 2
B A 1
B C 1
C A 1
fastmob.measures.collective.od_metrics_per_area(od_df, origin_col=None, destination_col=None)
Compute per-area mobility metrics from a long-format OD DataFrame.
Takes the long-format OD DataFrame returned by :func:od_matrix and
computes MoveInside, InComing, OutGoing, and Total flows for each area.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
od_df
|
DataFrame - like
|
Long-format OD DataFrame as returned by :func: |
required |
origin_col
|
str or None
|
Column name for the origin area. Auto-detected if None. |
None
|
destination_col
|
str or None
|
Column name for the destination area. Auto-detected if None. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame or DataFrame
|
DataFrame with columns |
Examples:
>>> import pandas as pd
>>> from fastmob.measures.collective import od_matrix, od_metrics_per_area
>>> trips = pd.DataFrame(
... {
... "origin_area": ["A", "A", "A", "B", "B", "C"],
... "destination_area": ["A", "B", "B", "A", "C", "A"],
... }
... )
>>> od = od_matrix(trips)
>>> result = od_metrics_per_area(od)
>>> print(result.to_string(index=False))
area_code MoveInside InComing OutGoing Total
A 1 2 2 5
B 0 2 2 4
C 0 1 1 2