x axis with duplicate values (loading profile) plot in matplotlib - python

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()

Related

Python: Problem with plotting from one point in Y to many points on X axis

I have one point on Y axis and many on X axis and i want to do straight lines from this one Y point to each X (shape of triangle).
plt.plot([P], [TR], 'k')
plt.xlabel('CENTERLINE')
plt.ylabel('RADIUS')
plt.show()
Where TR is my single point declared earlier and P are float points (first i create P = np.zeros((n+1)) and after that using for loop i put there values).
plt.show() returns empty chart (without any plot)
Here is the example how it should look like
When handling many lines at once it may be a good idea to use a LineCollection object:
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import numpy as np
pos_fixed = np.array([0, 35])
lines = np.array([[[pos, 0], pos_fixed] for pos in np.arange(0, 50, 2)])
line_coll = LineCollection(lines)
fig, ax = plt.subplots()
ax.add_collection(line_coll)
plt.xlim([0, lines[:,:,0].max()])
plt.ylim([0, lines[:,:,1].max()])
This way you can handle your plot more easily (and it's also faster if you have many lines).
Result:
Those lines are not a contiguous plot, so you'll need to plot them separately. You could make it a single line that goes up and down (and up and down and up and down...) but I think this makes more sense as separate lines. Consider:
import matplotlib.pyplot as plt
originpoint = (0, 5)
yfloor = 0
xvalues = [0, 1, 2, 3, 4]
for x in xvalues:
plt.plot((originpoint[0], x), (originpoint[1], yfloor))
plt.show()

Plot 2D histogram data with pcolormesh

I need to plot a binned statistic, as one would get from scipy.stats.binned_statistic_2d. Basically, that means I have edge values and within-bin data. This also means I cannot (to my knowledge) use plt.hist2d. Here's a code snippet to generate the sort of data I might need to plot:
import numpy as np
x_edges = np.arange(6)
y_edges = np.arange(6)
bin_values = np.random.randn(5, 5)
One would imagine that I could use pcolormesh for this, but the issue is that pcolormesh does not allow for bin edge values. The following will only plot the values in bins 1 through 4. The 5th value is excluded, since while pcolormesh "knows" that the value at 4.0 is some value, there is no later value to plot, so the width of the 5th bin is zero.
import matplotlib.pyplot as plt
X, Y = np.broadcast_arrays(x_edges[:5, None], y_edges[None, :5])
plt.figure()
plt.pcolormesh(X, Y, bin_values)
plt.show()
I can get around this with an ugly hack by adding an additional set of values equal to the last values:
import matplotlib.pyplot as plt
X, Y = np.broadcast_arrays(x_edges[:, None], y_edges[None, :])
dummy_bin_values = np.zeros([6, 6])
dummy_bin_values[:5, :5] = bin_values
dummy_bin_values[5, :] = dummy_bin_values[4, :]
dummy_bin_values[:, 5] = dummy_bin_values[:, 4]
plt.figure()
plt.pcolormesh(X, Y, dummy_bin_values)
plt.show()
However, this is an ugly hack. Is there any cleaner way to plot 2D histogram data with bin edge values? "No" is possibly the correct answer, but convince me that's the case if it is.
I do not understand the problem with any of the two options. So here is simly a code which uses both, numpy histogrammed data with pcolormesh, as well as simply plt.hist2d.
import numpy as np
import matplotlib.pyplot as plt
x_edges = np.arange(6)
y_edges = np.arange(6)
data = np.random.rand(340,2)*5
### using numpy.histogram2d
bin_values,_,__ = np.histogram2d(data[:,0],data[:,1],bins=(x_edges, y_edges) )
X, Y = np.meshgrid(x_edges,y_edges)
fig, (ax,ax2) = plt.subplots(ncols=2)
ax.set_title("numpy.histogram2d \n + plt.pcolormesh")
ax.pcolormesh(X, Y, bin_values.T)
### using plt.hist2d
ax2.set_title("plt.hist2d")
ax2.hist2d(data[:,0],data[:,1],bins=(x_edges, y_edges))
plt.show()
Of course this would equally work with scipy.stats.binned_statistic_2d.

Matplotlib: add twin y axis without using its values in the plots

This is to clarify the question title. Say you have four lists of integers, with which you want to produce a scatter plot:
a=[3,7,2,8,12,17]
b=[9,4,11,7,6,3]
c=[9,3,17,13,10,5]
d=[5,1,1,14,5,8]
You also have a function, for simplicity f(x)=1/x, that applies to all lists, so that:
from __future__ import division
a1=[1/i for i in a]
b1=[1/i for i in b]
c1=[1/i for i in c]
d1=[1/i for i in d]
My question: how to add a second y axis, knowing that the values returned by the function range from 0.06 to 1.0, without using any of the a1, b1, c1, d1 lists in the scatter plots?
What I am saying is: if you produce the following scatter plots in the traditional way, how can you then add the second y axis based on the values of a1, b1, c1, d1, without having any series using them in the plot itself?
import matplotlib.pyplot as plt
plt.scatter(a,b,c='red',label='reds')
plt.scatter(c,d,c='blue',label='blues')
plt.legend(loc='best')
This is the scatter without the second y axis:
And this is a made up version of the same one, including the second y axis discussed so far:
NB: This question is different from this, in that I am not trying to plot with different scales. I only want to add a second axis with the relevant values.
To make sure the numbers on the new axis are in the corresponding position to their inverses:
import matplotlib.pylab as plt
a=[3,7,2,8,12,17]
b=[9,4,11,7,6,3]
c=[9,3,17,13,10,5]
d=[5,1,1,14,5,8]
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(a,b,c='red',label='reds')
ax.scatter(c,d,c='blue',label='blues')
ax.legend(loc='best')
ax.set_ylabel('Y')
# make shared y axis
axi = ax.twinx()
# set limits for shared axis
axi.set_ylim(ax.get_ylim())
# set ticks for shared axis
inverse_ticks = []
label_format = '%.3f'
for tick in ax.get_yticks():
if tick != 0:
tick = 1/tick
inverse_ticks.append(label_format % (tick,))
axi.set_yticklabels(inverse_ticks)
axi.set_ylabel('1/Y')
fig.tight_layout()
fig.show()
And you can also do it for the X axis:
# make shared x axis
xaxi = ax.twiny()
# set limits for shared axis
xaxi.set_xlim(ax.get_xlim())
# set ticks for shared axis
inverse_ticks = []
label_format = '%.3f'
for tick in ax.get_xticks():
if tick != 0:
tick = 1/tick
inverse_ticks.append(label_format % (tick,))
xaxi.set_xticklabels(inverse_ticks)
xaxi.set_xlabel('1/X')
Just make shared y axis and set desired limits and ticks for new axis like here:
import matplotlib.pylab as plt
import numpy as np
a=[3,7,2,8,12,17]
b=[9,4,11,7,6,3]
c=[9,3,17,13,10,5]
d=[5,1,1,14,5,8]
plt.scatter(a,b,c='red',label='reds')
plt.scatter(c,d,c='blue',label='blues')
plt.legend(loc='best')
ax = plt.gca()
# make shared y axis
ax2 = ax.twinx()
# set limits for shared axis
ax2.set_ylim([0,1])
# set ticks for shared axis
plt.yticks(np.arange(0.06, 1, 0.14))
plt.show()

How to remove an histogram in Matplotlib

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]

Python - Line colour of 3D parametric curve

I have 2 lists tab_x (containe the values of x) and tab_z (containe the values of z) which have the same length and a value of y.
I want to plot a 3D curve which is colored by the value of z. I know it's can be plotted as a 2D plot but I want to plot a few of these plot with different values of y to compare so I need it to be 3D.
My tab_z also containe negatives values
I've found the code to color the curve by time (index) in this question but I don't know how to transforme this code to get it work in my case.
Thanks for the help.
I add my code to be more specific:
fig8 = plt.figure()
ax8 = fig8.gca(projection = '3d')
tab_y=[]
for i in range (0,len(tab_x)):
tab_y.append(y)
ax8.plot(tab_x, tab_y, tab_z)
I have this for now
I've tried this code
for i in range (0,len(tab_t)):
ax8.plot(tab_x[i:i+2], tab_y[i:i+2], tab_z[i:i+2],color=plt.cm.rainbow(255*tab_z[i]/max(tab_z)))
A total failure:
Your second attempt almost has it. The only change is that the input to the colormap cm.jet() needs to be on the range of 0 to 1. You can scale your z values to fit this range with Normalize.
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import colors
fig = plt.figure()
ax = fig.gca(projection='3d')
N = 100
y = np.ones((N,1))
x = np.arange(1,N + 1)
z = 5*np.sin(x/5.)
cn = colors.Normalize(min(z), max(z)) # creates a Normalize object for these z values
for i in xrange(N-1):
ax.plot(x[i:i+2], y[i:i+2], z[i:i+2], color=plt.cm.jet(cn(z[i])))
plt.show()

Categories

Resources