How to add subfigures in a loop - python

I have a loop in which I would like to create three subfigures. Here is some code with the function definitions removed.
n = 14
dets = []
entropies = []
N = 1000
fig = plt.figure()
# The loop.
for h in xrange(2,8,2):
for i in xrange(N):
A = (np.random.randint(2, size=(h,n)))*2-1
detA_Atranspose = np.linalg.det(np.dot(A, A.transpose()))
logdetA_Atranspose = math.log(detA_Atranspose + 1,2)
H = compute_entropy(A)
entropies.append(H)
dets.append(logdetA_Atranspose)
ax1 = fig.add_subplot(311)
ax1.plot(dets, entropies, 'ro')
plt.show()
However, there is something I don't know how to do.
In the code above, I need ax2 = fig.add_subplot(312)
ax2.plot(dets, entropies, 'ro') in the second iteration and ax3 = fig.add_subplot(313)
ax3.plot(dets, entropies, 'ro') in the third to create the three subfigures. How should I do that?

You can make use of plt.subplots and do something like:
fig, ax = plt.subplots(nrows = 3, ncols = 1)
hs = [2,8,2]
for p in xrange(3):
h = hs[p]
for i in xrange(N):
# skip other code
ax[p].plot(dets, entropies, 'ro')

Related

Python imshow will only display last line

I have the following code that when run separately, displays two maps:
Map1:
f = h5py.File(filename[0], 'r')
group_id='Soil_Moisture_Retrieval_Data_AM'
var_id = 'soil_moisture'
a = f[group_id][var_id][:,:]
plt.figure(figsize=(10, 10))
a[a==f[group_id][var_id].attrs['_FillValue'].astype(int)]==np.nan;
plt.imshow(a,vmin=0.,vmax=0.55, cmap = 'terrain_r');
cbar = plt.colorbar(orientation='horizontal')
cbar.set_label('$cm^3 cm^{-3}$')
Map2:
f1 = h5py.File(filename[1], 'r')
b = f1[group_id][var_id][:,:]
b[b==f1[group_id][var_id].attrs['_FillValue'].astype(int)]==np.nan;
plt.figure(figsize=(10, 10))
plt.imshow(b,vmin=0.,vmax=0.55, cmap = 'terrain_r');
cbar = plt.colorbar(orientation='horizontal')
cbar.set_label('$cm^3 cm^{-3}$')
Trying to overlay the two maps will only display the last line (in this case, b):
plt.figure(figsize=(10, 10))
plt.imshow(a,vmin=0.,vmax=0.55, cmap = 'terrain_r')
plt.imshow(b,vmin=0.,vmax=0.55, cmap = 'terrain_r')
What am I possibly missing? Happy to provide more info if needed...

Plot multiple lines in a loop

I try to plot lines in a loop,but its connecting it,i tried many variants,but cand understand and find the answer,maybe the dataframe
im a newbie in Matplotlib
the code of method:
self.testnewnewventnest[Debit] - is a nested dict with the data i need for plotting
def showmainplot(self):
for Debit in self.Debitlist:
self.Presinit = self.VentTable.loc[Debit]
self.Tinit= float(self.Tinit)
self.Presinit=int(float(self.Presinit))
self.Powinit = float(self.Powinit)
x = symbols("x")
for Turatie in self.Tfin:
eqPres = (Turatie/self.Tinit)*(Turatie/self.Tinit)*self.Presinit-x
PresFin = solve(eqPres)
eqDebit = (Turatie/self.Tinit)*int(Debit)
DebitFin = solve(eqDebit)
eqPow = (Turatie/self.Tinit)*(Turatie/self.Tinit)*(Turatie/self.Tinit)*float(self.Powinit)
self.TestnewVentnest['KW'] = float(eqPow)
self.TestnewVentnest['Turatie'] = Turatie
self.TestnewVentnest['Presiune'] = float(PresFin[0])
self.TestnewVent[float(eqDebit)] = dict(self.TestnewVentnest)
self.testnewnewventnest[Debit] = dict(self.TestnewVent)
print(self.testnewnewventnest)
axeslist = []
n=0
fig, ax = plt.subplots(figsize=(5, 5))
ax1 = ax.twinx()
ax1.spines.right.set_position(("axes", 1.06))
ax.set_xlabel("Debit")
for dicts in self.testnewnewventnest:
Ventdataframe = pd.DataFrame(self.testnewnewventnest[dicts])
print(Ventdataframe)
ax2 = plt.subplot()
fig, ax = plt.subplots(figsize=(5, 5))
ax1 = ax.twinx()
ax1.spines.right.set_position(("axes", 1.06))
ax.set_xlabel("Debit")
axeslist.append(plt.subplot())
# print(df.iloc[0])
# ax1.set_ylabel("Turatie")
# ax.set_ylabel("Presiune")
# Ventdataframe.plot(Ventdataframe.loc["Presiune"], color="b",label="Presiune"+str(n),marker = 'o')
Ventdataframe.loc["Presiune"].plot(color="b",label="Presiune"+str(n),marker = 'o')
n+=1
# ax2 = ax.twinx()
# ax2.set_ylabel('KW')
# ax1.plot(Ventdataframe.loc["Turatie"],color='#000000',label="Turatie",marker = 'o')
# ax2.plot(Ventdataframe.loc["KW"], color='r',label="KW",marker = 'o')
# ax1.grid()
# ax2.yaxis.set_major_locator(FixedLocator(Ventdataframe.loc["KW"]))
# ax.yaxis.set_major_locator(FixedLocator(Ventdataframe.loc["Presiune"]))
# ax1.yaxis.set_major_locator(FixedLocator(self.Tfin))
# ax.xaxis.set_major_locator(FixedLocator(Ventdataframe.columns))
# lc = matpl.ticker.NullLocator()
# ax.yaxis.set_major_locator(lc)
plt.show()
and the self.testnewnewventnest look like:
Yes,the problem was in the loop,and in the dictionaries,in every iteration he added all previous dictionaries from iterations
I would put that in a dataframe and do it like this.
uniques = df['ID'].unique()
for i in uniques:
fig, ax = plt.subplots()
fig.set_size_inches(4,3)
df_single = df[df['ID']==i]
sns.lineplot(data=df_single, x='Month', y='Expense')
ax.set(xlabel='Time', ylabel='Total Expense')
plt.xticks(rotation=45)
plt.show()

I have a 3D plot with 4 points, I want one to be the focal point and the other three to have lines connecting them to the focal point

I used scatter3D to plot the points, but it doesn't seem like I can connect them. The cell is the focal point and the inj are the three it should connect to, any suggestions?
fig = plt.figure()
ax = fig.gca(projection='3d')
cell= [1258096.60,11285000.00, 9415.22]
inj_1 = [1267960.80 ,11278335.00,9430.9]
inj_2 = [1267960.80 ,11278335.00,9441.32]
inj_3 = [1267960.80 ,11278335.00,9453.99]
inj_cells = cell,inj_1,inj_2,inj_3
for i in inj_cells:
I = np.array(i[0])
J = np.array(i[1])
K = np.array(i[2])
plot = ax.scatter3D(I,J,K)
plt.show()
to draw lines use ax.plot:
fig = plt.figure()
ax = fig.gca(projection='3d')
cell= [1258096.60,11285000.00, 9415.22]
inj_1 = [1267960.80 ,11278335.00,9430.9]
inj_2 = [1267960.80 ,11278335.00,9441.32]
inj_3 = [1267960.80 ,11278335.00,9453.99]
inj_cells = cell,inj_1,inj_2,inj_3
c, d, e = cell
for i in inj_cells:
I = np.array(i[0])
J = np.array(i[1])
K = np.array(i[2])
ax.plot((c,I), (d,J), (e,K))
plt.show()

Append data with different colour in matplotlib in real time

I'm updating dynamically a plot in a loop:
dat=[0, max(X[:, 0])]
fig = plt.figure()
ax = fig.add_subplot(111)
Ln, = ax.plot(dat)
Ln2, = ax.plot(dat)
plt.ion()
plt.show()
for i in range(1, 40):
ax.set_xlim(int(len(X[:i])*0.8), len(X[:i])) #show last 20% data of X
Ln.set_ydata(X[:i])
Ln.set_xdata(range(len(X[:i])))
Ln2.set_ydata(Y[:i])
Ln2.set_xdata(range(len(Y[:i])))
plt.pause(0.1)
But now I want to update it in a different way: append some values and show them in other colour:
X.append(other_data)
# change colour just to other_data in X
The result should look something like this:
How could I do that?
Have a look at the link I posted. Linesegments can be used to plot colors at a particular location differently. If you want to do it in real-time you can still use line-segments. I leave that up to you.
# adjust from https://stackoverflow.com/questions/38051922/how-to-get-differents-colors-in-a-single-line-in-a-matplotlib-figure
import numpy as np, matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap, BoundaryNorm
# my func
x = np.linspace(-2 * np.pi, 2 * np.pi, 100)
y = 3000 * np.sin(x)
# select how to color
cmap = ListedColormap(['r','b'])
norm = BoundaryNorm([2000,], cmap.N)
# get segments
xy = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.hstack([xy[:-1], xy[1:]])
# control which values have which colors
n = y.shape[0]
c = np.array([plt.cm.RdBu(0) if i < n//2 else plt.cm.RdBu(255) for i in range(n)])
# c = plt.cm.Reds(np.arange(0, n))
# make line collection
lc = LineCollection(segments,
colors = c
# norm = norm,
)
# plot
fig, ax = plt.subplots()
ax.add_collection(lc)
ax.autoscale()
ax.axvline(x[n//2], linestyle = 'dashed')
ax.annotate("Half-point", (x[n//2], y[n//2]), xytext = (4, 1000),
arrowprops = dict(headwidth = 30))
fig.show()

If function for annotating from pandas

I'm scatter plotting values from pandas dataframe. I would like to annotate points only if the value is greater than 100. I have no idea how to go about it.
Here's the code I'm working with (it's terrible but I'm very new to this):
female_data = r'/home/jg/Desktop/hurricanedata_f.csv'
female_df = read_csv(female_data)
male_data = r'/home/jg/Desktop/hurricanedata_m.csv'
male_df = read_csv(male_data)
x = female_df['Year']
y = female_df['alldeaths']
z = female_df['Name']
y_mean = [np.mean(y) for i in x]
a = male_df['Year']
b = male_df['alldeaths']
b_mean = [np.mean(b) for i in b]
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.annotate('Agnes', xy=(1972,117))
ax1 = fig.add_subplot(1,1,1)
ax1.scatter(x,y, label = 'female', color = 'r')
ax2 = fig.add_subplot(1,1,1)
ax2.scatter(a,b, label = 'male')
ax3 = fig.add_subplot(1,1,1)
ax3.plot(x, y_mean, linestyle='--', color = 'r')
ax4 = fig.add_subplot(1,1,1)
ax4.plot(a, b_mean, linestyle='--', color = 'blue')
plt.title('Hurricanes')
plt.xlabel('Year')
plt.ylabel('Deaths')
plt.legend(loc='upper right')
plt.ylim([-5,300])
plt.xlim([1948,2020])
plt.show()
You can loop over all your data points and check if each is greater than 100. Then give those points an annotation.
import matplotlib.pyplot as plt
import numpy as np
import string
# Fake data
x = np.arange(10)
y = 10*np.random.rand(10) + 95
names = string.lowercase[:10] # first 10 lowercase letters
# Plot data
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(x,y)
# Annonate points with y values greater than 100
for xi, yi, iname in zip(x,y,names): # Loop over x and y values
if yi > 100: # Check if y is greater than 100
ax.annotate(iname, (xi, yi),size = 30) # Add an annoatation.
plt.show()

Categories