A package for geospatial flow analysis and visualization
Project description
GeoFlowKit
A Python package for handling and analyzing geographical flow data, extending pandas and geopandas with flow-specific operations.
Overview
GeoFlowKit provides FlowSeries and FlowDataFrame types, which are subclasses of pandas.Series and pandas.DataFrame respectively. They are designed to work with flow data consisting of origin-destination (OD) pairs, similar to how geopandas.GeoSeries and geopandas.GeoDataFrame work with geometries.
Installation
pip install geoflowkit
Or install from source:
pip install .
Dependencies
- shapely
- numpy
- pandas
- geopandas >= 1.0.1
- matplotlib
- scikit-learn
- tqdm
- numba
- networkx >= 2.6
Quick Start
Creating Flow Objects
import numpy as np
from geoflowkit import Flow, FlowSeries, FlowDataFrame
# Create a single Flow (origin-destination pair)
flow = Flow([[0, 0], [1, 1]])
# Access origin and destination points
print(flow.o) # POINT (0 0)
print(flow.d) # POINT (1 1)
Creating FlowSeries
# From a list of Flow objects
fs = FlowSeries([
Flow([[0, 0], [1, 1]]),
Flow([[1, 1], [2, 2]]),
Flow([[2, 2], [3, 3]])
], crs="EPSG:4326")
# From coordinate arrays using flows_from_od
from geoflowkit import flows_from_od
o_points = np.array([[0, 0], [1, 1], [2, 2]])
d_points = np.array([[1, 1], [2, 2], [3, 3]])
fs = flows_from_od(o_points, d_points, crs="EPSG:4326")
Creating FlowDataFrame
# Create a FlowDataFrame with attributes
data = {
'id': [1, 2, 3],
'value': [10, 20, 30],
'geometry': fs
}
fdf = FlowDataFrame(data, crs="EPSG:4326")
print(fdf)
Reading Data from Files
# Read from CSV (specify origin/destination columns)
fdf = read_csv(
'flow_data.csv',
use_cols=['ox', 'oy', 'dx', 'dy'],
crs='EPSG:4326'
)
# Read from GeoPackage
fdf = read_file('flow_data.gpkg', layer='flows')
Core Features
Flow Properties
# Access origin and destination points
origins = fdf.o # GeoSeries of origin points
destinations = fdf.d # GeoSeries of destination points
# Flow length and angle
lengths = fdf.length # Distance from origin to destination
angles = fdf.angle # Direction of flow (radians)
# Flow density and volume
density = fdf.density # Flows per unit area
volume = fdf.volume # Total bounding area
Flow Metrics
# Calculate pairwise distances between flows
from geoflowkit import pairwise_distances
dist_matrix = pairwise_distances(fdf, distance='max')
# Calculate local density of flow
from geoflowkit import k_neighbor_distances, snn_distance
k_dists = k_neighbor_distances(fdf, k=2)
snn_dist = snn_distance(fdf, k=8)
# Calculate disorder of flows
from geoflowkit import flow_entropy, flow_divergence
entropy = flow_entropy(fdf)
div = flow_divergence(fdf, n_directions=6)
Spatial Operations
# Clip flows within a polygon
clipped = fdf.clip(polygon_mask)
# Select flows within bounds
within_bounds = fdf.within(bounds_box)
# Calculate the distance with others
dist_series = fdf.distance(flow)
dist_series = fdf.distance(other_fdf)
Spatial Clustering Scale Detection (K/L Functions)
# Calculate K function for spatial clustering
from geoflowkit import k_func, l_func
r_list, kr_list = k_func(fdf, dr=0.1, k=1)
r_list, lr_list = l_func(fdf, dr=0.1, k=1)
# Local L function for individual flows
from geoflowkit import local_l_func
llrs = local_l_func(fdf, r=0.5)
Grid Aggregation
# Divide study area into grid and aggregate flows
gridded = fdf.to_grid(delta_x=0.1, delta_y=0.1)
Visualization
# Plot flows as arrows
ax = fdf.plot(kind='arrow', column='value')
# Plot FlowSeries
ax = fs.plot()
OD Matrix & MapTrix
from geoflowkit.visualization import ODMatrixVisualizer, MapTrixVisualizer
# OD Matrix heatmap (colour = flow count)
ODMatrixVisualizer(
origin_zones=border, zone_id_col='Name',
weight='count', cmap='OrRd',
).fit_plot(fdf, ax=ax)
# OD Matrix with proportional circles (size = flow length)
ODMatrixVisualizer(
origin_zones=border, zone_id_col='Name',
weight='count', size_weight='length',
).fit_plot(fdf, ax=ax)
# MapTrix — rotated matrix + origin/destination maps
MapTrixVisualizer(
origin_zones=border, zone_id_col='Name',
weight='count', size_weight='length',
out_title='Outflow', in_title='Inflow',
).fit_plot(fdf, figsize=(16, 9))
Flow Clustering
# K-medoid clustering
from geoflowkit import kmedoid
labels = kmedoid(fdf, n_clusters=5)
# DBSCAN clustering
from geoflowkit import dbscan
labels = dbscan(fdf, eps=0.5, min_samples=5)
# K-Means clustering (virtual flow centers)
from geoflowkit import kmeans
labels = kmeans(fdf, n_clusters=5, distance='max', random_state=42)
# Or use the class API to inspect cluster centers
from geoflowkit import KMeansFlow
km = KMeansFlow(n_clusters=5, distance='max', random_state=42).fit(fdf)
print(km.cluster_centers_) # FlowSeries of virtual flow centers
Community Detection
Community detection algorithms identify groups of closely connected zones in flow networks. These algorithms first build a flow network graph from the FlowDataFrame, then detect communities using modularity optimization.
# CNM (Clauset-Newman-Moore) algorithm
from geoflowkit import cnm
labels = cnm(fdf, zone_method='grid', cell_size=1000)
# Louvain algorithm
from geoflowkit import louvain
labels = louvain(fdf, zone_method='grid', cell_size=1000, seed=42)
# STOCS (Spatial Tabu Optimization for Community Structure)
from geoflowkit import stocs
labels = stocs(
fdf, zone_method='grid', cell_size=1000,
spatial_weight=0.5, tabu_tenure=15
)
Zone methods: 'grid' (regular grid), 'aggregate' (unique OD pairs), 'gdf' (external GeoDataFrame), 'custom' (user function).
# Custom zone function example
import numpy as np
def my_zones(fdf):
origins = np.array([[p.x, p.y] for p in fdf.o])
destinations = np.array([[p.x, p.y] for p in fdf.d])
o_zones = (origins[:, 0] > 0).astype(int) * 2 + (origins[:, 1] > 0).astype(int)
d_zones = (destinations[:, 0] > 0).astype(int) * 2 + (destinations[:, 1] > 0).astype(int)
zone_centroids = {i: (origins[o_zones == i].mean(axis=0)) for i in range(4) if (o_zones == i).any()}
return o_zones.astype(int), d_zones.astype(int), zone_centroids
labels = louvain(fdf, zone_method='custom', zone_func=my_zones)
Output: Flow-level labels where -1 indicates cross-community flows (origin and destination belong to different communities).
Manifold Learning (FTSNE)
from geoflowkit import FTSNE
# Global interpretability (separate O and D)
transformer = FTSNE(perplexity=200, learning_rate='auto')
X_embedded = transformer.fit_transform(
fdf, identity={'o': 0, 'd': 1}
)
# Local interpretability (union O and D)
X_embedded = transformer.fit_transform(
fdf, union={('o', 'd'): (0, 1)}
)
Location Centrality (I-index)
The I-index quantifies the irreplaceability of a location based on flows, combining flow volume and flow length into a single metric following the H-index principle.
from geoflowkit.spatial import i_index
# Calculate I-index for each zone
result = i_index(fdf, zones)
# Using origin points instead of destination
result = i_index(fdf, zones, od_type='o')
# With custom alpha parameter
result = i_index(fdf, zones, alpha=1000.0)
I-index definition: The I-index of a location is the maximum value of i such that at least i flows with a length of at least α × i meters have reached this location. Higher values indicate more irreplaceable locations that attract many long-distance flows.
Examples
Jupyter notebook examples are available in the examples/ folder:
- basic_usage.ipynb - Basic usage of Flow, FlowSeries, and FlowDataFrame
- clustering.ipynb - Flow clustering and community detection
- kl_function.ipynb - K/L functions for spatial clustering detection
- visualization.ipynb - OD Matrix, MapTrix, and FTSNE visualizations
- centrality.ipynb - I-index for location irreplaceability
API Reference
Classes
Flow: Geometry object representing an origin-destination pairFlowSeries: pandas Series subclass for storing Flow objectsFlowDataFrame: pandas DataFrame subclass with Flow geometry columnKMedoidFlow: K-medoid clustering for flow dataDBSCANFlow: DBSCAN clustering for flow dataKMeansFlow: K-Means clustering for flow data (virtual flow centers)CNMFlow: Clauset-Newman-Moore community detectionLouvainFlow: Louvain community detectionSTOCSFlow: Spatial Tabu Optimization for Community StructureFTSNE: A Variant of t-SNE for Flow DataODMatrixVisualizer: OD matrix heatmap visualizationMapTrixVisualizer: MapTrix layout (matrix + maps + guide lines)
Key Functions
flows_from_od(o, d, crs=None): Create FlowSeries from coordinate arraysflows_from_geometry(geometry, crs=None): Create FlowSeries from geometry objectsread_csv(file_path, use_cols, crs=None, **kwargs): Read flow data from CSVread_file(file_path, **kwargs): Read flow data from vector filepairwise_distances(fdf, distance='max', ...): Calculate flow distance matrixk_neighbor_distances(fdf, k, distance='max', ...): K-order nearest neighbor distancessnn_distance(fdf, k, ...): Shared nearest neighbor distanceflow_entropy(fdf, cell_area=None, ...): Flow space entropyflow_divergence(fdf, n_directions=6, ...): Flow directional entropyk_func(fdf, dr, k=1, distance='max', ...): K function for spatial clustering detectionl_func(fdf, dr, k=1, distance='max', ...): L function for spatial clustering detectionlocal_l_func(fdf, r, distance='max', ...): Local L function for individual flowskmedoid(fdf, n_clusters=5, ...): K-medoid clustering for flowsdbscan(fdf, eps=0.5, min_samples=5, ...): DBSCAN clustering for flowskmeans(fdf, n_clusters=8, distance='max', ...): K-Means clustering for flows (virtual flow centers)cnm(fdf, zone_method='grid', cell_size=..., ...): CNM community detectionlouvain(fdf, zone_method='grid', cell_size=..., seed=..., ...): Louvain community detectionstocs(fdf, zone_method='grid', cell_size=..., spatial_weight=0.5, ...): STOCS community detectioni_index(fdf, zones, alpha=None, od_type='d', ...): I-index for location irreplaceabilitysecond_order_density(fdf, ...): Second-order density of flowsFlowSeries / FlowDataFrame methods:plot(): Render flows as arrows using matplotlib quiverwithin(mask): Select flows whose origin and destination are both inside maskclip(mask): Clip flows to a mask polygondistance(other, distance='max', ...): Calculate distance to another flow or FlowSeriesto_grid(delta_x=None, delta_y=None, ...): Divide study area into grid and aggregate flows (FlowDataFrame only)to_crs(crs): Transform CRS of flowsset_crs(crs, allow_override=False): Set CRS without transforming geometries
License
GeoFlowKit is licensed under the MIT License.
Contact
For questions or feedback: djw@lreis.ac.cn
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file geoflowkit-0.3.0.tar.gz.
File metadata
- Download URL: geoflowkit-0.3.0.tar.gz
- Upload date:
- Size: 82.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f25cdd4ce19d89f94a723abb3f3b3cca2919d216ae08ece041f2057737dd6d5
|
|
| MD5 |
6de018daffa4770c53b9f334c7d589e0
|
|
| BLAKE2b-256 |
f9610945c3691a61b6131a02cdb67a95c1298c10ad9ea9aaa2a440b12cadf335
|
Provenance
The following attestation bundles were made for geoflowkit-0.3.0.tar.gz:
Publisher:
publish.yml on djw-easy/geoflowkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
geoflowkit-0.3.0.tar.gz -
Subject digest:
6f25cdd4ce19d89f94a723abb3f3b3cca2919d216ae08ece041f2057737dd6d5 - Sigstore transparency entry: 2067241999
- Sigstore integration time:
-
Permalink:
djw-easy/geoflowkit@f3c1bfd3dadeeac77e01b07ab2c4a077a07f6379 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/djw-easy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f3c1bfd3dadeeac77e01b07ab2c4a077a07f6379 -
Trigger Event:
push
-
Statement type:
File details
Details for the file geoflowkit-0.3.0-py3-none-any.whl.
File metadata
- Download URL: geoflowkit-0.3.0-py3-none-any.whl
- Upload date:
- Size: 96.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb089286a4f35c6b4388984fa85f36c71da31c85d99a5097c0b0efa134767407
|
|
| MD5 |
59b147ad6a87e636575c53b24bcf6565
|
|
| BLAKE2b-256 |
90c5da7432c8f1e91ad6da39a441c1fd0bf1e42302067125f1cfa588cea5891d
|
Provenance
The following attestation bundles were made for geoflowkit-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on djw-easy/geoflowkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
geoflowkit-0.3.0-py3-none-any.whl -
Subject digest:
cb089286a4f35c6b4388984fa85f36c71da31c85d99a5097c0b0efa134767407 - Sigstore transparency entry: 2067242222
- Sigstore integration time:
-
Permalink:
djw-easy/geoflowkit@f3c1bfd3dadeeac77e01b07ab2c4a077a07f6379 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/djw-easy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f3c1bfd3dadeeac77e01b07ab2c4a077a07f6379 -
Trigger Event:
push
-
Statement type: