I am trying to print about 42 plots in 7 rows, 6 columns, but the printed output in jupyter notebook, shows all the plots one under the other. I want them in (7,6) format for comparison. I am using matplotlib.subplot2grid() function.
Note: I do not get any error, and my code works, however the plots are one under the other, vs being in a grid/ matrix form.
Here is my code:
def draw_umap(n_neighbors=15, min_dist=0.1, n_components=2, metric='euclidean', title=''):
fit = umap.UMAP(
n_neighbors=n_neighbors,
min_dist=min_dist,
n_components=n_components,
metric=metric
)
u = fit.fit_transform(df);
plots = []
plt.figure(0)
fig = plt.figure()
fig.set_figheight(10)
fig.set_figwidth(10)
for i in range(7):
for j in range(6):
plt.subplot2grid((7,6), (i,j), rowspan=7, colspan=6)
plt.scatter(u[:,0], u[:,1], c= df.iloc[:,0])
plt.title(title, fontsize=8)
n=range(7)
d=range(6)
for n in n_neighbors:
for d in dist:
draw_umap(n_neighbors=n, min_dist=d, title="n_neighbors={}".format(n) + " min_dist={}".format(d))
I did refer to this post to get the plots in a grid and followed the code.
I also referred to this post, and modified my code for size of the fig.
Is there a better way to do this using Seaborn?
What am I missing here? Please help!
Both questions that you have linked contain solutions that seem more complicated than necessary. Note that subplot2grid is useful only if you want to create subplots of varying sizes which I understand is not your case. Also note that according to the docs Using GridSpec, as demonstrated in GridSpec demo is generally preferred, and I would also recommend this function only if you want to create subplots of varying sizes.
The simple way to create a grid of equal-sized subplots is to use plt.subplots which returns an array of Axes through which you can loop to plot your data as shown in this answer. That solution should work fine in your case seeing as you are plotting 42 plots in a grid of 7 by 6. But the problem is that in many cases you may find yourself not needing all the Axes of the grid, so you will end up with some empty frames in your figure.
Therefore, I suggest using a more general solution that works in any situation by first creating an empty figure and then adding each Axes with fig.add_subplot as shown in the following example:
import numpy as np # v 1.19.2
import matplotlib.pyplot as plt # v 3.3.4
# Create sample dataset
rng = np.random.default_rng(seed=1) # random number generator
nvars = 8
nobs = 50
xs = rng.uniform(size=(nvars, nobs))
ys = rng.normal(size=(nvars, nobs))
# Create figure with appropriate space between subplots
fig = plt.figure(figsize=(10, 8))
fig.subplots_adjust(hspace=0.4, wspace=0.3)
# Plot data by looping through arrays of variables and list of colors
colors = plt.get_cmap('tab10').colors
for idx, x, y, color in zip(range(len(xs)), xs, ys, colors):
ax = fig.add_subplot(3, 3, idx+1)
ax.scatter(x, y, color=color)
This could be done in seaborn as well, but I would need to see what your dataset looks like to provide a solution relevant to your case.
You can find a more elaborate example of this approach in the second solution in this answer.
Related
I am currently taking a Matplotlib class. I was given an image to create the image as a 3D subplot 4 times at 4 different angles. It's a linear plot. As the data changes the plots change colors. As it's an image, I'm not certain where the actual changes start. I don't want an exact answer, just an explanation of how this would work. I have found many methods for doing this for a small list but this has 75 data points and I can't seem to do it without adding 75 entries.
I've also tried to understand cmap but I am confused on it as well.
Also, it needs to done without Seaborn.
This is part of the photo.
I am finding your question a little bit hard to understand. What I think you need is a function to map the input x/y argument onto a colour in your chosen colour map. See the below example:
import numpy as np
import matplotlib.pyplot
def number_to_colour(number, total_number):
return plt.cm.rainbow(np.linspace(0,1.,total_number))[list(number)]
x = np.arange(12)
y = x*-3.
z = x
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z, c=number_to_colour(x, len(x)))
plt.show()
plt.cm.rainbow(np.linspace(0,1.,total_number)) creates an array of colours of length total_number evenly spaced spaced across the colour map (in this case rainbow). Modifying the indexing of this array (or changing np.linspace to another function with the desired scaling), should give you the colour scaling that you need.
This question already has an answer here:
Drawing a colorbar aside a line plot, using Matplotlib
(1 answer)
Closed 1 year ago.
Let's say I have one figure with a certain number of plots, which resembles like this one:
where the colors of the single plots are decided automatically by matplotlib. The code to obtain this is very simple:
for i in range(len(some_list)):
x, y = some_function(dataset, some_list[i])
plt.plot(x, y)
Now suppose that all these lines depend on a third variable z. I would like to include this information plotting the given lines with a color that gives information about the magnitude of z, possibly using a colormap and a colorbar on the right side of the figure. What would you suggest me to do? I exclude to use a legend since in my figures I have many more lines that the ones I am showing. All information I can find is about how to draw one single line with different colors, but this is not what I am looking for. I thank you in advance!
Here it is some code that, in my opinion, you can easily adapt to your problem
import numpy as np
import matplotlib.pyplot as plt
from random import randint
# generate some data
N, vmin, vmax = 12, 0, 20
rd = lambda: randint(vmin, vmax)
segments_z = [((rd(),rd()),(rd(),rd()),rd()) for _ in range(N)]
# prepare for the colorization of the lines,
# first the normalization function and the colomap we want to use
norm = plt.Normalize(vmin, vmax)
cm = plt.cm.rainbow
# most important, plt.plot doesn't prepare the ScalarMappable
# that's required to draw the colorbar, so we'll do it instead
sm = plt.cm.ScalarMappable(cmap=cm, norm=norm)
# plot the segments, the segment color depends on z
for p1, p2, z in segments_z:
x, y = zip(p1,p2)
plt.plot(x, y, color=cm(norm(z)))
# draw the colorbar, note that we pass explicitly the ScalarMappable
plt.colorbar(sm)
# I'm done, I'll show the results,
# you probably want to add labels to the axes and the colorbar.
plt.show()
I need to plot changing molecule numbers against time. But I'm also trying to investigate the effects of parallel processing so I'm trying to avoid writing to global variables. At the moment I have the following two numpy arrays tao_all, contains all the time points to be plotted on the x-axis and popul_num_all which contains the changing molecule numbers to be plotted on the y-axis.
The current code I've got for plotting is as follows:
for i, label in enumerate(['Enzyme', 'Substrate', 'Enzyme-Substrate complex', 'Product']):
figure1 = plt.plot(tao_all, popul_num_all[:, i], label=label)
plt.legend()
plt.tight_layout()
plt.show()
I need to encapsulate this in a function that takes the above arrays as the input and returns the graph. I've read a couple of other posts on here that say I should write my results to an axis and return the axis? But I can't quite get my head around applying that to my problem?
Cheers
def plot_func(x, y):
fig,ax = plt.subplots()
ax.plot(x, y)
return fig
Usage:
fig = plot_func([1,2], [3,4])
Alternatively you may want to return ax. For details about Figure and Axes see the docs. You can get the axes array from the figure by fig.axes and the figure from the axes by ax.get_figure().
In addition to above answer, I can suggest you to use matplotlib animation.FuncAnimation method if you are working with the time series and want to make your visualization better.
You can find the details here https://matplotlib.org/api/_as_gen/matplotlib.animation.FuncAnimation.html
So, I have a numpy.ndarray called CT with shape (10, 500).
Each row is a function and defined over the x-variables called Gm. Gm is a numpy.ndarray with shape (1,500).
I need to graph the 10 functions in the CT matrix (as a function of Gm) in one graph and try the following:
# consumption functions over time
plt.figure(figsize=(10,10))
TimeSteps = CT.shape[0]
for t in range(0,TimeSteps):
plt.plot(Gm,CT[t].reshape(1,DiscG),'go',label='t')
plt.show()
This works, but all graphs are shown with the same color (green) and it is not possible to distinguish if the graph is t = 0, 1, 2, etc.
Any idea as to how you get plt to choose a different color for each graph and make it possible to label them and put it in a text box.
It is common curtosy when asking a question to have a minimal and verifiable example. The questions you posed as problems are actually examples of the code working as intended but not as you want them to be. Here is an example of scatter dots with different colors and different labels as you posed on your question and answered by me and #DavidG.
import matplotlib.pyplot as plt
import numpy as np
# dummy data
x = np.random.rand(10, 100)
fig, ax = plt.subplots()
[ax.plot(xi, marker = 'o', label = idx) for idx, xi in enumerate(x)]
ax.legend()
fig.show()
The color cycles here stem from the standard color map used by matplotlib if you want to use specific colors or change the standard cycles please look at the documentation provided by matplotlib
OK - found another simpler way ... simply to transpose the input:
plt.figure(figsize=(10,10))
plt.plot(Gm.transpose(),CT.transpose(),marker='o')
plt.show()
That way the whole function gets a unique color, and it seems resolved. So my initial guess running a for loop was too complicated.
I've got a lot of points to plot and am noticing that plotting them individually in matplotlib takes much longer (more than 100 times longer, according to cProfile) than plotting them all at once.
However, I need to color code the points (based on data associated with each one) and can't figure out how to plot more than one color for a given call to Axes.plot(). For example, I can get a result similar to the one I want with something like
fig, ax = matplotlib.pyplot.subplots()
rands = numpy.random.random_sample((10000,))
for x in range(10000):
ax.plot(x, rands[x], 'o', color=str(rands[x]))
matplotlib.pyplot.show()
but would rather do something much faster like
fig, ax = matplotlib.pyplot.subplots()
rands = numpy.random.random_sample((10000,))
# List of colors doesn't work
ax.plot(range(10000), rands, 'o', color=[str(y) for y in rands])
matplotlib.pyplot.show()
but providing a list as the value for color doesn't work in this way.
Is there a way to provide a list of colors (and for that matter, edge colors, face colors , shapes, z-order, etc.) to Axes.plot() so that each point can potentially be customized, but all points can be plotted at once?
Using Axes.scatter() seems to get part way there, since it allows for individual setting of point color; but color is as far as that seems to go. (Axes.scatter() also lays out the figure completely differently.)
It is about 5 times faster for me to create the objects (patches) directly. To illustrate the example, I have changed the limits (which have to be set manually with this method). The circle themselves are draw with matplotlib.path.Path.circle. Minimal working example:
import numpy as np
import pylab as plt
from matplotlib.patches import Circle
from matplotlib.collections import PatchCollection
fig, ax = plt.subplots(figsize=(10,10))
rands = np.random.random_sample((N,))
patches = []
colors = []
for x in range(N):
C = Circle((x/float(N), rands[x]), .01)
colors.append([rands[x],rands[x],rands[x]])
patches.append(C)
plt.axis('equal')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
collection = PatchCollection(patches)
collection.set_facecolor(colors)
ax.add_collection(collection)
plt.show()