Change color of bar plot in Python - python

I have three sets of histogram plot displayed by group. In this setting, I would like to differentiate each group by color.
For example, cubicle - red, hallway - blue, office - green. Any advice?
Here's my current code:
df_mean['mean'].hist(by=df_mean['type'])

Have you tried passing color parameter to hist?
plt.hist(x, color='r')

You can set a color for each histogram after you have created the figure with df.hist(), like in this example:
import numpy as np # v 1.19.2
import pandas as pd # v 1.1.3
import matplotlib.pyplot as plt # v 3.3.2
# Create random dataset
rng = np.random.default_rng(seed=12345) # random number generator
df = pd.DataFrame(dict(area_type = np.repeat(['cubicle', 'hallway', 'office'], [9, 10, 12]),
mean = np.append(rng.uniform(low=100, high=1400, size=9),
rng.exponential(scale=500, size=22))))
# Plot grid of histograms using pandas df.hist (note that df.plot.hist
# does not produce the same result, it seems to ignore the 'by' parameter)
grid = df['mean'].hist(by=df['area_type'])
colors = ['red', 'blue', 'green']
# Loop through axes contained in grid and list of colors
for ax, color in zip(grid.flatten(), colors):
# Loop through rectangle patches representing the histogram contained in ax
for patch in ax.patches:
patch.set_color(color)
# Change size of figure
plt.gcf().set_size_inches(8, 6)
plt.show()
Instead of manually picking colors, you could also pick colors automatically from a chosen colormap (in this case a qualitative colormap is appropriate), like this:
# Select colormap properties
cmap_name = 'Accent' # enter any colormap name (see whole list by running plt.colormaps())
ncolors = df['area_type'].nunique()
# Extract list of colors that span the entire gradient of the colormap
cmap = plt.cm.get_cmap(cmap_name)
colors = cmap(np.linspace(0, 1, ncolors))
# Create plot like in previous example
grid = df['mean'].hist(by=df['area_type'])
for ax, color in zip(grid.flatten(), colors):
for patch in ax.patches:
patch.set_color(color)
plt.gcf().set_size_inches(8, 6)
plt.show()

Related

How to assign colors to values in a seaborn heatmap

I have a data frame with 15 rows and 15 columns and the values are whole numbers in the range(0-5).
I use this data frame to create multiple heatmaps by filtering the data.
In the heatmap, I want to assign particular colors to every value so that even if the number of unique values in the data frame varies for every heatmap, the colors remain consistent for every assigned value.
Using the fixed color code, I want to use a single legend key for all the heat maps.
How can I assign colors with a dictionary?
cmap_dict = {0:'#FFFFFF',1:'#ff2a00', 2:'#ff5500', 3:'#ff8000', 4:'#ffaa00', 5:'#ffd500'}
heat_map = sns.heatmap(df,square=False,yticklabels=True,xticklabels=False,cmap=cmap1,vmin=0,vmax=5,cbar=False, annot=False)
If you set vmin and vmax the mapping from numbers to colors will always be the same, also when some values are missing from the data.
Some ideas:
Use a ListedColormap with the given list of 6 colors
Set vmin=-0.5, vmax=5.5 to have the values 0,1,2,3,4,5 nicely at the center of each color.
As seaborn by default makes the colorbar border invisible, and one of the colors is white, the colorbar border could be turned visible.
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import seaborn as sns
import pandas as pd
import numpy as np
cmap_dict = {0: '#FFFFFF', 1: '#ff2a00', 2: '#ff5500', 3: '#ff8000', 4: '#ffaa00', 5: '#ffd500'}
cmap = ListedColormap([cmap_dict[i] for i in range(6)])
df = pd.DataFrame(np.random.randint(0, 6, size=(15, 15)), index=[*'abcdefghijklmno'])
ax = sns.heatmap(data=df, cmap=cmap, vmin=-0.5, vmax=5.5, yticklabels=True, xticklabels=False)
for spine in ax.collections[0].colorbar.ax.spines.values():
spine.set_visible(True) # show the border of the colorbar
plt.tight_layout()
plt.show()

How to plot different shades of a color for each point in a scatter plot in matplotlib?

I am trying to plot a scatter plot where each point in the scatter plot should correspond to a particular shade of a given color of my choice. The mpl documentation states that if I set something like:
color = '0.7'
it gives me a shade of grey with that scaled intensity of 0.7. I am reading the intensity of the colours from an array with values between 0 and 1 and each value corresponds to the intensity of that point in the scatter plot. My code below is as follows:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import math
tsne_embeddings = np.load("tsne_embeddings.npy")
labels = np.load('labels.npy')
weights = np.load('weights.npy')
# Scale the weights from 0 to 1
max_weight = max(weights)
min_weight = min(weights)
weights = (weights - min_weight)/(max_weight - min_weight)
print(tsne_embeddings.shape)
x = list(tsne_embeddings[:,0])
y = list(tsne_embeddings[:,1])
labels = list(labels)
weights = np.round(weights,decimals=2)
weights = (np.exp(weights) - 1)/(np.exp(1) - 1)
weights = list(weights)
print(min(weights),max(weights))
for i, shade in enumerate(weights):
plt.scatter(x[i],y[i],color=shade,marker = '+')
plt.show()
I am scaling those weights exponentially hoping for a better variation.
So, essentially, my questions are:
How do I change the color to say shades of blue or red or green as opposed to just greyscale?
Is the approach which I follow for greyscale correct?
Thank you!
To make your approach work for shades of grey, you need to convert the value to a string, so plt.scatter(..., color=str(shade)).
The more standard way of working with matplotlib would be to directly use the weights, without rescaling them to the range 0 to 1, use a colormap, and calling scatter directly with the arrays. The weights go into the c= parameter. For grey values this would be plt.scatter(x, y, c=weights, cmap='Greys', marker='+'). An additional feature of matplotlib is that with this information it can automatically create a colorbar mapping the grey values to the corresponding weight. If only one scatter plot is created, plt.colorbar() without parameters will show this colorbar.
Similar colormaps exist of 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds', ... See the official doc with a complete list. If the range between light and dark goes the wrong way, appending '_r' to the name will use the opposite color range (so, 'Greys' goes from white to black, while 'Greys_r' goes from black to white).
Here is a working example using the values from 1 to 10 for the three arrays:
from matplotlib import pyplot as plt
import numpy as np
x = np.arange(1, 11)
y = np.arange(1, 11)
weights = np.arange(1, 11)
plt.scatter(x, y, c=weights, cmap='Greys', marker='+')
plt.colorbar()
plt.show()
You can use colormaps in python to generate different shades of blue green etc.
https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html
I am using Blues color map here
import matplotlib.pyplot as plt
import matplotlib as mpl
norm = mpl.colors.Normalize(vmin=min(weights), vmax=max(weights))
cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.Blues)
for i, xi in enumerate(x):
plt.scatter(x[i],y[i],color=cmap.to_rgba(i+1),marker = '+')
plt.show()

ListedColormap for identifying grid squares in matplotlib.pyplot.grid in python

How to reference or identify specific grid squares in a grid created using matplotlib.pyplot in python? I've used ListedColorMap to do this but I don't understand how to change the grid squares color to different colors and how ListedColormaps work?
Here is my code :
import matplotlib as mpl
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
import numpy as np
import itertools
N = 15
# making an empty data set
data = np.ones((N, N))
fig = plt.figure() # creates the figure
ax = fig.gca()
# fill in some sample data
data[6] = 1
# make color map
my_cmap = mpl.colors.ListedColormap(['g', 'b'])
ax.set_xticks(np.arange(-10, 0, 1))
ax.set_yticks(np.arange(-10, 0, 1))
for t in range(N + 1):
ax.axhline(t, lw=2, color='k', zorder=5)
ax.axvline(t, lw=2, color='k', zorder=5)
# draw the boxes
ax.imshow(data, interpolation='none', cmap=my_cmap, extent=[0, N, 0, N],
zorder=0)
# turn off the axis labels
ax.axis('on')
plt.show()
To set a color for some specific squares on the grid, first you need to make sure that the data for those locations are different from the others. For example, if you'd like the color the first row first two columns and second row first two columns, you'd do the following:
# Your data variable starts of having 1's at every location.
# To be able to see different colors, change the data
# at those locations. Here we set the data to 2. It could be
# any number different from 1.
data[0][0] = 2
data[0][1] = 2
data[1][0] = 2
data[1][1] = 2
The above helps you change colors for specific squares on the grid.
If you'd like to specify the colors that your grid's display, you have to specify them in the colors argument in matplotlib.colors.ListedColormap(colors, name='from_list', N=None).
# In this case, 'w' or white will be used for all the 1's in data.
# 'b' or blue will be used for all the 2's and 'r' or red for all the 3's.
# If you want to add new data, you can make it use new colors by adding
# more colors to the colors list.
# If you add new data but not new colors, the last color will be selected
# for the new data.
my_cmap = mpl.colors.ListedColormap(['w', 'b', 'r'])
Reference: ListedColorMap
Reference: colors - Matplotlib

Matplotlib Scatter plot change color based on value on list

I'm quite new to matplotlib and i would like to know how we can change color of points on a scatter plot based on the value in a list.
In fact, I have a 2-D array that I want to plot and a list with the same number of rows containing, for each point, the color we want to use.
#Example
data = np.array([4.29488806,-5.34487081],
[3.63116248,-2.48616998],
[-0.56023222,-5.89586997],
[-0.51538502,-2.62569576],
[-4.08561754,-4.2870525 ],
[-0.80869722,10.12529582])
colors = ['red','red','red','blue','red','blue']
ax1.plot(data[:,0],data[:,1],'o',picker=True)
How to set the color parameter to fit my list of colors ?
Using a line plot plt.plot()
plt.plot() does only allow for a single color. So you may simply loop over the data and colors and plot each point individually.
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
data = np.array([[4.29488806,-5.34487081],
[3.63116248,-2.48616998],
[-0.56023222,-5.89586997],
[-0.51538502,-2.62569576],
[-4.08561754,-4.2870525 ],
[-0.80869722,10.12529582]])
colors = ['red','red','red','blue','red','blue']
for xy, color in zip(data, colors):
ax.plot(xy[0],xy[1],'o',color=color, picker=True)
plt.show()
Using scatter plot plt.scatter()
In order to produce a scatter plot, use scatter. This has an argument c, which allows numerous ways of setting the colors of the scatter points.
(a) One easy way is to supply a list of colors.
colors = ['red','red','red','blue','red','blue']
ax.scatter(data[:,0],data[:,1],c=colors,marker="o", picker=True)
(b) Another option is to supply a list of data and map the data to color using a colormap
colors = [0,0,0,1,0,1] #red is 0, blue is 1
ax.scatter(data[:,0],data[:,1],c=colors,marker="o", cmap="bwr_r")
You have to set argument c of plt.scatter with a list of desired colors:
import matplotlib.pylab as plt
import numpy as np
data = np.array([[4.29488806,-5.34487081],
[3.63116248,-2.48616998],
[-0.56023222,-5.89586997],
[-0.51538502,-2.62569576],
[-4.08561754,-4.2870525 ],
[-0.80869722,10.12529582]])
colors = ['red','red','red','blue','red','blue']
plt.scatter(data[:,0],data[:,1],marker='o',c = colors)
plt.show()

Modifying python colormaps to single value beyond a specific point

How do I change a colormap color scheme to show the same color beyond a point.
E.g. here's my colormap:
import palettable
cmap = palettable.colorbrewer.sequential.YlGn_9.mpl_colormap
If I use this colormap to plot a range from 0 to 100, how can I modify the color map such that beyond 50, it changes to the color red?
You could create the colormap for the given range (0 →100) by stacking two different colormaps on top of each other as shown:
Illustration:
import numpy as np
import matplotlib.pyplot as plt
import palettable
import matplotlib.colors as mcolors
# Set random seed
np.random.seed(42)
# Create random values of shape 10x10
data = np.random.rand(10,10) * 100
# Given colormap which takes values from 0→50
colors1 = palettable.colorbrewer.sequential.YlGn_9.mpl_colormap(np.linspace(0, 1, 256))
# Red colormap which takes values from 50→100
colors2 = plt.cm.Reds(np.linspace(0, 1, 256))
# stacking the 2 arrays row-wise
colors = np.vstack((colors1, colors2))
# generating a smoothly-varying LinearSegmentedColormap
cmap = mcolors.LinearSegmentedColormap.from_list('colormap', colors)
plt.pcolor(data, cmap=cmap)
plt.colorbar()
# setting the lower and upper limits of the colorbar
plt.clim(0, 100)
plt.show()
Incase you want the upper portion to be of the same color and not spread over the length of the colormap, you could make the following modification:
colors2 = plt.cm.Reds(np.linspace(1, 1, 256))
cmap.set_over("red")
And you may wanna use one of the norm functions to set your specific bounds. If using imshow, you can also set the parameter vmin=50 to make that your top value.
You can create a new colormap from an existing colormap using:
newcmap = cmap.from_list('newcmap',list(map(cmap,range(50))), N=50)
This new map uses the last value from the colormap for colors over 50. To make the last color red, we can just append red to the last color in the list that defines the colormap.
newcmap = cmap.from_list('newcmap',list(map(cmap,range(50)))+[(1,0,0,1)], N=51)
import palettable
from matplotlib import pyplot as plt
cmap = palettable.colorbrewer.sequential.YlGn_9.mpl_colormap
newcmap = cmap.from_list('newcmap',list(map(cmap,range(50))), N=50)
for x in range(80):
plt.bar(x,1, width=1, edgecolor='none',facecolor=newcmap(x))
plt.show()
newcmap = cmap.from_list('newcmap',list(map(cmap,range(50)))+[(1,0,0,1)], N=51)
for x in range(80):
plt.bar(x,1, width=1, edgecolor='none',facecolor=newcmap(x))
plt.show()
You can access the colors with:
cmap_dict = cmap._segmentdata
which yields a dictionary. By indexing it with:
red = cmap_dict["red"]
green= cmap_dict["green"]
blue = cmap_dict["blue"]
alpha = cmap_dict["alpha"]
Now you can add a color from the list like this:
red .append(red [1])
recombine them into a dictionary with the 4 keys like:
cmap_dict_new["red"] = red
and create a new colormap with:
new_cmap = palettable.palette.ListedColormap(cmap_dict_new)
I don't think you should change the colormap, but rather the object using the colormap. I asked a similar question not so long ago: change color for first level of contourf, and I took the answer from here: Python matplotlib change default color for values exceeding colorbar range
If you use contours in your plot for example, you should do something like this:
cs = pyplot.contourf(x,y,z, cmap=your_cmap)
cs.cmap.set_over('r') # Change color to red
cs.set_clim(0, 50) # Set the limit beyond which everything is red
cb = pyplot.colorbar(cs) # Plot the colorbar (if needed)

Categories

Resources