I'm having an issue with using cartopy in Python to plot the longitude and latitude of datapoints onto a world map.
However, the resulting world map is inverted but the data points are correct.
Adding the link to the dataFrame here as it is too large to display here (clean_countryData1)
# Plotting world map
! pip install cartopy
import matplotlib.pyplot as plt
import seaborn as sb
import cartopy.crs as ccrs
import cartopy.crs as ccrs
import cartopy.feature as cf
fig = plt.figure(figsize = (40, 20))
ax = fig.add_subplot(1, 1, 1,
projection = ccrs.PlateCarree())
ax.add_feature(cf.LAND)
ax.add_feature(cf.OCEAN)
ax.add_feature(cf.COASTLINE)
ax.add_feature(cf.BORDERS, linestyle = ':')
ax.add_feature(cf.LAKES, alpha = 0.5)
ax.add_feature(cf.RIVERS)
ax.set_title("Aircraft Accidents Around The World",
fontsize = 40)
sb.scatterplot(x = "LONGITUDE", y = "LATITUDE",
data = clean_countryData,
hue = "INJURY_SEVERITY",
alpha = 0.8,
marker = 'o',
s = 100,
color = "red",
transform = ccrs.PlateCarree())
plt.show()
Related
I am plotting using contourf in which color schemes are user-defined and colorbar is extended at both ends. But same color is appearing for the last two-interval at both ends (as in the figure). I am expecting different colors as defined for each interval. The script is
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np
from mpl_toolkits.basemap import Basemap
val=np.random.random((37,97))
theLats=np.arange(0,90.3,2.5)
theLons=np.arange(-50,190.3,2.5)
xx, yy = np.float32(np.meshgrid(theLons, theLats))
m = Basemap(projection='cyl', resolution='l',
llcrnrlat=5, llcrnrlon=65,
urcrnrlat=40, urcrnrlon=100)
m.drawcoastlines()
parallels = np.arange(-90.,90,20.)
m.drawparallels(parallels,labels=[1,0,0,0],fontsize=10)
meridians = np.arange(0.,360.,20.)
m.drawmeridians(meridians,labels=[0,0,0,1],fontsize=10)
x, y = m(xx, yy)
colors=['red', 'darkorange', 'goldenrod','gold', 'lightgreen','limegreen','aquamarine','aqua','blue']
cm = matplotlib.colors.ListedColormap(colors)
clevs = np.arange(0.2,.8,0.1)
cs = m.contourf(x,y,val,clevs,cmap=cm,extend='both')
cbar = m.colorbar(cs,location='right',pad="5%")
plt.show()
I'm unsure if this is possible, but I'm essentially trying to isolate the Arctic circle latitude (60N) in an orthographic map AND maintain the ellipsoid, not have the zoomed in image be a rectangle/square.
Here is what I have:
fig = plt.figure(figsize=[20, 10])
ax1 = plt.subplot(1, 1, 1, projection=ccrs.Orthographic(0, 90))
for ax in [ax1]:
ax.coastlines(zorder=2)
ax.stock_img()
ax.gridlines()
This gives the north polar view I want, but I would like for it to stop at 60N.
Current yield
To get a zoom-in and square extent of an orthographic map, You need to plot some control points (with .scatter, for example) or specify correct extent in projection coordinates (more difficult). Here is the code to try.
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
fig = plt.figure(figsize=[8, 8])
lonlatproj = ccrs.PlateCarree()
my_projn = ccrs.Orthographic(central_longitude=0,central_latitude=90)
ax1 = plt.subplot(1, 1, 1, projection=my_projn)
# set `lowlat` as lower limits of latitude to plot some points
# these points will determine the plot extents of the map
lowlat = 60 + 2.8 # and get 60
lons, lats = [-180,-90,0,90], [lowlat,lowlat,lowlat,lowlat]
# plot invisible points to get map extents
ax1.scatter(lons, lats, s=0, color='r', transform=lonlatproj)
#ax1.stock_img() #uncomment to get it plotted
ax1.coastlines(lw=0.5, zorder=2)
ax1.gridlines(lw=2, ec='black', draw_labels=True)
Method 2: By specifying correct extent in projection coordinates
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
fig = plt.figure(figsize=[8, 8])
lonlatproj = ccrs.PlateCarree()
my_projn = ccrs.Orthographic(central_longitude=0,central_latitude=90)
ax1 = plt.subplot(1, 1, 1, projection=my_projn)
# These 2 lines of code grab extents in projection coordinates
_, y_min = my_projn.transform_point(0, 60, lonlatproj) #(0.0, -3189068.5)
x_max, _ = my_projn.transform_point(90, 60, lonlatproj) #(3189068.5, 0)
# prep extents of the axis to plot map
pad = 25000
xmin,xmax,ymin,ymax = y_min-pad, x_max+pad, y_min-pad, x_max+pad
# set extents with prepped values
ax1.set_extent([xmin,xmax,ymin,ymax], crs=my_projn) # data/projection coordinates
ax1.stock_img()
ax1.coastlines(lw=0.5, zorder=2)
# plot other layers of data here using proper values of zorder
# finally, plot gridlines
ax1.gridlines(draw_labels=True, x_inline=False, y_inline=True,
color='k', linestyle='dashed', linewidth=0.5)
plt.show()
Method 3 Plot the map with circular boundary
The runnable code:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import matplotlib.path as mpath
import numpy as np
r_limit = 3214068.5 #from: ax.get_ylim() of above plot
# some settings
lonlatproj = ccrs.PlateCarree()
my_projn = ccrs.Orthographic(central_longitude=0, central_latitude=90)
fig = plt.figure(figsize=[8, 8])
ax = plt.subplot(1, 1, 1, projection=my_projn)
# add bluemarble image
ax.stock_img()
# add coastlines
ax.coastlines(lw=0.5, color="black", zorder=20)
# draw graticule (of meridian and parallel lines)
gls = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree(), lw=3, color="gold",
y_inline=True, xlocs=range(-180,180,30), ylocs=range(-80,91,10))
# add extra padding to the plot extents
r_extent = r_limit*1.0001
ax.set_xlim(-r_extent, r_extent)
ax.set_ylim(-r_extent, r_extent)
# Prep circular boundary
circle_path = mpath.Path.unit_circle()
circle_path = mpath.Path(circle_path.vertices.copy() * r_limit,
circle_path.codes.copy())
#set circle boundary
ax.set_boundary(circle_path)
#hide frame
ax.set_frame_on(False) #hide the rectangle frame
plt.show()
The codes below put dots on the specific points on the earth map.
num_samples = 1250000
indices = np.random.choice(df.index, num_samples)
df_x = df.df_longitude[indices].values
df_y = df.df_latitude[indices].values
sns.set_style('white')
fig, ax = plt.subplots(figsize=(11, 12))
ax.scatter(df_x, df_y, s=5, color='red', alpha=0.5)
ax.set_xlim([-74.10, -73.60])
ax.set_ylim([40.85, 40.90])
ax.set_title('coordinates')
Is there any way to put these dots on a map instead of this white background?
Please have a look at the picture below:
geopandas provides an API that makes this quite easy. Here is an example, where the map is zoom into the continent of Africa:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import geopandas
df = pd.DataFrame(
{'Latitude': np.random.uniform(-20,10, 100),
'Longitude': np.random.uniform(40,20, 100)})
gdf = geopandas.GeoDataFrame(
df, geometry=geopandas.points_from_xy(df.Longitude, df.Latitude))
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
ax = world[world.continent == 'Africa'].plot(color='white', edgecolor='black')
# We can now plot our ``GeoDataFrame``.
gdf.plot(ax=ax, color='red')
plt.show()
The result:
I am plotting a shape file with Geopandas. Additionally im Adding Points of a dataframe (see picture). Now im trying to add a legend (at the right of the original plot) for the point. I dont really know how to do that!
Plot
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import geopandas as gpd
import test
variable = 'RTD_rtd'
df = test.getdataframe()
gdf = gpd.GeoDataFrame(
df, geometry=gpd.points_from_xy(df.NP_LongDegree, df.NP_LatDegree))
fp = "xxx"
map_df = gpd.read_file(fp)
ax = map_df.plot(color='white', edgecolor='black', linewidth=0.4, figsize= (10,10))
gdf.plot(column=variable, ax=ax, cmap='Reds', markersize=14.0, linewidth=2.0)
plt.show()
One Idea was to add a simple legend. I want something looking better. Maybe something similar to whats done in this tutorial: Tutorial
I followed the example that you referred to and this is the concise version. It would have been better if you could have shared a bit of your dataset 'df'. It seems that you want to have a colorbar which fig.colorbar generates.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import geopandas as gpd
import test
from shapely.geometry import Point
df = pd.read_csv('london-borough-profiles.csv', header=0)
df = df[['Area name','Population density (per hectare) 2017']]
fp = 'London_Borough_Excluding_MHW.shp'
map_df = gpd.read_file(fp)
gdf = map_df.set_index('NAME').join(df.set_index('Area name'))
variable = 'Population density (per hectare) 2017'
vmin, vmax = 120, 220
fig, ax = plt.subplots(1, figsize=(10, 6))
gdf.plot(column=variable, cmap='Blues', ax = ax, linewidth=0.8, edgecolor='0.8')
ax.axis('off')
ax.set_title('Population density (per hectare) 2017', fontdict={'fontsize': '25', 'fontweight' : '3'})
ax.annotate('Source: London Datastore, 2014',xy=(0.1, .08), xycoords='figure fraction', horizontalalignment='left', verticalalignment='top', fontsize=12, color='#555555')
sm = plt.cm.ScalarMappable(cmap='Blues', norm=plt.Normalize(vmin=vmin, vmax=vmax))
sm._A = []
cbar = fig.colorbar(sm)
You can add this into your solution and for this you have to set label for each plot
plt.legend()
I'm plotting some filled contours with Cartopy and Matplotlib. The data is on a latitude/longitude grid, and when plotting on a cartopy projection, a white line runs down the middle of the figure, or wherever I set "central_longitude" into in ccrs.PlateCarree()
Here is a quick setup that shows what I'm talking about. Using the code:
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
lon = np.arange(0, 360, 1)
lat = np.arange(-90, 90, 1)
data = np.zeros((180, 360))
fig = plt.figure()
ax = plt.subplot(projection=ccrs.PlateCarree())
ax.contourf(lon, lat, data)
ax.add_feature(cfeature.COASTLINE.with_scale('50m'))
plt.show()
Which produces the image:
Is there a way to remove this white line?
You should use cartopy.util.add_cyclic_point so that contourf sees the data as continuous in the x-direction and the white line will disappear:
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.util import add_cyclic_point
lon = np.arange(0, 360, 1)
lat = np.arange(-90, 90, 1)
data = np.zeros((180, 360))
data, lon = add_cyclic_point(data, coord=lon)
fig = plt.figure()
ax = plt.subplot(projection=ccrs.PlateCarree())
ax.contourf(lon, lat, data)
ax.add_feature(cfeature.COASTLINE.with_scale('50m'))
plt.show()