Achille G
Achille G

Reputation: 817

Geopandas can't plot the right country

I'm trying to plot a trip on the map of France but I can't plot only the map of France (see image), could someone help me with this ? I believe this may be an issue with the crs from the contextily library but I didn't find any information on the web Here is a reproducible example...

import pandas as pd
import geopandas as gpd

from shapely.geometry import Point
import shapely

import matplotlib.pyplot as plt
from matplotlib.colors import to_hex
import seaborn as sns

import contextily as ctx

def main():
    gdf = pd.DataFrame() 
    gdf["longitudes"] = [5.8127891, 5.2250324]
    gdf["latitudes"] = [46.1965678, 46.2051192]

    gdf["geometry"] = gpd.points_from_xy(gdf["longitudes"], gdf["latitudes"])
    
    gdf = gpd.GeoDataFrame(gdf, crs= {"init": "epsg:4326"})
        
    world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
    
    france = world.query('name == "France"')

    # Make the plot
    fig, ax = plt.subplots(figsize=(4,5))

    #ax = gdf.plot(figsize=(10, 5))

    # Plot the state outlines
    france.boundary.plot(color='black', linewidth=0.5, ax=ax)


    # Modify projection to match what contextily uses
    gdf = gdf.to_crs(epsg=3857)

    part1 = shapely.geometry.LineString(
        gdf['geometry'].values)
    

    linegdf = gpd.GeoDataFrame(
    {'geometry': [part1]}
    )


    c = to_hex(sns.light_palette('green')[0])

    linegdf.plot(
        color=c,
        linewidth=3,
        ax=ax
    )

    print(len(gdf))

    # Plot points colored by day
    gdf.plot(
        cmap=sns.light_palette('green', as_cmap=True),
        ax=ax,
        markersize=50,
        edgecolor='black', linewidth=0.5,
        zorder=1000 # force the points to be the top layer of the plot
    )

    # Add basemap
    ctx.add_basemap(ax=ax)

    # Remove axes
    ax.set_axis_off()

    plt.show()

main()

What I'm left with

Any help is much appreciated !

Upvotes: 0

Views: 1628

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31236

Two points

  • France is a MutliPolygon, where part is in Antartica. Have excluded this from geometry
  • need to be very consistent with CRS. Additionally best not to use legacy for of referencing CRS {"init": "epsg:4326"}
import matplotlib.pyplot as plt
from matplotlib.colors import to_hex
import seaborn as sns
import pandas as pd
import geopandas as gpd
import shapely.geometry
import contextily as ctx


def main():
    gdf = pd.DataFrame()
    gdf["longitudes"] = [5.8127891, 5.2250324]
    gdf["latitudes"] = [46.1965678, 46.2051192]

    gdf["geometry"] = gpd.points_from_xy(gdf["longitudes"], gdf["latitudes"])

    # lets project CRS early...
    gdf = gpd.GeoDataFrame(gdf, crs="epsg:4326").to_crs("EPSG:3857")

    world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))

    france = world.query('name == "France"')
    # just mainland france, not antartica... plus CRS
    france = (
        france["geometry"]
        .apply(
            lambda mp: shapely.geometry.MultiPolygon(
                [p for p in mp.geoms if p.bounds[1] > 20]
            )
        )
        .to_crs("EPSG:3857")
    )

    # Make the plot
    fig, ax = plt.subplots(figsize=(4, 5))

    # Plot the state outlines
    ax = france.boundary.plot(color="black", linewidth=0.5, ax=ax)

    part1 = shapely.geometry.LineString(gdf["geometry"].values)

    linegdf = gpd.GeoDataFrame({"geometry": [part1]})

    c = to_hex(sns.light_palette("green")[0])

    linegdf.plot(color=c, linewidth=3, ax=ax)

    # Plot points colored by day
    gdf.plot(
        cmap=sns.light_palette("green", as_cmap=True),
        ax=ax,
        markersize=50,
        edgecolor="black",
        linewidth=0.5,
        zorder=1000,  # force the points to be the top layer of the plot
    )

    # Add basemap
    ctx.add_basemap(ax=ax)

    # Remove axes
    ax.set_axis_off()

    plt.show()


main()

enter image description here

Upvotes: 2

Related Questions