I am using matplotlib to plot a 2D array but in the plot I am not getting curves, it only shows the axis. Following is my code:
posx = []
posy = []
for i in range(1,37):
posx.append(data[i,0])
posy.append(data[i,1])
for j in range(2,507):
plt.plot(data[0,j],data[i,j])
print(posx,posy)
plt.show()
I have tried plt.plot(data[0,j],data[i,j],'.') which shows me a scatter plot which I don't want.
In your call to plot - plt.plot(data[0,j],data[i,j]), data[0,j] and data[i,j] are single numbers. plt.plot() tries to plot a line, however you are only passing a single x and a single y value. In order plot a line, you need at least 2 values for the x and y.
Your code can be simplified using slice notation which will remove the inner for loop:
for i in range(1,37):
plt.plot(data[0, 2:507], data[i, 2:507])
plt.show()
Related
I want to draw multiple plots in the same plot so I took 2d list in which for one parameter it's storing the values in the string format and I am using the for loop for the same but when I am plotting the larger values on y axis are coming below the smaller values
Here is the code snippet that might help to understand
m=['H','.','<','^','*','+','x','#']
cnt=0
for i in all:# here all has the row wise data to plot
matplotlib.pyplot.plot(l3,i,m[cnt])# l3 contains the values about the x axis
cnt=cnt+1
plt.xlabel("x")
plt.ylabel("y")
plt.legend(para,loc='best')# para contains the info about the y parameters
plt.show()
The graph is coming like this how to get 12000 above 0 in the graph
This is the plot I got how to rescale it so that all values comes in acsending order on y axis
You have to convert strings to floats before plotting
for i in all:# here all has the row wise data to plot
y = [float(ii) for ii in i]
matplotlib.pyplot.plot(l3, y, m[cnt])# l3 contains the values about the x axis
cnt=cnt+1
I am trying to plot two different lines from a same vector in python using Matplotlib. For this, I use an additional vector whose values on certain indices filter the general array to plot in a certain line. The code is:
import matplotlib.pyplot as plt
def visualize_method(general, changes):
'''Correctly plots the data to visualize reversals and trials'''
x = np.array([i for i in range(len(general))])
plt.plot(x[changes==0], general[changes==0],
x[changes==1], general[changes==1],
linestyle='--', marker='o')
plt.show()
When plotting the data, the result is:
As it can be observed, the y axis is "duplicated", how could I use the same y and x axis for this filtered plot?
I'm trying to visualise a dataset in 3D which consists of a time series (along y) of x-z data, using Python and Matplotlib.
I'd like to create a plot like the one below (which was made in Python: http://austringer.net/wp/index.php/2011/05/20/plotting-a-dolphin-biosonar-click-train/), but where the colour varies with Z - i.e. so the intensity is shown by a colormap as well as the peak height, for clarity.
An example showing the colormap in Z is (apparently made using MATLAB):
This effect can be created using the waterfall plot option in MATLAB, but I understand there is no direct equivalent of this in Python.
I have also tried using the plot_surface option in Python (below), which works ok, but I'd like to 'force' the lines running over the surface to only be in the x direction (i.e. making it look more like a stacked time series than a surface). Is this possible?
Any help or advice greatly welcomed. Thanks.
I have generated a function that replicates the matlab waterfall behaviour in matplotlib, but I don't think it is the best solution when it comes to performance.
I started from two examples in matplotlib documentation: multicolor lines and multiple lines in 3d plot. From these examples, I only saw possible to draw lines whose color varies following a given colormap according to its z value following the example, which is reshaping the input array to draw the line by segments of 2 points and setting the color of the segment to the z mean value between the 2 points.
Thus, given the input matrixes n,m matrixes X,Y and Z, the function loops over the smallest dimension between n,m to plot each line like in the example, by 2 points segments, where the reshaping to plot by segments is done reshaping the array with the same code as the example.
def waterfall_plot(fig,ax,X,Y,Z):
'''
Make a waterfall plot
Input:
fig,ax : matplotlib figure and axes to populate
Z : n,m numpy array. Must be a 2d array even if only one line should be plotted
X,Y : n,m array
'''
# Set normalization to the same values for all plots
norm = plt.Normalize(Z.min().min(), Z.max().max())
# Check sizes to loop always over the smallest dimension
n,m = Z.shape
if n>m:
X=X.T; Y=Y.T; Z=Z.T
m,n = n,m
for j in range(n):
# reshape the X,Z into pairs
points = np.array([X[j,:], Z[j,:]]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
lc = LineCollection(segments, cmap='plasma', norm=norm)
# Set the values used for colormapping
lc.set_array((Z[j,1:]+Z[j,:-1])/2)
lc.set_linewidth(2) # set linewidth a little larger to see properly the colormap variation
line = ax.add_collection3d(lc,zs=(Y[j,1:]+Y[j,:-1])/2, zdir='y') # add line to axes
fig.colorbar(lc) # add colorbar, as the normalization is the same for all, it doesent matter which of the lc objects we use
Therefore, plots looking like matlab waterfall can be easily generated with the same input matrixes as a matplotlib surface plot:
import numpy as np; import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from mpl_toolkits.mplot3d import Axes3D
# Generate data
x = np.linspace(-2,2, 500)
y = np.linspace(-2,2, 40)
X,Y = np.meshgrid(x,y)
Z = np.sin(X**2+Y**2)
# Generate waterfall plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
waterfall_plot(fig,ax,X,Y,Z)
ax.set_xlabel('X') ; ax.set_xlim3d(-2,2)
ax.set_ylabel('Y') ; ax.set_ylim3d(-2,2)
ax.set_zlabel('Z') ; ax.set_zlim3d(-1,1)
The function assumes that when generating the meshgrid, the x array is the longest, and by default the lines have fixed y, and its the x coordinate what varies. However, if the size of the y dimension is larger, the matrixes are transposed, generating the lines with fixed x. Thus, generating the meshgrid with the sizes inverted (len(x)=40 and len(y)=500) yields:
with a pandas dataframe with the x axis as the first column and each spectra as another column
offset=0
for c in s.columns[1:]:
plt.plot(s.wavelength,s[c]+offset)
offset+=.25
plt.xlim([1325,1375])
I am plotting 2 lines and a dot, X axis is a date range. The dot is most important, but it appears on the boundary of the plot. I want to "expand" the plot further right so that the dot position is more visible.
In other words I want to expand the X axis without adding new values to Y values of lines. However if I just add a few dates to X values of lines I get the "x and y dimensions must be equal" error. I tried to add a few np.NaN values to Y so that dimensions are equal, but then I get an error "integer required".
My plot:
My code:
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
plot_x = train_original.index.values
train_y = train_original.values
ax1.plot(plot_x, train_y, 'grey')
x = np.concatenate([np.array([train_original.index.values[-1]]), test_original.index.values])
y = np.concatenate([np.array([train_original.dropna().values[-1]]), test_original.dropna().values])
ax1.plot(x, y, color='grey')
ax1.plot(list(predicted.index.values), list(predicted.values), 'ro')
ax1.axvline(x=train_end, alpha=0.7, linestyle='--',color='blue')
plt.show()
There are a couple of ways to do this.
An easy, automatic way to do this, without needing knowledge of the existing xlim is to use ax.margins. This will add a certain fraction of the data limits to either side of the plot. For example:
ax.margins(x=0.1)
will add 10% of the current x range to both ends of the plot.
Another method is to explicitly set the x limits using ax.set_xlim.
Just change the xlim(). Something like:
xmin, xmax = plt.xlim() # return the current xlim
plt.xlim(xmax=xmax+1)
I'm plotting a vector field with the quiver method of Matplotlib.
My array to store this vector has a dimension x * y but I'm working with a space that varies from -2 to 2.
So far, to plot the vector field I have this method:
import matplotlib.pyplot as plt
def plot_quiver(vector_field_x, vector_field_y, file_path):
plt.figure()
plt.subplots()
plt.quiver(vector_field_x, vector_field_y)
plt.savefig(file_path + '.png')
plt.close()
Which gives me this output, as an example, for a 10 x 10 array:
But to generate this vector field I centered my data in the x = 0, y = 0, x and y ranging from -2 to 2.
Then, I would like to plot the axis of the image following this pattern.
As an standard approach, I tried to do the following:
def plot_quiver(vector_field_x, vector_field_y, file_path):
plt.figure()
fig, ax = plt.subplots()
ax.quiver(vector_field_x, vector_field_y)
ax.set_xticks([-2, 0, 2])
ax.set_yticks([-2, 0, 2])
plt.savefig(file_path + '.png')
plt.close()
Which usually works with Matplotlib methods, as imshow and streamplot, for example.
But this what I've got with this code:
Which is not what I want.
So, I'm wondering how can I perform what I explained here to change the axes ticks.
Thank you in advance.
Funny thing, I just learnt about quiver yesterday... :)
According to the quiver documentation, the function can accept from 2 to 5 arguments...
The simplest way to use the function is to pass it two arrays with equal number of elements U and V. Then, matplotlib will plot an arrow for each element in the arrays. Specifically, for each element i,j you will get an arrow placed at i,j and with components defined by U[i,j] and V[i,j]. This is what is happening to you
A more complete syntax is to pass our arrays with equal number of elements X, Y, U and V. Again, you will get an arrow for each i,j element with components defined by U[i,j] and V[i,j], but this time they will be placed at coordinates X[i,j], Y[i,j].
In conclusion:
you need to call quiver like
quiver(values_x, values_y, vector_field_x, vector_field_y)
Probably you already did it, but you can get values_x and values_y using the numpy.meshgrid function.
The matplotlib example for the quiver function might be useful, also.
I hope it helps!