So I need to create a number of heatmaps in seaborn with varying datascales. Some range from 0-100 and some +100 to -100. What I need to do is to keep the colour grading the same throughout all graphs. So for example I want anything below 0 to be steadily getting from dark blue to light blue and anything above 0 to be getting darker red such as the terrible example graph below.
What I need that is not shown below very well is a fluid colour transition as currently I am not fully sure how seaborn is working it out as I have just listed a number of colours - Code below
sns.heatmap(df.T, cmap=ListedColormap(['#000066','#000099','#0000cc','#1a1aff','#6666ff','#b3b3ff','#ffff00','#ffcccc','#ff9999','#ff6666','#ff3333','#ff0000']), annot=False)
Thanks for any advise.
To specify the color normalization, you can use a Normalize instance, plt.Normalize(vmin, vmax) and supply it to the heatmap using the norm keyword (which is routed to the underlying pcolormesh).
To obtain a colormap with gradually changing colors, you may use the static LinearSegmentedColormap.from_list method and supply it with a list of colors.
import numpy as np; np.random.seed(0)
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
x1 = np.random.randint(0,100,size=(12,8))
x2 = np.random.randint(-100,100,size=(12,8))
fig, axes = plt.subplots(ncols=2)
cmap = mcolors.LinearSegmentedColormap.from_list("n",['#000066','#000099','#0000cc','#1a1aff','#6666ff','#b3b3ff',
'#ffff00','#ffcccc','#ff9999','#ff6666','#ff3333','#ff0000'])
norm = plt.Normalize(-100,100)
sns.heatmap(x1, ax=axes[0], cmap=cmap, norm=norm)
sns.heatmap(x2, ax=axes[1], cmap=cmap, norm=norm)
plt.show()
Related
I am new to seaborn, and I was going through documentation and examples. I have attached the plot below. How can we interpret the color intensity in this plot?
We will not be able to really understand what those bluish colours mean unless there is a scale or a guide which represents the mapping of colors to some attributes of the data.
Thus, the best way to do this would be to add a cbar=True argument in sns.displot, along with the title of the colorbar to make sure the visualisation conveys the context properly.
import matplotlib.pyplot as plt
import seaborn as sns
penguins = sns.load_dataset("penguins")
sns.displot(data=penguins, x="bill_length_mm", y="bill_depth_mm", cbar=True,
cbar_kws={'label': 'Counts in the bin'})
plt.show()
This gives:
In my data
import numpy as np
import matplotlib.pyplot as plt
voxel = np.random((2,2,2))
fig = plt.figure()
ax = fig.gca(projection = '3d')
ax.voxels(voxel, edgecolor ='k')
In this code, I can get the voxels with same color although all of the voxel has different values because of random function.
Here, can I make these voxel colors different according to the data in 'voxel'?
+) Also, I want to add colorbars in my plotting to see the range of colors like imshow() functions to get the feature map of CNN, however the system sends me that ax.voxels doesn't support colorbars. Can you give me suggestion how to plot my data?
I have a dataframe v with some numerical data in it.
v=pd.DataFrame(data=np.random.rand(300,3))
I am want to plot on the same matplotlib figure:
a scatter plot
a moving average of the same points
I do that using pd.DataFrame.plot()
plt.figure()
v.plot(style='o',legend=False,ax=plt.gca(),alpha=0.2,ls='')
v.rolling(7).mean().plot(legend=False,ax=plt.gca())
This works fine.
However, the points drawn with the first plot are colored according to their row number. Same happens for the lines in the second plot.
I would like the two colors to be consistent between the two plot commands, so
line obtained by moving average to have same color as in the scatter. How to get that?
Here is what I get running the code.
Obviously, I cannot figure out if the red lines correspond to the green orange or blue points...
ORIGINAL
I believe you need -
%matplotlib inline # only for jupyter notebooks
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
colors = {0: 'red', 1:'green', 2:'blue'}
v=pd.DataFrame(data=np.random.rand(300,3))
plt.figure()
v.plot(marker='o',legend=False,ax=plt.gca(),ls='', alpha=0.2, color=colors.values())
v.rolling(7).mean().plot(legend=False,ax=plt.gca(), color=colors.values())
UPDATE
Just go with -
Option 1 (no extra cm dependency)
colors_rand = np.random.rand(len(v.columns),3)
v.plot(marker='o',legend=False,ax=plt.gca(),ls='', alpha=0.5, color=colors_rand )
v.rolling(7).mean().plot(legend=False,ax=plt.gca(), color=colors_rand )
Option 2(as suggested by OP)
v.plot(marker='o',legend=False,ax=plt.gca(),ls='', alpha=0.5, colors=cm.rainbow(np.linspace(0,1,v.shape[1]) ))
v.rolling(7).mean().plot(legend=False,ax=plt.gca(), colors=cm.rainbow(np.linspace(0,1,v.shape[1]) ))
I have a 2D array of values between 0 and (including) 22.
I want every value to have a discrete colour and hover value assigned to it in a normal matshow plot.
I tried it with just a Colormap and with a normalization but the colours 15 and 16 are not consistent.
Without any normalization 15 has the colour of 16 (and of course the hover values are misaligned floats).
With normalization, everything is fine except 16 has the colour of 15.
I saw multiple other questions asking the same thing but following the answers resulted in this problem.
import matplotlib.pyplot as plt
import matplotlib.colors as colors
example_data = [list(range(23))]*4
cmaplist = [
"#b3b3b3", "#333333", "#8a745c", "#8f7456",
"#847362", "#1a53ff", "#336600", "#aa8a31",
"#b3b3b3", "#aa8a31", "#aa8a31", "#004d00",
"#aa8a31", "#5c330a", "#999999", "#66d9ff",
"#e481a2", "#e996b1", "#e481a2", "#e06c92",
"#e87da1", "#fff11c", "#ff6600"
]
norm = colors.BoundaryNorm(range(len(cmaplist)+1), len(cmaplist))
cmap = colors.LinearSegmentedColormap.from_list('mycmap', cmaplist, len(cmaplist))
plt.matshow(example_data, fignum=False, cmap=cmap, norm=norm)
plt.show()
I am not very good with matplotlib etc. so this may be a really obvious mistake. I am treating this just like its just a simple value lookup of the data but I am aware that that's not how it actually works but I can't think of a better approach with my limited knowledge.
First try to create a MCVE:
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import numpy as np
example_data = np.array([list(range(20))]*4)
cmaplist = ["red", "limegreen", "blue", "gold"]*5
fig, ax = plt.subplots()
norm = colors.BoundaryNorm(np.arange(0,len(cmaplist)+1)-0.5, len(cmaplist))
cmap = colors.LinearSegmentedColormap.from_list('mycmap',cmaplist, len(cmaplist))
im = ax.matshow(example_data, cmap=cmap, norm=norm)
plt.show()
As can be seen, the color at positions 14 and 15 is the same, while position 15 should be yellow. This is present in matplotlib 2.1, in matplotlib 2.0.2 the issue seems not to be there. I therefore opened a bug report about it.
Solution:
The numbers you are mapping (which are integers here) are exactly on the edge of the boundaries. I'm not exactly sure what goes wrong here, but to be on the save side, you may use the middle between two integers as the boundary, i.e.
norm = colors.BoundaryNorm(np.arange(0,len(cmaplist)+1)-0.5, len(cmaplist))
Complete example:
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import numpy as np
example_data = np.array([list(range(20))]*4)
cmaplist = ["red", "limegreen", "blue", "gold"]*5
fig, ax = plt.subplots()
norm = colors.BoundaryNorm(np.arange(0,len(cmaplist)+1)-0.5, len(cmaplist))
cmap = colors.LinearSegmentedColormap.from_list('mycmap',cmaplist, len(cmaplist))
im = ax.matshow(example_data, cmap=cmap, norm=norm)
plt.show()
import numpy as np
import matplotlib.pyplot as plt
x=np.linspace(-np.pi,np.pi,101)
y=np.sin(x)+np.sin(3*x)/3
y1=np.sin(x)+np.sin(2*x)/3
y2=np.sin(x)+np.sin(3*x)/2
plt.set_cmap('hot')
plt.plot(x,y)
plt.plot(x,y1)
plt.plot(x,y2)
plt.show()
I wanted to try a different colormap in my plot, but the command plt.set_cmap('hot') does not work, i.e. the colours are the same as in the standard palette ( http://i.stack.imgur.com/FjXoO.png)
I am using WXAgg backend under Debian Linux and matplotlib from Enthought's Canopy. I tried the Qt4Agg backend and the result was the same. How to properly change the colours?
plt.set_cmap will set a colormap to be used, for example, in an image plot. As you're simply plotting lines, it won't affect your plots.
When plotting using plt.plot you can provide a color keyword argument which will choose the color of your lines, as below.
# ...
plt.plot(x,y, color='black')
plt.plot(x,y1, color='pink')
plt.plot(x,y2, color='green')
plt.show()
Alternatively, you could set a new color cycle using the ax.set_color_cycle(), which allows you to choose how the colors will change as you add new plots and effectively creates the same graph as before. See here for a demo.
# ...
plt.gca().set_color_cycle(['black', 'pink', 'green'])
plt.plot(x,y)
plt.plot(x,y1)
plt.plot(x,y2)
plt.show()
Finally, if you want to get a list of colors from an existing colormap then you can use the below code to get them spaced out linearly. The colormap itself is given by matplotlib.pyplot.cm.<your_colormap_here>. And by passing 10 equally spaced numbers between 0 and 1 as an argument, you get 10 equally spaced colors.
import numpy as np
import matplotlib.pyplot as plt
x=np.linspace(-np.pi,np.pi,101)
y=np.sin(x)+np.sin(3*x)/3
y1=np.sin(x)+np.sin(2*x)/3
y2=np.sin(x)+np.sin(3*x)/2
colors = plt.cm.hot(np.linspace(0,1,10))
plt.gca().set_color_cycle(colors)
plt.plot(x,y)
plt.plot(x,y1)
plt.plot(x,y2)
plt.show()