Search code examples
pandasmatplotlibcartopy

Plotting points on a map with calculated distance


This is my dataframe

import pandas as pd
from shapely.geometry import Point
import geopandas as gpd
from geopandas import GeoDataFrame
import matplotlib.pyplot as plt

d = {"STATE" : [ "NJ", "NJ", "NJ", "NJ"], 
     "CATEGORY": ["A", "B", "C", "D"],
     "LATITUDE" : [ 40.794856, 40.790176, 40.826762, 40.495150], 
     "LONGITUDE" : [ -74.149086, -74.255100, -74.101990, -74.442890]}
df = pd.DataFrame(data=d)

df.plot(kind="scatter", x="LONGITUDE", y="LATITUDE", alpha=0.4)
plt.show()

enter image description here

I want to calculate the distance between points based on category column:

A -> B

A -> C

A -> D

and connect the dots with distance displayed between them as a label

#creating point object so I can calculate distance bwtween coordinates
df["point"] = [Point(xy) for xy in zip(df['LONGITUDE'], df['LATITUDE'])]
#Formula I use for calculating distance between two points, this works when I have two seperate columns
#df['lat_long_diff'] = df.apply(lambda x : geodesic((x['LATITUDE_A'],x['LONGITUDE_A']),(x['LATITUDE_other_points'],x['LONGITUDE_other_points'])).miles,axis=1)

Also if I could include the Map of New Jersey as background it would be great, just the outline map would do.


Solution

  • import cartopy
    import cartopy.crs as ccrs
    import cartopy.feature as cfeature
    
    import matplotlib.pyplot as plt
    from matplotlib.text import Text
    
    import geopandas as gpd
    import pandas as pd
    
    import geopy.distance
    
    
    def calc_dist(point_a, point_b):
        return(geopy.distance.geodesic(point_a, point_b).miles)
    
    def draw_lines(x, y, p1 , p2):
        x1, x2 = x[p1], x[p2]
        y1, y2 = y[p1], y[p2]
        ax.plot([x1,x2],[y1,y2])
    
    
    d = {"STATE" : [ "NJ", "NJ", "NJ", "NJ"], 
         "CATEGORY": ["A", "B", "C", "D"],
         "LATITUDE" : [ 40.794856, 40.790176, 40.826762, 40.495150], 
         "LONGITUDE" : [ -74.149086, -74.255100, -74.101990, -74.442890]}
    
    df = pd.DataFrame(d)
    
    dist_list = []
    for i in [1,2,3]:
        dist = calc_dist((df.at[0, 'LATITUDE'], df.at[0, 'LONGITUDE']),
                        (df.at[i, 'LATITUDE'], df.at[i, 'LONGITUDE']))
        dist_list.append(dist)
    
    proj = ccrs.PlateCarree(central_longitude=0)
    
    fig, ax = plt.subplots(subplot_kw=dict(projection=proj), figsize=(16,16))
    ax.set_extent([df['LONGITUDE'].min()-1,
                   df['LONGITUDE'].max()+ 1,
                   df['LATITUDE'].min()- 1,
                   df['LATITUDE'].max()+1], 
                  crs=ccrs.PlateCarree())
    
    x = df['LONGITUDE'].tolist()
    y = df['LATITUDE'].tolist()
    
    ax.scatter(x, y)
    
    draw_lines(x, y, 0, 1)
    draw_lines(x, y, 0, 2)
    draw_lines(x, y, 0, 3)
    
    ax._add_text(Text(text=str(round(dist_list[0], 2)), x=-74.20, y=40.82))
    ax._add_text(Text(text=str(round(dist_list[1], 2)), x=-74.12, y= 40.8))
    ax._add_text(Text(text=str(round(dist_list[2], 2)), x=-74.29, y= 40.64))
    
    ax.add_feature(cfeature.STATES.with_scale('10m'), zorder=0)
    
    fig.canvas.draw()
    fig.tight_layout()
    
    plt.show()
    

    enter image description here