matplotlib plot filled with different layers by loop, colouring - python

I produce multiple plots containing each 5 subplots, generated in a for loop.
How can I define the coloring of the subplots? Do I need something like a Matrix with numbers and colors and use it somehow like Matrix[z] instead of the Color?
fig = plt.figure()
ax = fig.add_subplot(111)
for z in Var
ax.plot(x, y, color='black', alpha=0.5 , label=labelString)

It is unclear what you exactly mean. But if you mean plotting 5 different curves in the same plot, each in different color, this is one way you can do it. This allows you to choose colors as you want. In case you do not specify colors manually like in the code below, python will assign colors automatically. In that case you just have to write ax.plot(x, y, label=r'y=%dx$^2$' %(i+1))
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8, 5))
ax = fig.add_subplot(111)
colors = ['r', 'g', 'b', 'k', 'y']
x = np.linspace(0, 5, 100)
for i in range(5):
y = (i+1)*x**2
ax.plot(x, y, color=colors[i], label=r'y=%dx$^2$' %(i+1))
plt.legend(fontsize=16)
Output

Related

Matplotlib : Horizontal Bar Plot with Color Range

Please forgive the crude explanation but I'm unsure how to describe the issue and as they say, a picture says a thousand words, so what I am trying to achieve is to draw a graph in matplotlib that looks like the below:
whereby the scale of the color range is the same across all bars as the x limits of the x-axis.
The closest I have got to so far is this (please ignore the fact it's not horizontal - I was planning on editing that once I had figured out the coloring):
fig, ax = plt.subplots()
mpl.pyplot.viridis()
bars = ax.bar(df['Profile'], df['noise_result'])
grad = np.atleast_2d(np.linspace(0,1,256)).T
ax = bars[0].axes
lim = ax.get_xlim()+ax.get_ylim()
for bar in bars:
bar.set_zorder(1)
bar.set_facecolor('none')
x,y = bar.get_xy()
w, h = bar.get_width(), bar.get_height()
ax.imshow(grad, extent=[x,x+w,y,y+h], aspect='auto', zorder=1,interpolation='nearest')
ax.axis(lim)
which only results in a graph like below:
Many thanks
I'm going along with your approach. The idea is to:
choose an appropriate colormap
create a normalizer for the bar values.
create a mappable which is going to map the normalized values to the colormap in order to create a colorbar.
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib.colors import Normalize
import pandas as pd
import numpy as np
df = pd.DataFrame({'key':['A', 'B', 'C', 'D', 'E'], 'val':[100, 20, 70, 40, 100]})
# create a normalizer
norm = Normalize(vmin=df['val'].min(), vmax=df['val'].max())
# choose a colormap
cmap = cm.plasma
# map values to a colorbar
mappable = cm.ScalarMappable(norm=norm, cmap=cmap)
mappable.set_array(df['val'])
fig, ax = plt.subplots()
bars = ax.bar(df['key'], df['val'])
ax = bars[0].axes
lim = ax.get_xlim()+ax.get_ylim()
for bar, val in zip(bars, df['val']):
grad = np.atleast_2d(np.linspace(0,val,256)).T
bar.set_zorder(1)
bar.set_facecolor('none')
x, y = bar.get_xy()
w, h = bar.get_width(), bar.get_height()
ax.imshow(np.flip(grad), extent=[x,x+w,y,y+h], aspect='auto', zorder=1,interpolation='nearest', cmap=cmap, norm=norm)
ax.axis(lim)
cb = fig.colorbar(mappable)
cb.set_label("Values")
Using what you have, you could change line 12 to:
ax.imshow(grad, extent=[x,x+w,y,y+h], aspect='auto', zorder=1, cmap = plt.get_cmap('gist_heat_r'))
or some other color map from:
https://matplotlib.org/stable/tutorials/colors/colormaps.html
You could also change line 3 to start as:
bars = ax.barh
for horizontal bars.

Change dimension of points with their value in matplotlib

Below I created a simple example of my dataset. I have 4 points and for each steps their value change. The points are plotted in x,y plane and I want their size to change with their value. There is also one other problem, each point is connected by a line and I don't want it. (I cannot use plt.scatter)
import pandas as pd
import matplotlib.pyplot as plt
data=[[1,1,3],[1,2,1],[2,1,9],[2,2,0]]
a=pd.DataFrame(data)
a.columns=['x','y','value']
data2=[[1,1,5],[1,2,2],[2,1,1],[2,2,3]]
b=pd.DataFrame(data2)
b.columns=['x','y','value']
data3=[[1,1,15],[1,2,7],[2,1,4],[2,2,8]]
c=pd.DataFrame(data3)
c.columns=['x','y','value']
final=[a,b,c]
for i in range(0,len(final)):
fig, ax = plt.subplots()
plt.plot(final[i]['x'],final[i]['y'],marker='o',markersize=22)
with this I fix the dimension the line appears in, how can I remove it?
If I change the markersize, it doesn't work:
for i in range(0,len(final)):
fig, ax = plt.subplots()
plt.plot(final[i]['x'],final[i]['y'],marker='o',markersize=final[i]['value'])
As I said before, the result I want is a plot in which there are only the points with different dimensions depending on their value.
Since you cannot use scatter, you need to loop over the values to use the markersize as it does not accept arrays but a scalar. Moreover, to just plot a marker, you use 'o' for a circle. I used size*5 to enlarge the circles further.
for i in range(0,len(final)):
fig, ax = plt.subplots()
for x, y, size in zip(final[i]['x'],final[i]['y'], final[i]['value']):
plt.plot(x, y, 'o', markersize=size*5)
In case you want to plot them as subplots
fig, axes = plt.subplots(1,3, figsize=(9, 2))
for i in range(0,len(final)):
for x, y, size in zip(final[i]['x'],final[i]['y'], final[i]['value']):
axes[i].plot(x, y, 'o', markersize=size*5)
plt.tight_layout()
You have an argument for the line width in plt.plot graphs. Please set it to zero.
plt.plot(final[i]["x"], final[i]["y"], marker="o", markersize=22, linewidth=0)

Dynamic marker colour in matplotlib

I have two lists containing the x and y coordinates of some points. There is also a list with some values assigned to each of those points. Now my question is, I can always plot the points (x,y) using markers in python. Also I can select colour of the marker manually (as in this code).
import matplotlib.pyplot as plt
x=[0,0,1,1,2,2,3,3]
y=[-1,3,2,-2,0,2,3,1]
colour=['blue','green','red','orange','cyan','black','pink','magenta']
values=[2,6,10,8,0,9,3,6]
for i in range(len(x)):
plt.plot(x[i], y[i], linestyle='none', color=colour[i], marker='o')
plt.axis([-1,4,-3,4])
plt.show()
But is it possible to choose a colour for the marker marking a particular point according to the value assigned to that point (using cm.jet, cm.gray or similar other color schemes) and provide a colorbar with the plot ?
For example, this is the kind of plot I am looking for
where the red dots denote high temperature points and the blue dots denote low temperature ones and others are for temperatures in between.
You are most likely looking for matplotlib.pyplot.scatter. Example:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# Generate data:
N = 10
x = np.linspace(0, 1, N)
y = np.linspace(0, 1, N)
x, y = np.meshgrid(x, y)
colors = np.random.rand(N, N) # colors for each x,y
# Plot
circle_size = 200
cmap = matplotlib.cm.viridis # replace with your favourite colormap
fig, ax = plt.subplots(figsize=(4, 4))
s = ax.scatter(x, y, s=circle_size, c=colors, cmap=cmap)
# Prettify
ax.axis("tight")
fig.colorbar(s)
plt.show()
Note: viridis may fail on older version of matplotlib.
Resulting image:
Edit
scatter does not require your input data to be 2-D, here are 4 alternatives that generate the same image:
import matplotlib
import matplotlib.pyplot as plt
x = [0,0,1,1,2,2,3,3]
y = [-1,3,2,-2,0,2,3,1]
values = [2,6,10,8,0,9,3,6]
# Let the colormap extend between:
vmin = min(values)
vmax = max(values)
cmap = matplotlib.cm.viridis
norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax)
fig, ax = plt.subplots(4, sharex=True, sharey=True)
# Alternative 1: using plot:
for i in range(len(x)):
color = cmap(norm(values[i]))
ax[0].plot(x[i], y[i], linestyle='none', color=color, marker='o')
# Alternative 2: using scatter without specifying norm
ax[1].scatter(x, y, c=values, cmap=cmap)
# Alternative 3: using scatter with normalized values:
ax[2].scatter(x, y, c=cmap(norm(values)))
# Alternative 4: using scatter with vmin, vmax and cmap keyword-arguments
ax[3].scatter(x, y, c=values, vmin=vmin, vmax=vmax, cmap=cmap)
plt.show()

How to fill mplot3d bar plot depth? [Python 3.x]

There is an example for how to build a bar plot at the bottom of this question taken from the matplotlib site.
I cannot find a parameter to increase the depth of each bar. I want depth to give it a 3d look like this picture.
Is there a function parameter to change this that I'm not seeing, or will I need to use a different 3D bar plot function?
Below is the bar plot code from the first link in case someone can't see it:
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 c, z in zip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]):
xs = np.arange(20)
ys = np.random.rand(20)
# You can provide either a single color or an array. To demonstrate this,
# the first bar of each set will be colored cyan.
cs = [c] * len(xs)
cs[0] = 'c'
ax.bar(xs, ys, zs=z, zdir='y', color=cs, alpha=0.8)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
I've found this link to a solution but this solution doesn't actually increase the depth. I'm hoping for a method to completely fill the depth if possible.
Do you want something like the code in this answer? They use bar3d(), but the locations for each bar are manually created with meshgrid.

how to shade points in scatter based on colormap in matplotlib?

I'm trying to shade points in a scatter plot based on a set of values (from 0 to 1) picked from one of the already defined color maps, like Blues or Reds. I tried this:
import matplotlib
import matplotlib.pyplot as plt
from numpy import *
from scipy import *
fig = plt.figure()
mymap = plt.get_cmap("Reds")
x = [8.4808517662594909, 11.749082788323497, 5.9075039082855652, 3.6156231827873615, 12.536817102137768, 11.749082788323497, 5.9075039082855652, 3.6156231827873615, 12.536817102137768]
spaced_colors = linspace(0, 1, 10)
print spaced_colors
plt.scatter(x, x,
color=spaced_colors,
cmap=mymap)
# this does not work either
plt.scatter(x, x,
color=spaced_colors,
cmap=plt.get_cmap("gray"))
But it does not work, using either the Reds or gray color map. How can this be done?
edit: if I want to plot each point separately so it can have a separate legend, how can I do it? I tried:
fig = plt.figure()
mymap = plt.get_cmap("Reds")
data = np.random.random([10, 2])
colors = list(linspace(0.1, 1, 5)) + list(linspace(0.1, 1, 5))
print "colors: ", colors
plt.subplot(1, 2, 1)
plt.scatter(data[:, 0], data[:, 1],
c=colors,
cmap=mymap)
plt.subplot(1, 2, 2)
# attempt to plot first five points in five shades of red,
# with a separate legend for each point
for n in range(5):
plt.scatter([data[n, 0]], [data[n, 1]],
c=[colors[n]],
cmap=mymap,
label="point %d" %(n))
plt.legend()
but it fails. I need to make a call to scatter for each point so that it can have a separate label=, but still want each point to have a different shade of the color map as its color.
thanks.
If you really want to do this (what you describe in your edit), you have to "pull" the colors from your colormap (I have commented all changes I made to your code):
import numpy as np
import matplotlib.pyplot as plt
# plt.subplots instead of plt.subplot
# create a figure and two subplots side by side, they share the
# x and the y-axis
fig, axes = plt.subplots(ncols=2, sharey=True, sharex=True)
data = np.random.random([10, 2])
# np.r_ instead of lists
colors = np.r_[np.linspace(0.1, 1, 5), np.linspace(0.1, 1, 5)]
mymap = plt.get_cmap("Reds")
# get the colors from the color map
my_colors = mymap(colors)
# here you give floats as color to scatter and a color map
# scatter "translates" this
axes[0].scatter(data[:, 0], data[:, 1], s=40,
c=colors, edgecolors='None',
cmap=mymap)
for n in range(5):
# here you give a color to scatter
axes[1].scatter(data[n, 0], data[n, 1], s=40,
color=my_colors[n], edgecolors='None',
label="point %d" %(n))
# by default legend would show multiple scatterpoints (as you would normally
# plot multiple points with scatter)
# I reduce the number to one here
plt.legend(scatterpoints=1)
plt.tight_layout()
plt.show()
However, if you only want to plot 10 values and want to name every single one,
you should consider using something different, for instance a bar chart as in this
example. Another opportunity would be to use plt.plot with a custom color cycle, like in this example.
As per the documentation, you want the c keyword argument instead of color. (I agree that this is a bit confusing, but the "c" and "s" terminology is inherited from matlab, in this case.)
E.g.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
x, y, colors = np.random.random((3,10))
fig, ax = plt.subplots()
ax.scatter(x, y, c=colors, s=50, cmap=mpl.cm.Reds)
plt.show()
How about:
import matplotlib.pyplot as plt
import numpy as np
reds = plt.get_cmap("Reds")
x = np.linspace(0, 10, 10)
y = np.log(x)
# color by value given a cmap
plt.subplot(121)
plt.scatter(x, y, c=x, s=100, cmap=reds)
# color by value, and add a legend for each
plt.subplot(122)
norm = plt.normalize()
norm.autoscale(x)
for i, (x_val, y_val) in enumerate(zip(x, y)):
plt.plot(x_val, y_val, 'o', markersize=10,
color=reds(norm(x_val)),
label='Point %s' % i
)
plt.legend(numpoints=1, loc='lower right')
plt.show()
The code should all be fairly self explanatory, but if you want me to go over anything, just shout.

Categories

Resources