Create colormap with specified RGB values - python

I want to create a colormap like heatmap but the colors are defined as a RGB values in a data.
Each cell contains specific color value which are needed to be plotted in the image.
I want to plot these values that looks like similar to this:
How to generate this kind of colormap without using matplotlib tables.
I have accomplished this using matplotlib table by taking reference from here:
matplotlib table color
But I want to implement this without using tables. Is these any method other than using matplotlib tables.

It wasn't a color bar, was it? If you can create an RGB relationship with the data, you can express it. I set 'c=colors', but I think it would be better to specify a column with RGB converted to hexadecimal.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.colors
data = [np.random.randn(50),np.random.randn(50),np.random.randint(1,5,(50,))]
fig = plt.figure(figsize=(10,7))
# RGB:[[100,125,200],[100,125,100],[100.25.50],[122,125,10],[100,25,201]]
# hex=(['#647dc8','#647d64','#641932','#7a7d0a'])
colors = ["#647dc8","#647d64","#641932","#7a7d0a","#ff19c9"]*10
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", colors)
im = plt.scatter(data[0], data[1], c=colors, linewidths=5, alpha=1.0)
plt.show()

Related

How to incorporate subplots option when plotting a data frame using Pandas-Bokeh?

I have a dataframe corresponding to a multivariate time series which I'd like to plot. Each channel would appear on its own set of axes, with all plots arranged vertically. I'd also like to add the interactive options available with Bokeh, including the ability to remove one channel from view by clicking on its label.
Without Bokeh, I can use subplots to get the separate "static" plots stacked vertically as follows:
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
A=np.random.rand(800,10)
df=pd.DataFrame(data=A,columns=['a','b','c','d','e','f','g','h','i','j'])
df.plot(subplots=True)
plt.show()
I can plot the 10 channels on one set of axes using Bokeh using this:
import numpy as np
import pandas as pd
pd.set_option('plotting.backend', 'pandas_bokeh')
A=np.random.rand(800,10)
df=pd.DataFrame(data=A,columns=['a','b','c','d','e','f','g','h','i','j'])
df.plot_bokeh(kind="line")
The resulting graph allows for zooming, panning, channel de-selection, etc. However all plots signals are plotted on the same set of axes, which I would rather not do.
I use this code snippet to plot my figures in a grid.
import pandas as pd
import pandas_bokeh
from bokeh.palettes import Dark2_5 as palette
def plot_grid(df: pd.DataFrame):
figs = []
color = itertools.cycle(palette)
for c in df.columns:
figs.append(df[c].plot_bokeh(show_figure=False, color=next(color)))
pandas_bokeh.plot_grid(figs, ncols=1, plot_width=1500)
The ncols parameter allows you to specify how many columns you want per row.
Hope this helps!

Retrieving Matplotlib Heatmap Colors

I am trying to retrieve the colors of each cell on a matplotlib heatmap, generated by the imshow() function, such as performed by the magic_function below:
import matplotlib.pyplot as plt
import numpy as np
hm = plt.imshow(np.random.rand(10, 10))
color_matrix = hm.magic_function() #returns matrix containing the RGB/Hex values of each cell
You are looking for the colormap that is used by the image created via imshow. Now of course you can reverse engineer how that colormap got into the image in the first place like the other answer suggests. That seems cumbersome and often enough isn't even possible.
So given an AxesImage (the object returned by imshow) or for that matter any other ScalarMappable, you get the colormap in use via .cmap. Since the data values are normalized to the range between 0..1, you need a normalization, which you get from the .norm attribute. Finally, you need the data, which you get from the .get_array() method.
The magic_function is hence a chain of three functions.
im = plt.imshow(np.random.rand(10, 10))
color_matrix = im.cmap(im.norm(im.get_array()))
color_matrix is now the (10, 10, 4)-shaped RGBA array of colors corresponding to the pixels in the image.
Building upon this answer, you need to understand the default color map chosen by matplotlib since you didn't provide one. The documentation states that it is the value of plt.rcParams["image.cmap"], so we use that.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cm as cm
from matplotlib.colors import Normalize
data = np.random.rand(10, 10)
cmap = cm.get_cmap(plt.rcParams["image.cmap"])
hm = plt.imshow(data)
norm = Normalize(vmin=data.min(), vmax=data.max())
rgba_values = cmap(norm(data))
The RGBA value of the upper left cell would then be rgba_values[0,0]

python matplotlib heatmap colorbar from transparent

How to implement python matplotlib heatmap colorbar like this?
plt.imshow(a,aspect='auto', cmap=plt.cm.gist_rainbow_r)
plt.colorbar()
This example from the matplotlib gallery shows some different ways to make custom colormaps, including transparency: https://matplotlib.org/examples/pylab_examples/custom_cmap.html
In your case, it looks like you want a modified version of the gist_rainbow colormap. You can achieve this by modifying the alpha channel as follows:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
# get colormap
ncolors = 256
color_array = plt.get_cmap('gist_rainbow')(range(ncolors))
# change alpha values
color_array[:,-1] = np.linspace(1.0,0.0,ncolors)
# create a colormap object
map_object = LinearSegmentedColormap.from_list(name='rainbow_alpha',colors=color_array)
# register this new colormap with matplotlib
plt.register_cmap(cmap=map_object)
# show some example data
f,ax = plt.subplots()
h = ax.imshow(np.random.rand(100,100),cmap='rainbow_alpha')
plt.colorbar(mappable=h)

Custom colour maps Matplotlib, make one value a prescribed colour

I have an array in python, using matplotlib, with floats ranging between 0 and 1.
I am displaying this array with imshow, I am trying to create a custom cmap, which is identical to Greens, however when a cell becomes 0 I would like to be able to map that value to red, and leave the rest of he spectrum unchanged.
If anyone more familiar with matplotlib would be able to help me I would greatly appreciate it!
For instance how would I edit this script so that the zero value in the matrix showed as red?
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
x = np.array([[0,1,2],[3,4,5],[6,7,8]])
fig = plt.figure()
cmap_custom = matplotlib.cm.Greens
plt.imshow( x, interpolation='nearest' ,cmap = cmap_custom)
plt.colorbar()
plt.show()
The colormaps in matplotlib allow you to set special colors for values that are outside of the defined range. In your case specify the color for values below the defined range with cmap_custom.set_under('r').
Then you also need to specify the lower end of the range: vmin=0.01 (just some value > 0).
Finally create the colorbar with plt.colorbar(extend='min').
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
x = np.array([[0,1,2],[3,4,5],[6,7,8]])
fig = plt.figure()
cmap_custom = matplotlib.cm.Greens
cmap_custom.set_under('r')
plt.imshow( x, interpolation='nearest' ,cmap = cmap_custom, vmin=0.01)
plt.colorbar(extend='min')
plt.show()

How to add legend to imshow() in matplotlib

I am using matplotlib
In plot() or bar(), we can easily put legend, if we add labels to them. but what if it is a contourf() or imshow()
I know there is a colorbar() which can present the color range, but it is not satisfied. I want such a legend which have names(labels).
For what I can think of is that, add labels to each element in the matrix, then ,try legend(), to see if it works, but how to add label to the element, like a value??
in my case, the raw data is like:
1,2,3,3,4
2,3,4,4,5
1,1,1,2,2
for example, 1 represents 'grass', 2 represents 'sand', 3 represents 'hill'... and so on.
imshow() works perfectly with my case, but without the legend.
my question is:
Is there a function that can automatically add legend, for example, in my case, I just have to do like this: someFunction('grass','sand',...)
If there isn't, how do I add labels to each value in the matrix. For example, label all the 1 in the matrix 'grass', labell all the 2 in the matrix 'sand'...and so on.
Thank you!
Edit:
Thanks to #dnalow, it's smart really. However, I still wonder if there is any formal solution.
I quote here a solution to a similar question, in case someone is still interested:
I suppose putting a legend for all values in a matrix only makes sense if there aren't too many of them. So let's assume you have 8 different values in your matrix. We can then create a proxy artist of the respective color for each of them and put them into a legend like this
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
# create some data
data = np.random.randint(0, 8, (5,5))
# get the unique values from data
# i.e. a sorted list of all values in data
values = np.unique(data.ravel())
plt.figure(figsize=(8,4))
im = plt.imshow(data, interpolation='none')
# get the colors of the values, according to the
# colormap used by imshow
colors = [ im.cmap(im.norm(value)) for value in values]
# create a patch (proxy artist) for every color
patches = [ mpatches.Patch(color=colors[i], label="Level {l}".format(l=values[i]) ) for i in range(len(values)) ]
# put those patched as legend-handles into the legend
plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0. )
plt.grid(True)
plt.show()
You could use matplotlib.pylab.text to add text to your plot and customize it to look like a legend
For example:
import numpy as np
import matplotlib.cm as cm
import matplotlib.pylab as plt
raw_data = np.random.random((100, 100))
fig, ax = plt.subplots(1)
ax.imshow(raw_data, interpolation='nearest', cmap=cm.gray)
ax.text(5, 5, 'your legend', bbox={'facecolor': 'white', 'pad': 10})
plt.show()
which gives you following
You can check out the matplotlib documentation on text for more details matplotlib text examples
I am just working on the same project to draw a land use map like your problem. Here is my solution following the answers above.
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
##arrayLucc is the array of land use types
arrayLucc = np.random.randint(1,4,(5,5))
## first you need to define your color map and value name as a dic
t = 1 ## alpha value
cmap = {1:[0.1,0.1,1.0,t],2:[1.0,0.1,0.1,t],3:[1.0,0.5,0.1,t]}
labels = {1:'agricultural land',2:'forest land',3:'grassland'}
arrayShow = np.array([[cmap[i] for i in j] for j in arrayLucc])
## create patches as legend
patches =[mpatches.Patch(color=cmap[i],label=labels[i]) for i in cmap]
plt.imshow(arrayShow)
plt.legend(handles=patches, loc=4, borderaxespad=0.)
plt.show()
This resolution doesn't seem very good but it can works. I am also looking for my other methods.
I guess you have to fake your legend, since it requires a line for creating the legend.
You can do something like this:
import pylab as pl
mycmap = pl.cm.jet # for example
for entry in pl.unique(raw_data):
mycolor = mycmap(entry*255/(max(raw_data) - min(raw_data)))
pl.plot(0, 0, "-", c=mycolor, label=mynames[entry])
pl.imshow(raw_data)
pl.legend()
Of cause this is not very satisfying yet. But maybe you can build something on that.
[edit: added missing parenthesis]

Categories