My program produces two arrays and I have to plot one of them in the X axis and the other one on the Y axis (the latter are taken from the row of a matrix).
The problem is that I have to repeat this operation for a number of times (I am running a loop) but all the graphs should be on the same plot. Every time the dots should be of a different colour. Then I should save the file.
I have tried with
for row in range(6):
plt.plot(betaArray, WabArray[row], 'ro')
plt.show()
but this only shows one plot each for every iteration and always of the same colour.
You could try something like this:
import numpy as np
import matplotlib.pylab as plt
import matplotlib as mpl
x = [1,2,3,4]
y_mat = np.array([[1,2,3,4], [5,6,7,8]])
n, _ = y_mat.shape
colors = mpl.cm.rainbow(np.linspace(0, 1, n))
fig, ax = plt.subplots()
for color, y in zip(colors, y_mat):
ax.scatter(x, y, color=color)
plt.show()
This creates n colors from the rainbow color map and uses scatter to plot the points in the respective color. You may want to switch to a different color map or even choose the colors manually.
This is the result:
Related
I would like to create a legend for a scatter plot similar to scatter_demo.py The legend should show the color and size of the the largest and smallest points. Here is what I have so far:
import numpy as np
import matplotlib.pyplot as plt
N = 10
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (10 * np.random.rand(N) + 3)**2
plt.scatter(x, y, s=area, c=colors, edgecolors='face')
b_idx = area.argmax()
s_idx = area.argmin()
plt.scatter(x[b_idx], y[b_idx], s=area[b_idx], c=colors[b_idx],label='big')
plt.scatter(x[s_idx], y[s_idx], s=area[s_idx], c=colors[s_idx], label='small')
plt.legend(title = 'Size and Color')
plt.show()
my_plot
This does not put the correct colors into the legend. Also my approach double plots points. This creates a small crescent behind the original point.
The color of the scatter points is determined from the input array colors by mapping the input values to a colormap. (In the case here, the colormap is the default colormap, implicitely set in the scatter call.)
However, the color used in the legend is the standard color from the colorcycle.
As #DavidG pointed out in his solution, one way to overcome this is to use an array of rgb colors instead of an array of values to specify the colors of the points. While this solves the issue of coloring the legend entries, it has 2 major drawbacks: (a) You loose the ability to use a colormap and (b) In a real world case, the data to show as colors are not colors themselves, but some scalar quantity to be visualized using color.
It is therefore highly beneficial to stick to the input colors array and modify the code afterwards to show the respective minimally and maximally sized points in color in the legend. To this end, one would need to find out which color they have and provide this to the proxy artists used to create the legend.
This can be done using the to_rgba method from the the scatter plot itself (which is a ScalarMappable object).
Finally in order not to have the points drawn twice in the plot, one can simply provide empty coordinate arrays to the proxy scatters.
import numpy as np; np.random.seed(20)
import matplotlib.pyplot as plt
N = 10
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (10 * np.random.rand(N) + 3)**2
sc = plt.scatter(x, y, s=area, c=colors, edgecolors='face')
b_idx = area.argmax()
s_idx = area.argmin()
plt.scatter([], [], s=area[b_idx], c=sc.to_rgba(colors[b_idx]),label='big')
plt.scatter([], [], s=area[s_idx], c=sc.to_rgba(colors[s_idx]),label='small')
plt.legend(title = 'Size and Color')
plt.show()
The problem lies with your array colors. It needs to be a 3xN array representing N RGB colours. Therefore, to fix the code that you have provided, use the following line:
colors = np.random.rand(N,3)
Then, keeping the rest of the code unchanged the following graph is produced:
I am used to work with plots that change over the time in order to show differences when a parameter is changed. Here I provide an easy example
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111)
ax.grid(True)
x = np.arange(-3, 3, 0.01)
for j in range(1, 15):
y = np.sin(np.pi*x*j) / (np.pi*x*j)
line, = ax.plot(x, y)
plt.draw()
plt.pause(0.5)
line.remove()
You can clearly see that increasing the paramter j the plot becames narrower and narrower.
Now if I want to do the some job with a counter plot than I just have to remove the comma after "line". From my understanding this little modification comes from the fact that the counter plot is not an element of a tuple anymore, but just an attribute as the counter plot completely "fill up" all the space available.
But it looks like there is no way to remove (and plot again) an histogram. Infact if type
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111)
ax.grid(True)
x = np.random.randn(100)
for j in range(15):
hist, = ax.hist(x, 40)*j
plt.draw()
plt.pause(0.5)
hist.remove()
It doesn't matter whether I type that comma or not, I just get a message of error.
Could you help me with this, please?
ax.hist doesn't return what you think it does.
The returns section of the docstring of hist (access via ax.hist? in an ipython shell) states:
Returns
-------
n : array or list of arrays
The values of the histogram bins. See **normed** and **weights**
for a description of the possible semantics. If input **x** is an
array, then this is an array of length **nbins**. If input is a
sequence arrays ``[data1, data2,..]``, then this is a list of
arrays with the values of the histograms for each of the arrays
in the same order.
bins : array
The edges of the bins. Length nbins + 1 (nbins left edges and right
edge of last bin). Always a single array even when multiple data
sets are passed in.
patches : list or list of lists
Silent list of individual patches used to create the histogram
or list of such list if multiple input datasets.
So you need to unpack your output:
counts, bins, bars = ax.hist(x, 40)*j
_ = [b.remove() for b in bars]
Here the right way to iteratively draw and delete histograms in matplotlib
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize = (20, 10))
ax = fig.add_subplot(111)
ax.grid(True)
for j in range(1, 15):
x = np.random.randn(100)
count, bins, bars = ax.hist(x, 40)
plt.draw()
plt.pause(1.5)
t = [b.remove() for b in bars]
I have been trying to do a simple heatmap with pcolormesh and I run into this weird effect with some sizes, which add empty white columns. If I create a 10x30, as below, it works perfectly.
from matplotlib import pyplot as plt
import numpy as np
d = []
for x in range(10):
d.append([])
for y in range(30):
d[-1].append(y)
plt.pcolormesh(np.array(d))
plt.show()
But, if I try with a 10x37:
from matplotlib import pyplot as plt
import numpy as np
d = []
for x in range(10):
d.append([])
for y in range(34):
d[-1].append(y)
plt.pcolormesh(np.array(d))
plt.show()
I got those weird white columns at the end. This seems to hold for a couple of values (10x11 fails, but 10x12 works... I wasn't able to discerna pattern.
Is there any way to remove them, maybe forcing the final size of the heatmap?
In terms of axes limits and aspect ratio, pcolormesh acts less like an image, and more like a line plot. If you want to show the elements of an array as pixels, you can use imshow. Alternatively, you can set the x-limits of your pcolormesh plot. Consider the following example:
from matplotlib import pyplot as plt
import numpy as np
d1 = []
d2 = []
for x in range(10):
d1.append([])
d2.append([])
for y in range(30):
d1[-1].append(y+x)
for y in range(37):
d2[-1].append(y+x)
fig, axes = plt.subplots(ncols=4, figsize=(10,4))
# your first two examples
axes[0].pcolormesh(np.array(d1), cmap=plt.cm.coolwarm)
axes[1].pcolormesh(np.array(d2), cmap=plt.cm.coolwarm)
# let's reset the x-lims on this
axes[2].pcolormesh(np.array(d2), cmap=plt.cm.coolwarm)
axes[2].set_ylim(bottom=0, top=d2.shape[0])
axes[2].set_xlim(left=0, right=d2.shape[1])
# or more concisely (thanks Joe):
axes[2].axis('tight')
# and use imshow here
axes[3].imshow(np.array(d2), cmap=plt.cm.coolwarm)
and that gives us:
I want to color the line in a plot based on the following of a data set on the y axis.
if data > 0:
color = 'r'
if data = 0:
color = 'g'
if data < 0:
color = 'b'
Unfortunately I only know how to color the entire data set one color. I also couldn't find anything on the web. I'm assuming there is a way to do this without breaking up the dataset for every time the color changes.
Below is an example of plotting the data with just one color.
import matplotlib.pyplot as plt
import numpy as np
# Simple data
x = np.linspace(0, 2 * np.pi, 400)
data = np.sin(x ** 2)
#plot
f, ax = plt.subplots()
ax.plot(x, data, color='r')
plt.show()
The color parameter actually can take a list as an argument. For example, here's a simple bit of code that sets up a list of colors based on whether the data is positive or negative:
colors = []
for item in data:
if item < 0:
colors.append('r')
else:
colors.append('g')
then simply:
ax.bar(x, data, color=colors)
Edit: So I tested it, and it appears that my answer is only applicable for bar graphs. I couldn't find anything in the matplotlib documentation that seemed to indicate that coloring a line plot with multiple colors was possible. I did, however find this site, which I believe has the information you want. The guy there defines his own function to achieve it.
Using the file at my link, here is an equivalent version for a line graph:
cmap = ListedColormap(['r', 'g']) # use the colors red and green
norm = BoundaryNorm([-1000,0,1000], cmap.N) # map red to negative and green to positive
# this may work with just 0 in the list
fig, axes = plt.subplots()
colorline(x, data, data, cmap=cmap, norm=norm)
plt.xlim(x.min(), x.max())
plt.ylim(data.min(), data.max())
plt.show()
The last three arguments of colorline here tell it the color data and how to map it.
i have load profile data where x axis is load profile such that for multiple same values of x (constant load) i have different values for y.
till now in excel i used to line plot y and right click graph->selec data->change hoizontal axis data by providing it range o x axis data and that used to give me the graph
the problem i have is when i try to give
plot(x,y), matplotlib plots y for unique vals of x ie it neglects out all the remaining value of for same value of x.
and when i plot with plot(y) i get sequence numbers on x axis
i tried xticks([0,5,10,15]) for checking out but couldn't get the required result.
my question is
is it possible to plot a graph in a similar fashion as of excel
the other alternative i could think of was plotting plot(y and plot (x) with same horizontal axis it atleast gives a pictorial idea but is there any means to do it the excel way??
From your description, it sounds to me like you want to use the "scatter" plotting command instead of the "plot" plotting command. This will allow the use of redundant x-values. Sample code:
import numpy as np
import matplotlib.pyplot as plt
# Generate some data that has non-unique x-values
x1 = np.linspace(1,50)
y1 = x1**2
y2 = 2*x1
x3 = np.append(x1,x1)
y3 = np.append(y1,y2)
# Now plot it using the scatter command
# Note that some of the abbreviations that work with plot,
# such as 'ro' for red circles don't work with scatter
plt.scatter(x3,y3,color='red',marker='o')
As I mentioned in the comments, some of the handy "plot" shortcuts don't work with "scatter" so you may want to check the documentation: http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.scatter
If you want to plot y-values for a given x-values, you need to get the index which has same x-values. If you are working with numpy then you can try
import pylab as plt
import numpy as np
x=np.array([1]*5+[2]*5+[3]*5)
y=np.array([1,2,3,4,5]*3)
idx=(x==1) # Get the index where x-values are 1
plt.plot(y[idx],'o-')
plt.show()
If you are working with lists you can get the index by
# Get the index where x-values are 1
idx=[i for i, j in enumerate(x) if j == 1]
just answering own question,found this around when i had posted this question years back :)
def plotter(y1,y2,y1name,y2name):
averageY1=float(sum(y1)/len(y1))
averageY2=float(sum(y2)/len(y2))
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(y1,'b-',linewidth=2.0)
ax1.set_xlabel("SNo")
# Make the y2-axis label and tick labels match the line color.
ax1.set_ylabel(y1name, color='b')
for tl in ax1.get_yticklabels():
tl.set_color('b')
ax1.axis([0,len(y2),0,max(y1)+50])
ax2 = ax1.twinx()
ax2.plot(y2, 'r-')
ax2.axis([0,len(y2),0,max(y2)+50])
ax2.set_ylabel(y2name, color='r')
for tl in ax2.get_yticklabels():
tl.set_color('r')
plt.title(y1name + " vs " + y2name)
#plt.fill_between(y2,1,y1)
plt.grid(True,linestyle='-',color='0.75')
plt.savefig(y1name+"VS"+y2name+".png",dpi=200)
You can use
import numpy as np
import matplotlib.pyplot as plt
x = np.array([1, 1, 1, 2, 2, 2])
y = np.array([1, 2, 1, 5, 6, 7])
fig, ax = plt.subplots()
ax.plot(np.arange(len(x)), y)
ax.set_xticklabels(x)
plt.show()