I have a function that takes a dictionary (key: string, values: 2D numbers) and displays the values of the dictionary in a graph (one color per key).
I would like to use this function directly to display in the same page four graphs, each graph corresponding to a particular dictionary
if possible I would like to have a script like :
def my_function(dico):
display picture
def global_function(multiple):
plt.subplot(1,2,1)
my_function(multiple[0])
plt.subplot(1,2,2)
my_function(multiple[1])
You can plot these graphs as subplots to one figure.
import numpy as np
import matplotlib.pyplot as plt
#plotting function
def plot_2_subplots (x1, y1, x2, y2):
f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
ax1.plot(x1, y1)
ax1.set_title('Plot 1')
ax2.plot(x2, y2)
ax2.set_title('Plot 2')
lists_a = sorted(d.items()) # return a list of tuples (sorted by key)
x1, y1 = zip(*lists_a) # unpack into tuple
lists_b = sorted(d.items()) # return a list of tuples (sorted by key)
x2, y2 = zip(*lists_b) # unpack into tuple
#Call plotting function
plot_2_subplots(x1, y1, x2, y2)
This generates this figure:
Related
I have an arbitrary, large number (50-1000) of lists, representing X and Y coordinates, I'd like to plot them in one figure.
The lists are of different length, usually 100-1000 elements each. I get the lists as pairs of x and y coordinates (see example), but could easily convert them to 2xN arrays. They need to be plotted in order, from first to the last element. Each line separately.
Is there a way to pack all my lists to one (or two; x and y) object that matplotlib can read?
This example gives the wanted output but is unhandy when there is a lot of data.
I'm happy for a solution that takes advantage of numpy.
from matplotlib import pyplot as plt
fig, ax = plt.subplots(1,1)
x1 = [1,2,5] # usually much longer and a larger number of lists
y1 = [3,2,4]
x2 = [1,6,5,3]
y2 = [7,6,3,2]
x3 = [4]
y3 = [4]
for x, y, in zip([x1, x2, x3],[y1, y2, y3]):
ax.plot(x,y, 'k.-')
plt.show()
I would prefer something like this:
# f() is the function i need, to formats the data for plotting
X = f(x1, x2, x3)
Y = f(y1, y2, y3)
#... so that I can do some processing of the arrays X, and Y here.
ax.plot(X, Y, 'k.-')
You can use a LineCollection for that. Unfortunately, if you want to have markers in your lines, LineCollection does not support that, so you would need to do some trick like adding a scatter plot on top (see Adding line markers when using LineCollection).
from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection
fig, ax = plt.subplots(1,1)
x1 = [1,2,5]
y1 = [3,2,4]
x2 = [1,6,5,3]
y2 = [7,6,3,2]
x3 = [4]
y3 = [4]
# Add lines
X = [x1, x2, x3]
Y = [y1, y2, y3]
lines = LineCollection((list(zip(x, y)) for x, y in zip(X, Y)),
colors='k', linestyles='-')
ax.add_collection(lines)
# Add markers
ax.scatter([x for xs in X for x in xs], [y for ys in Y for y in ys], c='k', marker='.')
# If you do not use the scatter plot you need to manually autoscale,
# as adding the line collection will not do it for you
ax.autoscale()
plt.show()
If you are working with arrays, you may also do as follows:
import numpy as np
# ...
X = [x1, x2, x3]
Y = [y1, y2, y3]
lines = LineCollection((np.stack([x, y], axis=1) for x, y in zip(X, Y)),
colors='k', linestyles='-')
ax.add_collection(lines)
ax.scatter(np.concatenate(X), np.concatenate(Y), c='k', marker='.')
I'm looking for the correct data structure to use for the following. I want to plot a line between two points, for a multiple set of points.
For example, to plot a line between (-1, 1) and (12, 4) I do this:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,1)
x1 = [-1, 12]
y1 = [1, 4]
ax.plot( x1, y1 )
plt.show()
If I want to plot another line connecting two different points (unrelated to the first set of points) I do this:
x2 = [1, 10]
y2 = [3, 2]
ax.plot( x1, y1, x2, y2 )
plot.show()
How do I extend this? That is, what data structure should I use to represent a growing array of such points [x1, y1, x2, y2, ...] generated by my input data?
I have tried the following,
points = [x1, y1, x2, y2]
ax.plot( points )
But the plot ends up connecting all of the individual lines with lines I do not want.
You are close:
ax.plot(*points)
The asterisk operator * converts an iterable (the list in your case) into a sequence of function parameters.
I'm plotting multiple figures of the same variable on one plot using matplotlib library. I'm not looking for a colorbar for subplots, which is the dominant search material. I plot multiple scatters, but the colorbar is only set to the values of the last scatter I plot.
Here is the part of the code:
plt.scatter(x1, y1, c=z1,cmap='viridis_r',marker='s')
plt.scatter(x2, y2, c=z2,cmap='viridis_r',marker='o')
plt.scatter(x3, y3, c=z3,cmap='viridis_r',marker='^')
plt.colorbar().set_label('Wind speed',rotation=270)
It requires a bit of extra work:
You have to get the minimum and maximum of the cs (the colorbar values)
You have to clim each scatter plot
First the minimum and maximum:
zs = np.concatenate([z1, z2, z3], axis=0)
min_, max_ = zs.min(), zs.max()
Then the scatter plots with clim:
plt.scatter(x1, y1, c=z1,cmap='viridis_r',marker='s')
plt.clim(min_, max_)
plt.scatter(x2, y2, c=z2,cmap='viridis_r',marker='o')
plt.clim(min_, max_)
plt.scatter(x3, y3, c=z3,cmap='viridis_r',marker='^')
plt.clim(min_, max_)
plt.colorbar().set_label('Wind speed',rotation=270)
For a very simple dataset:
x1, x2, x3 = [1,2,3], [2,3,4], [3,4,5]
y1 = y2 = y3 = [1, 2, 3]
z1, z2, z3 = [1,2,3], [4,5,6], [7,8,9]
scatter has a norm argument. Using the same norm for all scatters ensures that the colorbar produced by any of the plots (hence also the last) is the same for all scatter plots.
The norm can be a Normalize instance, to which minimum and maximum value are set and which produces a linear scaling in between. Of course you can also use any other norm provided in matplotlib.colors like PowerNorm, LogNorm, etc.
mini, maxi = 0, 2 # or use different method to determine the minimum and maximum to use
norm = plt.Normalize(mini, maxi)
plt.scatter(x1, y1, c=z1,cmap='viridis_r',marker='s', norm=norm)
plt.scatter(x2, y2, c=z2,cmap='viridis_r',marker='o', norm=norm)
plt.scatter(x3, y3, c=z3,cmap='viridis_r',marker='^', norm=norm)
plt.colorbar().set_label('Wind speed',rotation=270)
I am looking for something similar to arrangeGrob in R:
I have a function (say, function FUN1) that creates a plot with subplots. The number of subplots FUN1 creates may vary and the plot itself is quite complex. I have two other functions FUN2 and FUN3 which also create plots of varying structure.
Is there a simple way to define/arrange an overall GRID, for example a simple 3 rows 1 column style and simply pass
FUN1 --> GRID(row 1, col 1)
FUN2 --> GRID(row 2, col 1)
FUN3 --> GRID(row 3, col 1)
afterwards such that the complicated plot generated by FUN1 gets plotted in in row 1, the plot generated by FUN2 in row 2 and so on, without specifying the subplot criteria in the FUNs before?
The usual way to create plots with matplotlib would be to create some axes first and then plot to those axes. The axes can be set up on a grid using plt.subplots, figure.add_subplot, plt.subplot2grid or more sophisticated, using GridSpec.
Once those axes are created, they can be given to functions, which plot content to the axes. The following would be an example where 6 axes are created and 3 different functions are used to plot to them.
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
def func1(ax, bx, cx):
x = np.arange(3)
x2 = np.linspace(-3,3)
y1 = [1,2,4]
y2 = [3,2.5,3.4]
f = lambda x: np.exp(-x**2)
ax.bar(x-0.5, y1, width=0.4)
ax.bar(x, y2, width=0.4)
bx.plot(x,y1, label="lab1")
bx.scatter(x,y2, label="lab2")
bx.legend()
cx.fill_between(x2, f(x2))
def func2(ax, bx):
x = np.arange(1,18)/1.9
y = np.arange(1,6)/1.4
z = np.outer(np.sin(x), -np.sqrt(y)).T
ax.imshow(z, aspect="auto", cmap="Purples_r")
X, Y = np.meshgrid(np.linspace(-3,3),np.linspace(-3,3))
U = -1-X**2+Y
V = 1+X-Y**2
bx.streamplot(X, Y, U, V, color=U, linewidth=2, cmap="autumn")
def func3(ax):
data = [sorted(np.random.normal(0, s, 100)) for s in range(2,5)]
ax.violinplot(data)
gs = gridspec.GridSpec(3, 4,
width_ratios=[1,1.5,0.75,1], height_ratios=[3,2,2] )
ax1 = plt.subplot(gs[0:2,0])
ax2 = plt.subplot(gs[2,0:2])
ax3 = plt.subplot(gs[0,1:3])
ax4 = plt.subplot(gs[1,1])
ax5 = plt.subplot(gs[0,3])
ax6 = plt.subplot(gs[1:,2:])
func1(ax1, ax3, ax5)
func3(ax2)
func2(ax4, ax6)
plt.tight_layout()
plt.show()
This is related to this and this question.
I have a sequence of figures and subplots that have all very similar settings. However, I can't seem to find a way to set them all at the same time. Here's a simplified version (I generally work with more instances):
fspec = plt.figure(1)
spC = fspec.add_subplot(211)
spC.set_title('Surface concentrations')
spC.grid(True)
spC.set_ylim(1e-3, None)
spT = fspec.add_subplot(212, sharex=spC)
spT.set_title('Surface temperature')
spT.grid(True)
spT.set_ylim(1e-3, None)
fener = plt.figure(2)
enC = fener.add_subplot(211)
enC.set_title('Surface concentrations')
enC.grid(True)
enC.set_ylim(1e-3, None)
enT = fener.add_subplot(212, sharex=enC)
enT.set_title('Surface temperature')
enT.grid(True)
enT.set_ylim(1e-3, None)
I feel like there should be a way to apply something to every subplot open, or AT LEAST every subplot in a figure. Something like
fspec.set_global_grid(True)
fspec.set_global_ylim(1e-3, None)
But I can't find it.
I took a look at some of the previous but none of them seem to work for me, since I don't work with one figure or axis at a time, I work with all of them kind of at the same time.
Cheers.
Some settings concerning mostly the style of the figure can be set globally using the matplotlib rc parameters.
For example, setting the grid on throughout the script, put
plt.rcParams['axes.grid'] = True
at the beginning of your file (after the imports).
Other things like axis limits are really specific to the plot itself, and there is no global parameter for that. But you can still go the way, as outlined in the linked questions, i.e. write your own function that does most of the stuff you need.
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['axes.grid'] = True
def plotfunction(fig, x1, y1, x2, y2,
title1 = 'Surface concentrations',
title2 = 'Surface temperature', **kwargs ):
ax = fig.add_subplot(211)
ax2 = fig.add_subplot(212, sharex=ax)
ax.set_title(title1)
ax2.set_title(title2)
ax.set_ylim(1e-3, None)
ax2.set_ylim(1e-3, None)
ax.plot(x1, y1, **kwargs)
ax2.plot(x2, y2, **kwargs)
fspec = plt.figure(1)
fener = plt.figure(2)
x1, y1, x2, y2 = np.loadtxt("spectrum.txt", unpack=True)
plotfunction(fspec,x1, y1, x2, y2)
x1, y1, x2, y2 = np.loadtxt("energy.txt", unpack=True)
plotfunction(fener,x1, y1, x2, y2, linewidth=3)