In my opinion, the most effective options geo information possesses is its functionality for 3D visualization. Nevertheless, because of the quantity of computational assets wanted for such calculations, it’s actually hardly ever carried out in python (typically JavaScript and its libraries used as options). In considered one of my earlier articles I shared six python packages which permit creation of lovely static and interactive maps, but solely in 2D house.
Immediately I wish to bridge this hole and examine with you a extremely fashionable and environment friendly framework for high-performance web-based visualizations deck.jl, which additionally has a python library PyDeck.
To correctly discover its capabilities in python we want a big geospatial dataset. An ideal candidate for that’s Los Angeles Crime Data 2010–2020 dataset from Kaggle. Fortunately, it has an open license, so we might freely use it for our functions.
The authors distribute two csv information, which we’re going to merge into one filtering out all of the columns besides longitude and latitude (coordinates of the locations the place the crimes have been carried out).
🐍The complete python code: GitHub.
import numpy as np
import pandas as pd
import xarray as xr
import geopandas as gpd
import random
import mathimport matplotlib.pyplot as plt
from shapely import Level
import cartopy
import cartopy.crs as ccrs
import cartopy.characteristic as cfeature
import warnings
warnings.filterwarnings('ignore')
current = pd.read_csv('./LA Crimes/Crime_Data_from_2020_to_Present.csv')[['LAT', 'LON']]
previous = pd.read_csv('./LA Crimes/Crime_Data_from_2010_to_2019.csv')[['LAT', 'LON']]
df = pd.concat([old, recent])
df = df[(df.LON!=0) & (df.LAT!=0)] #zeros are Nans in accordance with meta information
After loading it in pandas, I wish to carry out a static 2D visualization utilizing cartopy, simply to have a dependable reference. If we merely plot the info, we’ll get a bunch of knowledge factors, that are of no use for us.
As an alternative let’s carry out spatial interpolation utilizing the NN methodology (you may learn extra about it in my different article).
Mainly, it signifies that we switch sparse observations right into a geographical grid (PyDeck will do the identical factor, on this case it may be referred to as information aggregation).
def coords(x,y, base=0.01):
x, y = spherical(base * math.ceil(abs(x)/base),2), spherical(base * math.ceil(y/base),2)
return (y,x)def NN(information, LAT, LON):
array = np.zeros((LAT.form[0], LON.form[0]),dtype=int)
onGrid = information.apply(lambda row: coords(row.LAT, row.LON, 0.01), axis = 1).value_counts()
for coor in onGrid.index:
lon_idx, lat_idx = np.the place(LON==coor[0]), np.the place(LAT==coor[1])
array[lat_idx,lon_idx] = int(onGrid[coor])
return array
After the algorithm is completed (you’ll want to attend for a while, since we now have greater than 2 mil rows to course of), we are able to wrap its outcomes into an xarray dataset and map it.
LAT, LON = np.arange(spherical(df.LAT.min()), spherical(df.LAT.max()), 0.01).astype(np.float32), np.arange(spherical(df.LON.min()), spherical(df.LON.max()), 0.01).astype(np.float32)
crimes = NN(df, LAT, LON)
ds = xr.Dataset(
{'Crimes': (['lat', 'lon'], crimes)},
coords={'lat': LAT, 'lon': LON})fig, ax = plt.subplots(subplot_kw=dict(projection=ccrs.PlateCarree()), figsize=(16, 9))
ds.Crimes.plot(ax=ax, cmap='Reds')
ax.set_extent([-118.9, -118.1, 33.6, 34.5 ], crs=ccrs.PlateCarree())
ax.gridlines(draw_labels=True,linewidth=2, colour='black', alpha=0.5, linestyle='--')
ax.add_feature(cfeature.BORDERS, edgecolor='black', linewidth=1)
ax.add_feature(cfeature.COASTLINE, edgecolor='black', linewidth=1)
ax.add_feature(cartopy.characteristic.RIVERS, edgecolor='blue', linewidth=0.5)
states_provinces = cfeature.NaturalEarthFeature(
class='cultural', identify='admin_1_states_provinces',
scale='10m', facecolor='none')
plt.present()
From my perspective, it seems to be good and informative, but when it’s worthwhile to promote this venture to somebody, you’ll likely fail with such a map xD. So let’s pip set up PyDeck and see what it could actually do for us!
The primary kind of map layer I discovered stunning was the Hexagon layer. It is advisable specify it whereas creating the Layer variable in PyDeck. There are a number of different essential parameters for us:
- radius (the radius of hexagon in meters, i.e. spatial decision in m);
- elevation_scale (scale issue for bins, the larger the worth, the upper the hexagons);
- elevation_range (min and max top);
- pickable (interactively displaying the values);
- extruded (cell elevation).
layer = pdk.Layer(
'HexagonLayer',
df,
get_position=['LON', 'LAT'],
radius=500, #bin radius
auto_highlight=True,
elevation_scale=50, #scale issue for bins (the larger - the upper)
elevation_range=[0, 3000],
pickable=True,
extruded=True,#cell elevation
)
The second variable we have to create is the View state. We have to feed it with:
- longitude and latitude;
- zoom (preliminary zoom);
- min_zoom and max_zoom;
- bearing (left/proper view angle);
- pitch (up/down view angle).
view_state = pdk.ViewState(
longitude=-118.3,
latitude=34.4,
zoom=8,
min_zoom=6,
max_zoom=15,
bearing=-20,#left/proper angle
pitch=20, #up/down angle
)
Since we now have a big dataset, google colab doesn’t show all of the dataset, so you could have two choices:
- Pattern N rows from the dataset;
- Save the map to html and open it in your browser.
In case you decide the second, you’ll get this:
To be sincere, I really like how hexagons look, however I’ve by no means seen them in any scientific paper/presentation/lecture, so I’d advocate utilizing them consciously.
Now let’s attempt to create an analogous visualization, however utilizing columns. However on this case we might want to cross to the perform the xarray dataset we created earlier and specify the colour and the variable to visualise:
layer = pdk.Layer(
'ColumnLayer',
ds.to_dataframe().reset_index(),
get_position=['lon', 'lat'],
get_elevation='Crimes',
elevation_scale=10,
radius=200,
get_fill_color=['Crimes', 220],
pickable=True,
extruded=True,
)
In essence, scatter plot is a cloud of factors, however the authors of PyDeck developed cylinders, which look fairly distinctive:
layer = pdk.Layer(
'ColumnLayer',
df[:15000],
get_position=['LON', 'LAT'],
auto_highlight=True,
get_radius=200, # Radius is given in meters
get_fill_color=[180, 0, 200, 140], # Set an RGBA worth for fill
pickable=True)
A extremely cool factor about PyDeck is that as plotly, geemap, folium and different interactive mapping instruments, it permits customers to vary the basemap, which means you may design a map in accordance with your venture’s context:
r = pdk.Deck(layers=[layer],
initial_view_state=view_state,
map_style=pdk.map_styles.LIGHT, # ‘gentle’, ‘darkish’, ‘highway’, ‘satellite tv for pc’, ‘dark_no_labels’, and ‘light_no_labels
)
The subsequent characteristic, which I discover tremendous useful, is altering the interactive information description. By placing a cursor on a column/hexagon/level you may get meta data, however typically it seems to be slightly bit preposterous. However in PyDeck you may simply overcome it:
r = pdk.Deck(layers=[layer],
initial_view_state=view_state,
"html": "<b>Variety of crimes:</b> {elevationValue}",
"fashion": {
"backgroundColor": "yellow",
"colour": "black"
}
},
)
Lastly, probably the most wonderful characteristic of this library is your means to vary the viewing angle on the map just by clicking the precise button of your mouse:
from ipywidgets import HTMLtextual content = HTML(worth='Transfer the perspective')
def filter_by_bbox(row, west_lng, east_lng, north_lat, south_lat):
return west_lng < row['lng'] < east_lng and south_lat < row['lat'] < north_lat
def filter_by_viewport(widget_instance, payload):
west_lng, north_lat = payload['data']['nw']
east_lng, south_lat = payload['data']['se']
filtered_df = df[df.apply(lambda row: filter_by_bbox(row, west_lng, east_lng, north_lat, south_lat), axis=1)]
r.deck_widget.on_click(filter_by_viewport)
I undoubtedly take pleasure in PyDeck and plan to dive deeper into the deck.jl framework. With tremendous straightforward and intuitive syntax it permits customers to construct spectacular visualizations being energy-efficient. Python limits the capabilities of this bundle loads, so take a look at their gallery, it’s thoughts blowing, particularly their experimental GlobalView characteristic…
Hopefully this text was informative and insightful for you!
===========================================
All my publications on Medium are free and open-access, that’s why I’d actually admire for those who adopted me right here!
P.s. I’m extraordinarily enthusiastic about (Geo)Knowledge Science, ML/AI and Local weather Change. So if you wish to work collectively on some venture pls contact me in LinkedIn.
🛰️Observe for extra🛰️