0

I have some code that plots a map with markers that represent a given pair of longitude and latitude (as a point).

df = pd.read_csv("geo.csv", delimiter=';', skiprows=0, low_memory=False)
geometry = [Point(xy) for xy in zip(df['longitude'], df['latitude'])]
gdf = GeoDataFrame(df, geometry=geometry)   

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
gdf.plot(ax=world.plot(figsize=(10, 6)), marker='o', color='red', markersize=15);

Is it possible to plot a map with only a latitude (OR longitude) "as a line"? How would I do that?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
till31
  • 33
  • 3

2 Answers2

0

There are lots of way to do this! Here are a few...

Using matplotlib: matplotlib.pyplot.grid

One would be to add gridlines at specific lat/lons. You're just using matplotlib (i.e., not cartopy with a specific projection), so the way to do this is to set specific major and minor tick locations, then draw lines with matplotlib.pyplot.grid. See, e.g. How to add a grid line at a specific location in a matplotlib plot?:

import matplotlib.pyplot as plt
import geopandas as gpd
na = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
fig, ax = plt.subplots()
na.plot(ax=ax)
ax.set_ylim(20, 50)
ax.set_xlim(-130, -60)
# set latitude lines as major axis ticks
ax.set_yticks([23, 30, 41], minor=False)
ax.yaxis.grid(True, which='major')

map of land covering the continental United States with horizontal ticks and lines at

Using cartopy: cartopy.mpl.geoaxes.GeoAxes.gridlines

Another option is to use cartopy in your plotting ot manage projections and to add gridlines using cartopy.mpl.geoaxes.GeoAxes.gridlines. This is similar to the matplotlib option, but allows easy projection management:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import geopandas as gpd
na = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
fig, ax = plt.subplots(subplot_kw={'projection': ccrs.Orthographic(-95, 35)})
na.plot(ax=ax, transform=ccrs.PlateCarree())
ax.set_extent([-150, -40, 10, 60], crs=ccrs.PlateCarree())
# set latitude lines to be transformed into the axis's projection
ax.gridlines(ylocs=[23, 30, 41], xlocs=[]);

similar figure, but with latitudes following a curved contour line on the Orthographic projection

By manually drawing lines with matplotlib.pyplot.plot

Another option is simply to draw lines using matplotlib.pyplot.plot.html. In this case, you need to decide what your [(x1, y1), (x2, y2)] points are. The simplest version of this is to use the x or y limits of the current axis:

import matplotlib.pyplot as plt
import geopandas as gpd

# set up plot
na = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
fig, ax = plt.subplots()
na.plot(ax=ax)
ax.set_ylim(20, 50)
ax.set_xlim(-130, -60)

# draw line using the (x1, x2) from xlim
xbounds = ax.get_xlim()
ax.plot(xbounds, [23, 23], color='grey')
ax.plot(xbounds, [30, 30], color='green')
ax.plot(xbounds, [41, 41], color='black')

enter image description here

Michael Delgado
  • 13,789
  • 3
  • 29
  • 54
0

Another approach is construct LineString for each latitude and longitude and plot them. If you only want one then just construct the lines you want.

import geopandas as gpd
from geopandas import GeoDataFrame
import pandas as pd
from shapely.geometry import Point, LineString

# simulate a CSV to be able to use question code
p_ = gpd.read_file(gpd.datasets.get_path("naturalearth_cities")).sample(
    5, random_state=42
)
pd.DataFrame({"latitude": p_.geometry.y, "longitude": p_.geometry.x}).to_csv(
    "geo.csv", sep=";"
)

df = pd.read_csv("geo.csv", delimiter=";", skiprows=0, low_memory=False)
geometry = [Point(xy) for xy in zip(df["longitude"], df["latitude"])]
gdf = GeoDataFrame(df, geometry=geometry)

world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
ax = gdf.plot(ax=world.plot(figsize=(10, 6)), marker="o", color="red", markersize=40)

# construct linestrings for points
gdf_l = pd.concat(
    [
        gpd.GeoDataFrame(
            geometry=df["latitude"].apply(lambda l: LineString([[-180, l], [180, l]])),
            crs="epsg:4326",
        ),
        gpd.GeoDataFrame(
            geometry=df["longitude"].apply(lambda l: LineString([[l, -90], [l, 90]])),
            crs="epsg:4326",
        ),
    ]
)
gdf_l.plot(ax=ax, color="yellow")

enter image description here

Also works with interactive map:

m = gdf.set_crs("epsg:4326").explore(style_kwds={"radius":8}, color="red")
gdf_l.explore(m=m, color="yellow")
Rob Raymond
  • 29,118
  • 3
  • 14
  • 30