Missing plots after for loop - python

I have a dataset that I want to plot, and also do a linear regression on the data in some invervals, plotting it in the same graph.
But I have some problems with this... The main graph is plotted first, the intervals and the linear regression in the for loop:
plt.plot(Trec, lnp, 'r-')
for i in range(len(Werte)):
plt.plot( subset(Time, Trec, Data[i][5], Data[i][6])[1], subset(Time, Trec, Data[i][5], Data[i][6])[1] * Data[i][2] + Data[i][4])
plt.axvline(x=Data[i][5])
plt.show()
With this code it only plots me the last iteration of the for loop. By itself, the commands all do what I intend them to do... What am I doing wrong?

What you want is superimposing figures on the same plot. For that purpose, you can use the axis object returned by subplots.
fig, ax = plt.subplots()
ax.plot(...) # plot your data here
ax.plot(...) # plot your interval and regression here.
plt.show()

Related

Matplotlib update one plot function when multiple functions plotted on same figure

I have a case where I plot multiple functions on one figure but want to update one function while not having to re-plot the other function.
A very simplistic example:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x = np.arange(0,10,0.1)
ax1 = plt.subplot(1,1,1)
ax2 = plt.subplot(1,1,1)
ax1.plot(x,1*np.sin(x),'b-')
ax2.plot(x,2*np.sin(x),'g-')
I want to clear/update the data plotted in ax2 so that the data in ax1 isn't cleared or needs to be replotted.
Using ax2.clear() or ax2.cla() both clear the entire figure.
Are there any suggestions on how I can either update just the data in ax2 or a better way to control the plotting data for multiple functions on the same plot independently?
The actual case scenario plots satellite data (ax1) on a projected map with contour lines (ax2) overlayed. So the motivation is not to replot the satellite data due to time, but to keep the satellite data and update the contour plots (ax2) and save the figure at each step in a for-loop.
You can set the data for the line in ax2:
l2, = ax2.plot(x, 2*np.sin(x),'g-')
l2.set_data((2*x, 3*np.sin(x)))
This will trigger replotting of the line in ax2, but axis scaling etc. isn't updated. Not sure if this is what you want.

How can I plot residuals in seasonal_decompose(df['Employees'], model='add') as a line chart, not a scatterplot?

the code is:
result = seasonal_decompose(df['Employees'], model='add')
result.plot()
The output is
the following
I would like to have my residuals in a line chart. How do I do this?
I don't understand why the residuals would show up as a scatter plot instead of a line chart as a line chart is the default behavior of the .plot() method - perhaps it has something to do with overlapping datetimes in your data, but we should expect the timegrains of observed + trend + seasonal + residuals to line up exactly. If anyone can answer this I would be curious how this is possible. Was your data obtained from somewhere online so I can reproduce your output exactly?
For now, since result is an object of type DecomposeResult, you can try accessing its attributes one at a time: result.observed, result.trend, result.seasonal, result.resid, and plot them together on the same subplot
import matplotlib.pyplot as plt
fig, axes = plt.subplots(3, 1, sharex=True)
result.observed.plot(ax=axes[0], legend=False)
result.trend.plot(ax=axes[1], legend=False)
result.seasonal.plot(ax=axes[2], legend=False)
result.resid.plot(ax=axes[3], legend=False)
axes[0].set_ylabel('Observed')
axes[1].set_ylabel('Trend')
axes[2].set_ylabel('Seasonal')
axes[3].set_ylabel('Residual')
plt.show()
add extrapolate_trend='freq', period=3 as parameters to seasonal_decompose

Show confidence interval in legend of plot in Python / Seaborn

I am generating some scatter plots with linear regression and confidence interval using seaborn on Python, with the sns.regplot function. I could find a way to show the Regression line in the legend, but I would also like to add the Confidence Interval in the legend (with the transparent blue as the reference colour).
Here is the code I have and the result I get so far.
Tobin_Nationality_Reg = sns.regplot(x="Nationality_Index_Normalized",
y="Tobins_Q_2017",
data=Scatter_Plot,
line_kws={'label':'Regression line'})
plt.xlabel("Nationality Index")
plt.ylabel("Tobin's Q")
plt.legend()`
plt.savefig('Tobin_Nationality_Reg.png')
Here is the output I currently get:
Scatter Plot
Does anybody have an idea how I could do that? Thanks in advance.
I believe there is no clean way to do this, because seaborn does not expose keyword arguments for the fill_between call that plots the confidence interval.
However, it can be done by modifying the label attribute of the PolyCollection directly:
x, y = np.random.rand(2, 20)
ax = sns.regplot(x, y, line_kws={'label': 'Regression line'})
ax.collections[1].set_label('Confidence interval')
ax.legend()

Currently Animating Scatter Plot With Static Frames. Is there a way to animate over a moving window instead?

I have an array of arrays with format [2000][200,3] that I am creating an animated scatter plot of. 2000 is the number of frames and the interior arrays have format [length, [x,y,inten]] which are the points to scatter.
So for an example a single frame will look like:
Array[0]=np.array([x_1,y_1,I_1],[x_2,y_2,I_2],...,[x_200,y_200,I_200])
So we have 2000 frames of 200 points each. These points are arbitrarily truncated every 200 and are actually sequential. So I can feasibly reshape the array into:
Array=np.array(np.array([x_1,y_1,I_1],[x_2,y_2,I_2],...,[x_400000,y_400000,I_400000])
Which is no problem for me. I know how to do this.
My question is how can I animate a scatter plot that adaptively moves through the points instead of displaying 200 point bins? The code below allows me to plot an animated scatter plot with frames (1-200,201-400,401-600,etc) but the result is not very smooth to the eye. Ideally I would like something that updates at every point or at least every 10 points so for example frames (1-200,2-201,3-202,etc) or (1-200,11-210,21-200,etc)
numframes=len(Array)
plt.ion()
fig, ax = plt.subplots()
norm = plt.Normalize(Array[:][:,2].min(), Array[:][:,2].max())
sc = ax.scatter(Array[0][:,0], Array[0][:,1], c=Array[0][:,2], cmap=cm.hot, s=5)
plt.xlim(-40,40)
plt.ylim(0,200)
plt.draw()
for i in range(numframes):
sc.set_offsets(np.c_[Array[i][:,0], Array[i][:,1]])
sc.set_array(Array[i][:,2])
print(i)
plt.pause(0.1)
plt.ioff()
plt.show()
The code below steps continuously through my array of points with a given step size and window of 200 instead of discretely binning every 200.
stepsize=10
NewArray=np.ravel(Array)
NewArray.reshape(2000*200,3)
plt.ion()
fig, ax = plt.subplots()
norm = plt.normalize(NewArray[:,2].min(), NewArray[:,2].max())
sc = ax.scatter(NewArray[0:200,0], NewArray[0:200,1], c=NewArray[0:200,2], cmap=cm.jet, s=5)
plt.xlim(-40,40)
plt.ylim(0,200)
plt.draw()
for i in range(len(NewArray//stepsize)-200):
sc.set_offsets(np.c_[NewArray[(i*stepsize):(i*stepsize)+200,0],\
NewArray[(i*stepsize):(i*stepsize)+200,1]])
sc.set_array(NewArray[(i*stepsize):(i*stepsize)+200,2])
plt.pause(0.1)
plt.ioff()
plt.show()

python, matplotlib: specgram data array values does not match specgram plot

I am using matplotlib.pyplot.specgram and matplotlib.pyplot.pcolormesh to make spectrogram plots of a seismic signal.
Background information -The reason for using pcolormesh is that I need to do arithmitic on the spectragram data array and then replot the resulting spectrogram (for a three-component seismogram - east, north and vertical - I need to work out the horizontal spectral magnitude and divide the vertical spectra by the horizontal spectra). It is easier to do this using the spectrogram array data than on individual amplitude spectra
I have found that the plots of the spectrograms after doing my arithmetic have unexpected values. Upon further investigation it turns out that the spectrogram plot made using the pyplot.specgram method has different values compared to the spectrogram plot made using pyplot.pcolormesh and the returned data array from the pyplot.specgram method. Both plots/arrays should contain the same values, I cannot work out why they do not.
Example:
The plot of
plt.subplot(513)
PxN, freqsN, binsN, imN = plt.specgram(trN.data, NFFT = 20000, noverlap = 0, Fs = trN.stats.sampling_rate, detrend = 'mean', mode = 'magnitude')
plt.title('North')
plt.xlabel('Time [s]')
plt.ylabel('Frequency [Hz]')
plt.clim(0, 150)
plt.colorbar()
#np.savetxt('PxN.txt', PxN)
looks different to the plot of
plt.subplot(514)
plt.pcolormesh(binsZ, freqsZ, PxN)
plt.clim(0,150)
plt.colorbar()
even though the "PxN" data array (that is, the spectrogram data values for each segment) is generated by the first method and re-used in the second.
Is anyone aware why this is happening?
P.S. I realise that my value for NFFT is not a square number, but it's not important at this stage of my coding.
P.P.S. I am not aware of what the "imN" array (fourth returned variable from pyplot.specgram) is and what it is used for....
First off, let's show an example of what you're describing so that other folks
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
# Brownian noise sequence
x = np.random.normal(0, 1, 10000).cumsum()
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(8, 10))
values, ybins, xbins, im = ax1.specgram(x, cmap='gist_earth')
ax1.set(title='Specgram')
fig.colorbar(im, ax=ax1)
mesh = ax2.pcolormesh(xbins, ybins, values, cmap='gist_earth')
ax2.axis('tight')
ax2.set(title='Raw Plot of Returned Values')
fig.colorbar(mesh, ax=ax2)
plt.show()
Magnitude Differences
You'll immediately notice the difference in magnitude of the plotted values.
By default, plt.specgram doesn't plot the "raw" values it returns. Instead, it scales them to decibels (in other words, it plots the 10 * log10 of the amplitudes). If you'd like it not to scale things, you'll need to specify scale="linear". However, for looking at frequency composition, a log scale is going to make the most sense.
With that in mind, let's mimic what specgram does:
plotted = 10 * np.log10(values)
fig, ax = plt.subplots()
mesh = ax.pcolormesh(xbins, ybins, plotted, cmap='gist_earth')
ax.axis('tight')
ax.set(title='Plot of $10 * log_{10}(values)$')
fig.colorbar(mesh)
plt.show()
Using a Log Color Scale Instead
Alternatively, we could use a log norm on the image and get a similar result, but communicate that the color values are on a log scale more clearly:
from matplotlib.colors import LogNorm
fig, ax = plt.subplots()
mesh = ax.pcolormesh(xbins, ybins, values, cmap='gist_earth', norm=LogNorm())
ax.axis('tight')
ax.set(title='Log Normalized Plot of Values')
fig.colorbar(mesh)
plt.show()
imshow vs pcolormesh
Finally, note that the examples we've shown have had no interpolation applied, while the original specgram plot did. specgram uses imshow, while we've been plotting with pcolormesh. In this case (regular grid spacing) we can use either.
Both imshow and pcolormesh are very good options, in this case. However,imshow will have significantly better performance if you're working with a large array. Therefore, you might consider using it instead, even if you don't want interpolation (e.g. interpolation='nearest' to turn off interpolation).
As an example:
extent = [xbins.min(), xbins.max(), ybins.min(), ybins.max()]
fig, ax = plt.subplots()
mesh = ax.imshow(values, extent=extent, origin='lower', aspect='auto',
cmap='gist_earth', norm=LogNorm())
ax.axis('tight')
ax.set(title='Log Normalized Plot of Values')
fig.colorbar(mesh)
plt.show()

Categories

Resources