I want to use grid to achieve this. However, I have encountered many problems with color fills and axes。I refer to an example in the official matplotlib documentation that is very close to this image
(the link), but it's still a little different.
here is the picture
It's my fault, the picture is too large,it's difficult to implement quickly. So i choose a part of the original image, here:
Try with plotting custom heatmaps. For example
from matplotlib import colors
import matplotlib.pyplot as plt
import numpy as np
cmap = colors.ListedColormap(['cyan','gray','white','yellow'])
bounds=[0, 10, 20, 30, 40]
norm = colors.BoundaryNorm(bounds, cmap.N)
data=np.array([[5,15,5],[25,32,6],[15,31,25]])
heatmap = plt.pcolor(data, cmap=cmap, norm=norm)
plt.show()
a value between 0-10 will give cyan colour, 10-20 will give gray as so on. So make your data array accodingly.
Result :
I've solved this qusetion by using seaborn.
from matplotlib import colors
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
cmap = colors.ListedColormap(['white','gray','blue','yellow'])
bounds=[0, 2, 4, 6, 8]
norm = colors.BoundaryNorm(bounds, cmap.N)
data = np.array([[1,1,1,1,7,7,7,7], [1,1,1,1,1,1,1,5], [1,1,1,1,1,1,1,5], [1,1,1,3,1,1,1,5], [1,1,1,1,1,1,3,5]])
ax = sns.heatmap(data, cmap=cmap, norm=norm, linewidths=.5,
linecolor='black', square=True, cbar=False)
sns.plt.annotate('S', (1.4, 3.4))
sns.plt.show()
result
Related
I found this tutorial on how to do a watermark but I cannot figure out how to put it behind my plotted data.
https://www.tutorialspoint.com/how-to-plot-a-watermark-image-in-matplotlib
Changing zorder has no impact because I think it is being drawn on the entire figure. I would like to have a subdued logo behind my data which is always centered in the figure so I don't really want to plot an image as a data point because then it would move as it is panned/zoomed.
Setting the zorder to a negative value works for me. However, you also need to make the facecolor of the axes transparent:
import numpy as np
import matplotlib.cbook as cbook
import matplotlib.image as image
import matplotlib.pyplot as plt
with cbook.get_sample_data('logo2.png') as file:
im = image.imread(file)
fig, ax = plt.subplots()
fig.figimage(im, 10, 10, zorder=-1, alpha=.5)
ax.plot(np.sin(10 * np.linspace(0, 1)), '-o', ms=20,
alpha=0.7, mfc='orange')
ax.set_facecolor('none')
plt.show()
hope everyone is doing well in these hard times. I am trying to plot the track of a cyclone with scatter points over a base map. I was successful in plotting it, but what I want is want the scatter plots to be plotted with different colors according to a certain range, such as less than 17 knots in color black, between 17-27 knts blue, between 27-33 cyan, between 33-47 green, between 47-63 orange and greater than 120 knots red. I was able to plot the scatter with various colors but not according to the range. So if anyone can help me by showing me how to do it it will be much appreciated.
The code I have used and the plot generated is attached below.
import os
os.environ["PROJ_LIB"] = "C:\\Utilities\\Python\\Anaconda\\Library\\share"; #fixr
from mpl_toolkits.basemap import Basemap
import proplot as plot
import pandas as pd
import matplotlib as mpl
m=Basemap()
#dt = pd.read_excel('E:/tracks.xlsx',sheet_name='amp')
data = [25,25,35,40,45,55,70,80,100,120,125,130,125,115,105,100,95]
lon= [87,86.3,86.3,86.1,86,86,86,86.1,86.3,86.2,86.3,86.5,86.7,86.9,87,87.2,87.5]
lat= [10.4,10.9,10.9,11.1,11.4,11.5,12,12.5,13.2,13.4,14,14.9,15.6,16.5,17.4,18.4,19.1]
cmap = mpl.cm.get_cmap('bwr')
norm = mpl.colors.Normalize(vmin=25, vmax=130)
colors = cmap(norm(data))
x,y=m(lon,lat)
fig, axs = plot.subplots(ncols=1, axwidth=3, proj='merc', proj_kw={'lon_0': 180})
axs.format(
latlim=(0, 30), lonlim=(50, 100),linewidth=1,
gridlinewidth=0,coast=True, latlines=30, lonlines=60,)
l=axs.scatter(x,y,c=colors,s=10)
fig.colorbar(colors)
You can use ListedColormap with BoundaryNorm to generate your custom discrete colorbar. Here is an example using cartopy:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import matplotlib as mpl
data = [25,25,35,40,45,55,70,80,100,120,125,130,125,115,105,100,95]
lon = [87,86.3,86.3,86.1,86,86,86,86.1,86.3,86.2,86.3,86.5,86.7,86.9,87,87.2,87.5]
lat = [10.4,10.9,10.9,11.1,11.4,11.5,12,12.5,13.2,13.4,14,14.9,15.6,16.5,17.4,18.4,19.1]
cmap = mpl.colors.ListedColormap(['blue', 'cyan', 'green', 'orange'])
norm = mpl.colors.BoundaryNorm([17, 27, 33, 47, 63], cmap.N)
cmap.set_under('black')
cmap.set_over('red')
colors = cmap(norm(data))
fig, ax = plt.subplots(figsize=(10, 5), subplot_kw={'projection': ccrs.PlateCarree()})
ax.coastlines() # draw coastlines
ax.set_extent([65, 95, 5, 25]) # zoom into India
ax.scatter(lon, lat, s=20, c=colors, cmap=cmap, norm=norm, transform=ccrs.Geodetic())
fig.colorbar(mpl.cm.ScalarMappable(norm, cmap), extend='both')
Using this code, I don't know how to customize the colorbar. The colormaps on this webiste can't satisfy me.
shade = m.contourf(Lon,Lat,TBB,np.arange(-90, -20, 10),extend='both',cmap=plt.cm.get_cmap('jet'))
m.colorbar(shade)
I want to draw a picture like this with obvious colorbar. So, what should I do?
You can define your own colormap using matplotlib.colors.LinearSegmentedColormap() or matplotlib.colors.ListedColormap() and use it for your plot.
Example:
import numpy as np; np.random.seed(0)
import matplotlib.pyplot as plt
import matplotlib.colors
x = np.arange(0,25)
a = np.random.randint(0,130, size=(25,25))-115
a = np.sort(a).reshape(25,25)
colors = ["#eaa941", "#efef39", "#53a447", "#3b387f", "#48a2ba"]
cmap= matplotlib.colors.ListedColormap(colors)
cmap.set_under("crimson")
cmap.set_over("w")
norm= matplotlib.colors.Normalize(vmin=-100,vmax=-0)
fig, ax = plt.subplots()
im = ax.contourf(x,x,a, levels=[-100,-80,-60,-40,-20,0],
extend='both',cmap=cmap, norm=norm)
fig.colorbar(im, extend="both")
plt.show()
Looks a lot like the spectral colormap, which is given on the matplotlib page..
Seaborn offers a function called color_palette, which allows you to easily create new color_palettes for plots.
colors = ["#67E568","#257F27","#08420D","#FFF000","#FFB62B","#E56124","#E53E30","#7F2353","#F911FF","#9F8CA6"]
color_palette = sns.color_palette(colors)
I want to transform color_palette to a cmap, which I can use in matplotlib, but I don't see how I can do this.
Sadly just functions like "cubehelix_palette","light_palette",… have an "as_cmap" paramater. "color_palette" doesn't, unfortunately.
You have to convert a list of colors from seaborn palette to color map of matplolib (thx to #RafaelLopes for proposed changes):
import seaborn as sns
import matplotlib.pylab as plt
import numpy as np
from matplotlib.colors import ListedColormap
# construct cmap
flatui = ["#9b59b6", "#3498db", "#95a5a6", "#e74c3c", "#34495e", "#2ecc71"]
my_cmap = ListedColormap(sns.color_palette(flatui).as_hex())
N = 500
data1 = np.random.randn(N)
data2 = np.random.randn(N)
colors = np.linspace(0,1,N)
plt.scatter(data1, data2, c=colors, cmap=my_cmap)
plt.colorbar()
plt.show()
Most seaborn methods to generate color palettes have an optional argument as_cmap which by default is False. You can use to directly get a Matplotlib colormap:
import seaborn as sns
import matplotlib.pylab as plt
import numpy as np
# construct cmap
my_cmap = sns.light_palette("Navy", as_cmap=True)
N = 500
data1 = np.random.randn(N)
data2 = np.random.randn(N)
colors = np.linspace(0,1,N)
plt.scatter(data1, data2, c=colors, cmap=my_cmap)
plt.colorbar()
plt.show()
The first answer is somehow correct but way too long with a lot of unnecessary information. The correct and short answer is:
To convert any sns.color_palette() to a matplotlib compatible cmap you need two lines of code
from matplotlib.colors import ListedColormap
cmap = ListedColormap(sns.color_palette())
Just an additional tip - if one wants a continuous colorbar/colormap, adding 256 as the number of colors required from Seaborn colorscheme helps a lot.
cmap = ListedColormap(sns.color_palette("Spectral",256))
I wanted to change the font size for a heatmap colorbar.
The following is my code:
import seaborn as sns
import matplotlib.pyplot as plt
from numpy import arange
x = arange(25).reshape(5, 5)
cmap = sns.diverging_palette(220, 20, sep=20, as_cmap=True)
ax = sns.heatmap(x, cmap=cmap)
plt.show()
I was able to change the tick labels with plt.tick_params(axis='both', labelsize=20). However, the colorbar font size does not change.
Is there a way to do that?
You can use matplotlib.axes.Axes.tick_params with labelsize.
For example, your plot with labelsize 20:
import seaborn as sns
import matplotlib.pyplot as plt
from numpy import arange
x = arange(25).reshape(5, 5)
cmap = sns.diverging_palette(220, 20, sep=20, as_cmap=True)
ax = sns.heatmap(x, cmap=cmap)
# use matplotlib.colorbar.Colorbar object
cbar = ax.collections[0].colorbar
# here set the labelsize by 20
cbar.ax.tick_params(labelsize=20)
plt.show()
I refered to the following answer:
- Using matplotlib.colorbar.Colorbar object
- Setting parameter
You can change the font scale with the seaborn.set() method setting the font_scale param to the scale you want, see more in seaborn documentation.
For example, your plot with scale 3:
import seaborn as sns
import matplotlib.pyplot as plt
from numpy import arange
# here set the scale by 3
sns.set(font_scale=3)
x = arange(25).reshape(5, 5)
cmap = sns.diverging_palette(220, 20, sep=20, as_cmap=True)
ax = sns.heatmap(x, cmap=cmap)
plt.show()
If you set the following, it will increase all text in the graph by a factor of two. However, if you immediately set the tick_params to lower right after, you will be left with just the font size of the colorbar increased.
sns.set(font_scale=2)
sns.heatmap(df, vmin=0, vmax=1, center=0.5)
heatmap.tick_params(labelsize=15)
sns.set(font_scale=1)
Don't forget to set the font_scale back :)