how to use matplotlib's set_cmap()? - python

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()

Related

Why doesn't the color of the points in a scatter plot match the color of the points in the corresponding legend?

I have a sample scatterplot via matplotlib via the code below.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 100, 501)
y = np.sin(x)
label = 'xy data sample'
plt.scatter(x, y, cmap='plasma', c=x, label=label)
legend_dict = dict(ncol=1, loc='best', scatterpoints=4, fancybox=True, shadow=True)
plt.legend(**legend_dict)
plt.show()
Running the code above produces the plot below.
The colormap was successfully plotted, but the legend shows points that are all blue rather than points in a color that correspond to the chosen colormap. Why does this happen?
I tried putting cmap='plasma' in legend_dict, but it results in the error below.
File "/Users/.../
site-packages/matplotlib/axes/_axes.py", line 550, in legend
self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'cmap'
EDIT:
My desired output is to have the four dots represented in the legend to be a different color via the chosen colormap. Ideally, cmap='plasma' in this example could produce a legend using something similar to a blue dot, then a purple dot, then an orange-red dot, then a yellow dot. Although a colorbar could make for a possible alternative, I have yet to look through any documentation about colorbars.
A colorbar can be achieved via plt.colorbar(). This would allow to directly see the values corresponding to the colors.
Having the points in the legend show different colors is of course also nice, although it would not allow to give any quantitative information.
Unfortunately matplotlib does not provide any inbuilt way to achieve this. So one way would be to subclass the legend handler used to create the legend handle and implement this feature.
Here we create a ScatterHandler with a custom create_collection method, in which we create the desired PathCollection and use this by specifying it in the legend_map dictionary of the legend.
handler_map={ type(sc) : ScatterHandler()}
The following code seems a bit complicated at first sight, however you may simply copy the class without understanding it completely and use it in your code.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerRegularPolyCollection
class ScatterHandler(HandlerRegularPolyCollection):
def update_prop(self, legend_handle, orig_handle, legend):
legend._set_artist_props(legend_handle)
legend_handle.set_clip_box(None)
legend_handle.set_clip_path(None)
def create_collection(self, orig_handle, sizes, offsets, transOffset):
p = type(orig_handle)([orig_handle.get_paths()[0]],
sizes=sizes, offsets=offsets,
transOffset=transOffset,
cmap=orig_handle.get_cmap(),
norm=orig_handle.norm )
a = orig_handle.get_array()
if type(a) != type(None):
p.set_array(np.linspace(a.min(),a.max(),len(offsets)))
else:
self._update_prop(p, orig_handle)
return p
x = np.linspace(0, 100, 501)
y = np.sin(x)*np.cos(x/50.)
sc = plt.scatter(x, y, cmap='plasma', c=x, label='xy data sample')
legend_dict = dict(ncol=1, loc='best', scatterpoints=4, fancybox=True, shadow=True)
plt.legend(handler_map={type(sc) : ScatterHandler()}, **legend_dict)
plt.show()

consistent colors after multiple calls of pd.DataFrame.plot()

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]) ))

Seaborn HeatMap - How to set colour grading throughout multiple different datasets

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()

Increment matplotlib color cycle

Is there a simple way to increment the matplotlib color cycle without digging into axes internals?
When plotting interactively a common pattern I use is:
import matplotlib.pyplot as plt
plt.figure()
plt.plot(x,y1)
plt.twinx()
plt.plot(x,y2)
The plt.twinx() in necessary to get different y-scales for y1 and y2 but both plots are drawn with the first color in the default colorcycle making it necessary to manually declare the color for each plot.
There must be a shorthand way to instruct the second plot to increment the color cycle rather than explicitly giving the color. It is easy of course to set color='b' or color='r' for the two plots but when using a custom style like ggplot you would need need to lookup the color codes from the current colorcycle which is cumbersome for interactive use.
You could call
ax2._get_lines.get_next_color()
to advance the color cycler on color. Unfortunately, this accesses the private attribute ._get_lines, so this is not part of the official public API and not guaranteed to work in future versions of matplotlib.
A safer but less direct way of advance the color cycler would be to plot a null plot:
ax2.plot([], [])
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(10)
y1 = np.random.randint(10, size=10)
y2 = np.random.randint(10, size=10)*100
fig, ax = plt.subplots()
ax.plot(x, y1, label='first')
ax2 = ax.twinx()
ax2._get_lines.get_next_color()
# ax2.plot([], [])
ax2.plot(x,y2, label='second')
handles1, labels1 = ax.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
ax.legend(handles1+handles2, labels1+labels2, loc='best')
plt.show()
Similar to the other answers but using matplotlib color cycler:
import matplotlib.pyplot as plt
from itertools import cycle
prop_cycle = plt.rcParams['axes.prop_cycle']
colors = cycle(prop_cycle.by_key()['color'])
for data in my_data:
ax.plot(data.x, data.y, color=next(colors))
There are several colour schemes available in Pyplot. You can read more on the matplotlib tutorial Specifying Colors.
From these docs:
a "CN" color spec, i.e. 'C' followed by a number, which is an index into the
default property cycle (matplotlib.rcParams['axes.prop_cycle']); the indexing
is intended to occur at rendering time, and defaults to black if the cycle
does not include color.
You can cycle through the colour scheme as follows:
fig, ax = plt.subplots()
# Import Python cycling library
from itertools import cycle
# Create a colour code cycler e.g. 'C0', 'C1', etc.
colour_codes = map('C{}'.format, cycle(range(10)))
# Iterate over series, cycling coloour codes
for y in my_data:
ax.plot(x, y, color=next(color_codes))
This could be improved by cycling over matplotlib.rcParams['axes.prop_cycle'] directly.

Meaning of cmap in contourf

I have two questions regarding usage of the contourf plotting function. I have been searching for answers but haven't found them.
In the contourf function, there is a variable named cmap. What is this used for and what is its meaning? And what is cmap=cm.jet mean?
When one puts x,y,z into contourf and then creates a colorbar, how do we get the minimum and maximum values by which to set the colorbar limits? I am doing it manually now, but is there no way to get the min and max directly from a contourf handle?
The cmap kwarg is the colormap that should be used to display the contour plot. If you do not specify one, the jet colormap (cm.jet) is used. You can change this to any other colormap that you want though (i.e. cm.gray). matplotlib has a large number of colormaps to choose from.
Here is a quick demo showing two contour plots with different colormaps selected.
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
data = np.random.rand(10,10)
plt.subplot(1,2,1)
con = plt.contourf(data, cmap=cm.jet)
plt.title('Jet')
plt.colorbar()
hax = plt.subplot(1,2,2)
con = plt.contourf(data, cmap=cm.gray)
plt.title('Gray')
plt.colorbar()
As far as getting the upper/lower bounds on the colorbar programmatically, you can do this by getting the clim value of the contourf plot object.
con = plt.contourf(data);
limits = con.get_clim()
(0.00, 1.05)
This returns a tuple containing the (lower, upper) bounds of the colorbar.

Categories