matplotlib.patches.Polygon colors not rendering - python-2.7

for info, shape in zip(map.counties_info, map.counties):
if info['FIPS'] in geoids:
x = np.random.rand(1)[0]
c = cmap(x)[:3]
newc = rgb2hex(c)
patches.append(Polygon(np.array(shape), color=newc, closed=True))
ax.add_collection(PatchCollection(patches))
plt.title('Counties with HQ of NYSE-Listed Firms: 1970')
plt.show()
produces this image:
My question is the code specifically asks for random colors in the polygons. If I print the values of newc and display them at a website that converts hex codes to colors, there is a wide range of different colors. But the output has only one. How can I fix this?

In order for a PatchCollection to have different colors for the individual patches, you have two options.
Using the colors of the original patches.
Using a colormap to determine the colors according to some array of values.
Using the colors of the original patches.
This approach is closest to the code from the question. It would require to set the argument match_original=True to the patch collection.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
import matplotlib.patches
import matplotlib.collections
ar = np.array([[0,0],[1,0],[1,1],[0,1],[0,0]])
cmap=plt.cm.jet
patches=[]
fig, ax=plt.subplots()
for i in range(5):
x = np.random.rand(1)[0]
c = cmap(x)[:3]
poly = plt.Polygon(ar+i, color=c, closed=True)
patches.append(poly)
collection = matplotlib.collections.PatchCollection(patches,match_original=True)
ax.add_collection(collection)
ax.autoscale()
plt.show()
Using a colormap to determine the colors according to some array of values.
This is probably easier to implement. Instead of giving each individual polygon a color, you would set an array of values to the PatchCollection and specify a colormap according to which the polygons are colorized.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
import matplotlib.patches
import matplotlib.collections
ar = np.array([[0,0],[1,0],[1,1],[0,1],[0,0]])
values = np.random.rand(5)
cmap=plt.cm.jet
patches=[]
fig, ax=plt.subplots()
for i in range(len(values)):
poly = plt.Polygon(ar+i, closed=True)
patches.append(poly)
collection = matplotlib.collections.PatchCollection(patches, cmap=cmap)
collection.set_array(values)
ax.add_collection(collection)
ax.autoscale()
plt.show()

Related

Show all colors on colorbar with scatter plot

In the following I use scatter and an own ListedColormap to plot some coloured data points. In addition the corresponding colorbar is also plotted.
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap, ListedColormap, BoundaryNorm
from numpy import arange
fig, ax = plt.subplots()
my_cm = ListedColormap(['#a71b1b','#94258f','#ea99e6','#ec9510','#ece43b','#a3f8ff','#2586df','#035e0d'])
bounds=range(8)
norm = BoundaryNorm(bounds, my_cm.N)
data = [1,2,1,3,0,5,3,4]
ret = ax.scatter(range(my_cm.N), [1]*my_cm.N, c=data, edgecolors='face', cmap=my_cm, s=50)
cbar = fig.colorbar(ret, ax=ax, boundaries=arange(-0.5,8,1), ticks=bounds, norm=norm)
cbar.ax.tick_params(axis='both', which='both',length=0)
If my data is not covering each value of the boundary interval, the colorbar does not show all colours (like in the added figure). If data would be set to range(8), I get a dot of each colour and the colorbar also shows all colours.
How can I force the colorbar to show all defined colours even if data does not contain all boundary values?
You need to manually set vminand vmax in your call to ax.scatter:
ret = ax.scatter(range(my_cm.N), [1]*my_cm.N, c=data, edgecolors='face', cmap=my_cm, s=50, vmin=0, vmax=7)
resulting in
If my data is not covering each value of the boundary interval, the colorbar does not show all colours (like in the added figure).
If either vminor vmax are `None the color limits are set via the method
autoscale_None, and the minimum and maximum of your data are therefore used.
So using your code it is actually not necessary for showing all colors in the colorbar that every value of the boundary interval is covered, only the minimum and maximum need to be included.
Using e.g. data = [0,0,0,0,0,0,0,7] results in the following:
When looking for something else, I found another solution to that problem: colorbar-for-matplotlib-plot-surface-command.
In that case, I do not need to set vmin and vmax and it is also working in cases if the arrays/lists of points to plot are empty. Instead a ScalarMappable is defined and provided to colorbar instead of the scatterinstance.
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap, ListedColormap, BoundaryNorm
import matplotlib.cm as cm
from numpy import arange
fig, ax = plt.subplots()
my_cm = ListedColormap(['#a71b1b','#94258f','#ea99e6','#ec9510','#ece43b','#a3f8ff','#2586df','#035e0d'])
bounds=range(8)
norm = BoundaryNorm(bounds, my_cm.N)
mappable = cm.ScalarMappable(cmap=my_cm)
mappable.set_array(bounds)
data = [] # also x and y can be []
ax.scatter(x=range(my_cm.N), y=[1]*my_cm.N, c=data, edgecolors='face', cmap=my_cm, s=50)
cbar = fig.colorbar(mappable, ax=ax, boundaries=arange(-0.5,8,1), ticks=bounds, norm=norm)
cbar.ax.tick_params(axis='both', which='both',length=0)

Column order reversed in step histogram plot

Passing a 2D array to Matplotlib's histogram function with histtype='step' seems to plot the columns in reverse order (at least from my biased, Western perspective of left-to-right).
Here's an illustration:
import matplotlib.pyplot as plt
import numpy as np
X = np.array([
np.random.normal(size=5000),
np.random.uniform(size=5000)*2.0 - 1.0,
np.random.beta(2.0,1.0,size=5000)*3.0,
]).T
trash = plt.hist(X,bins=50,histtype='step')
plt.legend(['Normal','2*Uniform-1','3*Beta(2,1)'],loc='upper left')
Produces this:
Running matplotlib version 2.0.2, python 2.7
From the documentation for legend:
in order to keep the "label" and the legend element instance together,
it is preferable to specify the label either at artist creation, or by
calling the set_label method on the
artist
I recommend to use the label keyword argument to hist:
String, or sequence of strings to match multiple datasets
The result is:
import matplotlib.pyplot as plt
import numpy as np
X = np.array([
np.random.normal(size=5000),
np.random.uniform(size=5000)*2.0 - 1.0,
np.random.beta(2.0,1.0,size=5000)*3.0,
]).T
trash = plt.hist(X,bins=50,histtype='step',
label=['Normal','2*Uniform-1','3*Beta(2,1)'])
plt.legend(loc='upper left')
plt.show()

Python: plot different kinds of colors [duplicate]

I am using matplotlib to create the plots. I have to identify each plot with a different color which should be automatically generated by Python.
Can you please give me a method to put different colors for different plots in the same figure?
Matplotlib does this by default.
E.g.:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)
plt.show()
And, as you may already know, you can easily add a legend:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)
plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')
plt.show()
If you want to control the colors that will be cycled through:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
plt.gca().set_color_cycle(['red', 'green', 'blue', 'yellow'])
plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)
plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')
plt.show()
If you're unfamiliar with matplotlib, the tutorial is a good place to start.
Edit:
First off, if you have a lot (>5) of things you want to plot on one figure, either:
Put them on different plots (consider using a few subplots on one figure), or
Use something other than color (i.e. marker styles or line thickness) to distinguish between them.
Otherwise, you're going to wind up with a very messy plot! Be nice to who ever is going to read whatever you're doing and don't try to cram 15 different things onto one figure!!
Beyond that, many people are colorblind to varying degrees, and distinguishing between numerous subtly different colors is difficult for more people than you may realize.
That having been said, if you really want to put 20 lines on one axis with 20 relatively distinct colors, here's one way to do it:
import matplotlib.pyplot as plt
import numpy as np
num_plots = 20
# Have a look at the colormaps here and decide which one you'd like:
# http://matplotlib.org/1.2.1/examples/pylab_examples/show_colormaps.html
colormap = plt.cm.gist_ncar
plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))
# Plot several different functions...
x = np.arange(10)
labels = []
for i in range(1, num_plots + 1):
plt.plot(x, i * x + 5 * i)
labels.append(r'$y = %ix + %i$' % (i, 5*i))
# I'm basically just demonstrating several different legend options here...
plt.legend(labels, ncol=4, loc='upper center',
bbox_to_anchor=[0.5, 1.1],
columnspacing=1.0, labelspacing=0.0,
handletextpad=0.0, handlelength=1.5,
fancybox=True, shadow=True)
plt.show()
Setting them later
If you don't know the number of the plots you are going to plot you can change the colours once you have plotted them retrieving the number directly from the plot using .lines, I use this solution:
Some random data
import matplotlib.pyplot as plt
import numpy as np
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
for i in range(1,15):
ax1.plot(np.array([1,5])*i,label=i)
The piece of code that you need:
colormap = plt.cm.gist_ncar #nipy_spectral, Set1,Paired
colors = [colormap(i) for i in np.linspace(0, 1,len(ax1.lines))]
for i,j in enumerate(ax1.lines):
j.set_color(colors[i])
ax1.legend(loc=2)
The result is the following:
TL;DR No, it can't be done automatically. Yes, it is possible.
import matplotlib.pyplot as plt
my_colors = plt.rcParams['axes.prop_cycle']() # <<< note that we CALL the prop_cycle
fig, axes = plt.subplots(2,3)
for ax in axes.flatten(): ax.plot((0,1), (0,1), **next(my_colors))
Each plot (axes) in a figure (figure) has its own cycle of colors — if you don't force a different color for each plot, all the plots share the same order of colors but, if we stretch a bit what "automatically" means, it can be done.
The OP wrote
[...] I have to identify each plot with a different color which should be automatically generated by [Matplotlib].
But... Matplotlib automatically generates different colors for each different curve
In [10]: import numpy as np
...: import matplotlib.pyplot as plt
In [11]: plt.plot((0,1), (0,1), (1,2), (1,0));
Out[11]:
So why the OP request? If we continue to read, we have
Can you please give me a method to put different colors for different plots in the same figure?
and it make sense, because each plot (each axes in Matplotlib's parlance) has its own color_cycle (or rather, in 2018, its prop_cycle) and each plot (axes) reuses the same colors in the same order.
In [12]: fig, axes = plt.subplots(2,3)
In [13]: for ax in axes.flatten():
...: ax.plot((0,1), (0,1))
If this is the meaning of the original question, one possibility is to explicitly name a different color for each plot.
If the plots (as it often happens) are generated in a loop we must have an additional loop variable to override the color automatically chosen by Matplotlib.
In [14]: fig, axes = plt.subplots(2,3)
In [15]: for ax, short_color_name in zip(axes.flatten(), 'brgkyc'):
...: ax.plot((0,1), (0,1), short_color_name)
Another possibility is to instantiate a cycler object
from cycler import cycler
my_cycler = cycler('color', ['k', 'r']) * cycler('linewidth', [1., 1.5, 2.])
actual_cycler = my_cycler()
fig, axes = plt.subplots(2,3)
for ax in axes.flat:
ax.plot((0,1), (0,1), **next(actual_cycler))
Note that type(my_cycler) is cycler.Cycler but type(actual_cycler) is itertools.cycle.
I would like to offer a minor improvement on the last loop answer given in the previous post (that post is correct and should still be accepted). The implicit assumption made when labeling the last example is that plt.label(LIST) puts label number X in LIST with the line corresponding to the Xth time plot was called. I have run into problems with this approach before. The recommended way to build legends and customize their labels per matplotlibs documentation ( http://matplotlib.org/users/legend_guide.html#adjusting-the-order-of-legend-item) is to have a warm feeling that the labels go along with the exact plots you think they do:
...
# Plot several different functions...
labels = []
plotHandles = []
for i in range(1, num_plots + 1):
x, = plt.plot(some x vector, some y vector) #need the ',' per ** below
plotHandles.append(x)
labels.append(some label)
plt.legend(plotHandles, labels, 'upper left',ncol=1)
**: Matplotlib Legends not working
Matplot colors your plot with different colors , but incase you wanna put specific colors
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
plt.plot(x, x)
plt.plot(x, 2 * x,color='blue')
plt.plot(x, 3 * x,color='red')
plt.plot(x, 4 * x,color='green')
plt.show()
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from skspatial.objects import Line, Vector
for count in range(0,len(LineList),1):
Line_Color = np.random.rand(3,)
Line(StartPoint,EndPoint)).plot_3d(ax,c="Line"+str(count),label="Line"+str(count))
plt.legend(loc='lower left')
plt.show(block=True)
The above code might help you to add 3D lines with different colours in a randomized fashion. Your colored lines can also be referenced with a help of a legend as mentioned in the label="... " parameter.
Honestly, my favourite way to do this is pretty simple: Now this won't work for an arbitrarily large number of plots, but it will do you up to 1163. This is by using the map of all matplotlib's named colours and then selecting them at random.
from random import choice
import matplotlib.pyplot as plt
from matplotlib.colors import mcolors
# Get full named colour map from matplotlib
colours = mcolors._colors_full_map # This is a dictionary of all named colours
# Turn the dictionary into a list
color_lst = list(colours.values())
# Plot using these random colours
for n, plot in enumerate(plots):
plt.scatter(plot[x], plot[y], color=choice(color_lst), label=n)

bar plot with different colors in python

I have data like this :
import pandas as pd
import matplotlib.pyplot as plt
index={'A','B','C','D','E'}
d={'typ':[1,2,2,2,1],'value':[10,25,15,17,13]}
df=pd.DataFrame(d,index=index)
I want to plot the dataframe in horizontal bars with different colors reffering to the column 'typ'
You can use the color parameter of matplotlib's barh function:
import pandas as pd
import matplotlib.pyplot as plt
index={'A','B','C','D','E'}
d={'typ':[1,2,2,2,1],'value':[10,25,15,17,13]}
df=pd.DataFrame(d,index=index)
# define the colors for each type
colors = {1:'blue', 2:'red'}
# plot the bars
plt.bar(range(len(df)), df['value'], align='center',
color=[colors[t] for t in df['typ']])

2D Histogram from a 3x3 array in PYTHON

This might sound trivial, but I am unable find a solution in PYTHON. No problem in ROOT or MATLAB.
So, I have a 3x3 array, and I would like each element in the array to represent the height (frequency) of a bin. I should have a histogram with 9 bins. Here's an example of what I have been trying.
import numpy as np
import matplotlib.pyplot as plt
H = np.array([[21,33,6],[25,20,2],[80,40,0]])
hist, bin = np.histogramdd(H, bins=3)
center = 0.5*(bin[:-1] + bin[1:])
plt.bar(center, hist)
plt.show()
I've tried histogram2D, I just can't find any to get this to work with PYTHON. Thanks in advance for any help on this.
If im not mistaken shouldnt this just be:
H=H.reshape(-1)
plt.bar(np.arange(H.shape[0]),H)
You can also do a 3D histogram:
extent = [0,2,0,2]
plt.imshow(H, extent=extent, interpolation='nearest')
plt.colorbar()
plt.show()
3D Bar histogram:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for z,height in enumerate(H):
cs = [c] * len(xs)
cs[0] = 'c'
ax.bar(np.arange(3), height, zs=z, zdir='y', color=cs, alpha=0.8)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
The above should work, I dont have my laptop with me at the moment. More example can be found here. A great example for 3D bars can be found here.