African Cities Density¶
In [1]:
import pandas as pd
import geopandas as gpd
from lets_plot import *
from lets_plot.geo_data import *
from lets_plot import tilesets
In [2]:
LetsPlot.setup_html()
In [3]:
def get_naturalearth_data(data_type, columns=None):
import shapefile
from shapely.geometry import shape
naturalearth_url = "https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/" + \
"data/naturalearth/{0}/data.shp?raw=true".format(data_type)
sf = shapefile.Reader(naturalearth_url)
gdf = gpd.GeoDataFrame(
[
dict(zip([field[0] for field in sf.fields[1:]], record))
for record in sf.records()
],
geometry=[shape(s) for s in sf.shapes()]
)
if columns is not None:
gdf = gdf[columns]
gdf.columns = [col.lower() for col in gdf.columns]
return gdf
In [4]:
world_gdf = get_naturalearth_data("admin_0_countries", columns=["NAME", "ADM0_A3", "CONTINENT"])
print(world_gdf.shape)
world_gdf.head()
Out[4]:
In [5]:
continent_gdf = world_gdf[world_gdf["continent"] == "Africa"].drop(columns=["continent"]).reset_index(drop=True)
continent_gdf["name"] = continent_gdf["name"].replace({
"Central African Rep.": "Central African Republic",
"Dem. Rep. Congo": "Democratic Republic of the Congo",
"Eq. Guinea": "Equatorial Guinea",
})
continent_gdf = continent_gdf[~continent_gdf["name"].isin(["Somaliland"])]
print(continent_gdf.shape)
continent_gdf.head()
Out[5]:
In [6]:
capitals_gdf = get_naturalearth_data("populated_places", columns=["NAME", "ADM0_A3", "ADM0CAP", "geometry"])
capitals_gdf = capitals_gdf[capitals_gdf["adm0cap"] == 1].drop(columns=["adm0cap"]).reset_index(drop=True)
print(capitals_gdf.shape)
capitals_gdf.head()
Out[6]:
In [7]:
continent_capitals_gdf = pd.merge(continent_gdf, capitals_gdf, on="adm0_a3", how='inner').drop(columns=["adm0_a3"])
continent_capitals_gdf.columns = ["country", "capital", "geometry"]
continent_capitals_gdf = continent_capitals_gdf.sort_values(by="country").reset_index(drop=True)
print(continent_capitals_gdf.shape)
continent_capitals_gdf.head()
Out[7]:
In [8]:
def geocode_country(name, capital, geometry):
result = geocode_cities().scope(name).ignore_not_found().get_centroids()[["found name", "geometry"]]
result.columns = ["name", "geometry"]
result = result.assign(is_capital = (result["name"] == capital))
if not result["is_capital"].any():
capital_row = gpd.GeoDataFrame({"name": [capital], "geometry": [geometry], "is_capital": True}, crs=result.crs)
result = pd.concat([result, capital_row], ignore_index=True)
return result.assign(country=name).sort_values(by=["is_capital", "name"])
gdf = pd.concat([
geocode_country(row["country"], row["capital"], row["geometry"])
for i, row in continent_capitals_gdf.iterrows()
]).reset_index(drop=True)
print(gdf.shape)
gdf.head()
Out[8]:
In [9]:
ggplot() + \
geom_livemap(data_size_zoomin=1, tiles=tilesets.LETS_PLOT_LIGHT) + \
geom_pointdensity(aes(fill="..scaled..",
stroke="is_capital", size="is_capital",
group=["country"]),
map=gdf, adjust=.15, shape=21, color="red", show_legend=False,
tooltips=layer_tooltips().title("@name\n@country")
.line("neighbours count|@..count..")
.line("is capital|@is_capital")) + \
scale_fill_viridis() + \
scale_manual("size", values=[1, 2]) + \
scale_manual("stroke", values=[0, .5]) + \
ggsize(800, 800)
Out[9]: