Skip to content

Commit

Permalink
dexplore as extension class
Browse files Browse the repository at this point in the history
  • Loading branch information
knaaptime committed Jan 2, 2025
1 parent 7864cb1 commit c2a1dae
Showing 1 changed file with 115 additions and 4 deletions.
119 changes: 115 additions & 4 deletions geosnap/visualize/mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
from warnings import warn

import contextily as ctx
import geopandas as gpd
import mapclassify.classifiers as classifiers
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from mapclassify.util import get_color_array
from matplotlib import colormaps
from matplotlib.animation import ArtistAnimation, PillowWriter
Expand All @@ -19,10 +21,110 @@
schemes[classifier.lower()] = getattr(classifiers, classifier)


__all__ = ["animate_timeseries", "gif_from_path", "plot_timeseries", "dexplore"]
__all__ = ["animate_timeseries", "gif_from_path", "plot_timeseries", "_dexplore"]


# these methods
@pd.api.extensions.register_dataframe_accessor("gvz")
class GeosnapAccessor:
def __init__(self, pandas_obj):
self._validate(pandas_obj)
self._obj = pandas_obj

@staticmethod
def _validate(obj):
# verify there is a column latitude and a column longitude
if not isinstance(obj, gpd.GeoDataFrame):
raise AttributeError("must be a geodataframe")

def explore(
self,
column=None,
cmap=None,
scheme=None,
k=6,
categorical=False,
elevation=None,
extruded=False,
elevation_scale=1,
alpha=1,
layer_kwargs=None,
map_kwargs=None,
classify_kwargs=None,
nan_color=[255, 255, 255, 255],
color=None,
wireframe=False,
):
"""explore a dataframe using lonboard and deckgl
Parameters
----------
gdf : geopandas.GeoDataFrame
dataframe to visualize
column : str, optional
name of column on dataframe to visualize on map, by default None
cmap : str, optional
name of matplotlib colormap to , by default None
scheme : str, optional
name of a classification scheme defined by mapclassify.Classifier, by default
None
k : int, optional
number of classes to generate, by default 6
categorical : bool, optional
whether the data should be treated as categorical or continuous, by default
False
elevation : str or array, optional
name of column on the dataframe used to extrude each geometry or an array-like
in the same order as observations, by default None
extruded : bool, optional
whether to extrude geometries using the z-dimension, by default False
elevation_scale : int, optional
constant scaler multiplied by elevation valuer, by default 1
alpha : float, optional
alpha (opacity) parameter in the range (0,1) passed to
mapclassify.util.get_color_array, by default 1
layer_kwargs : dict, optional
additional keyword arguments passed to lonboard.viz layer arguments (either
polygon_kwargs, scatterplot_kwargs, or path_kwargs, depending on input
geometry type), by default None
map_kwargs : dict, optional
additional keyword arguments passed to lonboard.viz map_kwargs, by default None
classify_kwargs : dict, optional
additional keyword arguments passed to `mapclassify.classify`, by default None
nan_color : list-like, optional
color used to shade NaN observations formatted as an RGBA list, by
default [255, 255, 255, 255]
color : str or array-like, optional
_description_, by default None
wireframe : bool, optional
whether to use wireframe styling in deckgl, by default False
Returns
-------
lonboard.Map
a lonboard map with geodataframe included as a Layer object.
"""
return _dexplore(
self._obj,
column,
cmap,
scheme,
k,
categorical,
elevation,
extruded,
elevation_scale,
alpha,
layer_kwargs,
map_kwargs,
classify_kwargs,
nan_color,
color,
wireframe,
)


def dexplore(
def _dexplore(
gdf,
column=None,
cmap=None,
Expand Down Expand Up @@ -94,7 +196,9 @@ def dexplore(
from lonboard import viz
from lonboard.colormap import apply_categorical_cmap, apply_continuous_cmap
except ImportError as e:
raise ImportError from e('you must have the lonboard package installed to use this function')
raise ImportError(
"you must have the lonboard package installed to use this function"
) from e
if cmap is None:
cmap = "Set1" if categorical else "viridis"
if map_kwargs is None:
Expand Down Expand Up @@ -132,8 +236,12 @@ def dexplore(
if categorical:
color_array = _get_categorical_cmap(gdf[column].values, cmap)
elif scheme is None:
# minmax scale the column first, matplotlib needs 0-1
transformed = (gdf[column] - np.nanmin(gdf[column])) / (
np.nanmax(gdf[column]) - np.nanmin(gdf[column])
)
color_array = apply_continuous_cmap(
values=gdf[column], cmap=colormaps[cmap], alpha=alpha
values=transformed, cmap=colormaps[cmap], alpha=alpha
)
else:
color_array = get_color_array(
Expand Down Expand Up @@ -163,6 +271,9 @@ def dexplore(


def _get_categorical_cmap(categories, cmap):
# this already sits inside a conditional import from lonboard
from lonboard.colormap import apply_categorical_cmap

colors = colormaps[cmap].colors
colors = (np.array(colors) * 255).astype(int)
unique_cats = np.unique(categories)
Expand Down

0 comments on commit c2a1dae

Please sign in to comment.