How to plot multiple graphs in Matplotlib from the numpy datasets I am working on? - numpy

I am new to programming, and I'm having difficulty plotting multiple graphs. What I am trying to get is a graph containing values of K along the Y-axis plotted against values of Dk. I need this graph to contain all the K=f(Dk) for each temperature Tcwin in range (10,40,1)
While the code seems to be working well and I have obtained the data I was trying to calculate, I can't seem to plot them. Any help would be appreciated.
import numpy as np
import pandas as pd
A=3000
d_in=20
CF=0.85
w=2.26
Tcwin=12
Dk=np.arange(27.418,301.598,27.418)
dk=(Dk*1000/(A*3.600))
cp=4.19
Gw=13000
e=2.718281828
f_velocity=w*1.1/(20**0.25)
for Tcwin in range(10,40,1):
while Tcwin<35:
print(Tcwin)
f_w=0.12*CF*(1+0.15*Tcwin)
Ф_в=f_velocity**f_w
K=CF*4070*((1.1*w/(d_in**0.25))**(0.12*CF*(1+0.15*Tcwin)))*(1-(((35-Tcwin)**2)*(0.52-0.0072*dk)*(CF**0.5))/1000)
n=(K*A)/(cp*Gw*1000)
Tcwout_theor=Tcwin+(Dk*2225/(cp*Gw))
Subcooling_theor=(Tcwout_theor-Tcwin)/(e**(K*A/(cp*(Gw*1000/3600)*1000)))
TR_theor=Tcwout_theor-Tcwin
Tsat_theor=Tcwout_theor+Subcooling_theor
print(K)
print(Tcwout_theor)
print(Subcooling_theor)
print(Tsat_theor)
Tcwin+=1
else:
print('Loop done')

Is this what you are looking for? plotting after each run:
import numpy as np
import pandas as pd
A=3000
d_in=20
CF=0.85
w=2.26
Tcwin=12
Dk=np.arange(27.418,301.598,27.418)
dk=(Dk*1000/(A*3.600))
cp=4.19
Gw=13000
e=2.718281828
f_velocity=w*1.1/(20**0.25)
for Tcwin in range(10,40,1):
while Tcwin<35:
print(Tcwin)
f_w=0.12*CF*(1+0.15*Tcwin)
Ф_в=f_velocity**f_w
K=CF*4070*((1.1*w/(d_in**0.25))**(0.12*CF*(1+0.15*Tcwin)))*(1-(((35-Tcwin)**2)*(0.52-0.0072*dk)*(CF**0.5))/1000)
n=(K*A)/(cp*Gw*1000)
Tcwout_theor=Tcwin+(Dk*2225/(cp*Gw))
Subcooling_theor=(Tcwout_theor-Tcwin)/(e**(K*A/(cp*(Gw*1000/3600)*1000)))
TR_theor=Tcwout_theor-Tcwin
Tsat_theor=Tcwout_theor+Subcooling_theor
print(K)
print(Tcwout_theor)
print(Subcooling_theor)
print(Tsat_theor)
Tcwin+=1
plt.plot(K,dk) #---------------> this is the code for plotting
else:
print('Loop done')

Related

Unable to generate plot using matplotlib

I am a beginner to Python and experimenting with a plot. the script runs fine but plot does not show up.
the matplotlib and numpy libraries are installed.
import numpy as np
f= h5py.File('3DIMG_05JUN2021_0000_L3B_HEM_DLY.h5','r')
#Studying the structure of the file by printing what HDF5 groups are present
for key in f.keys():
print(key) #Names of the groups in HDF5 file.
# will print the variables in the file
#Get the HDF5 group
ls=list(f.keys())
print("ls")
print(ls)
tsurf = f['HEM_DLY'][:]
print("tsurf")
print(tsurf)
tsurf1=np.squeeze(tsurf)
print(tsurf1.shape)
import matplotlib.pyplot as plt
im= plt.plot(tsurf1)
#plt.colorbar()
plt.imshow(im)```
Python version is 3 running on Ubuntu
Difficult to give you the exact answer without the dataset (please update the question with the dataset), but for sure, plt.plot does not return an object that can be plotted with plt.imshow
Try instead:
ax = plt.plot(tsurf1)
plt.show()
Probably the error was on the final plot.Try this:
import numpy as np
import matplotlib.pyplot as plt
f= h5py.File('/path','r')
ls=list(f.keys())
tsurf = f['your_key_str'][:]
tsurf1=np.squeeze(tsurf)
im= plt.plot(tsurf1)
plt.show(im) # <-- plt.show() NOT plt.imshow()

How can i plotting two columns with string as value in a DataSet with Matplotlib?

I have the following Dataset and I wanna create a plot, which to columns compares with each other.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
ds=pd.read_csv('h-t-t-p-:bit.ly/uforeports') #My DataSet
ds.head(5) # Only the fist 5 rows to show
ds1= ds.head(4).drop(['Colors Reported','State'],axis=1) # Droping of unnecesssary rows
print(ds1)
Now I wanna compare "City" and "Shape Reported" with help of plotting. I found something with Pandas but this is not so elegant!
x=ds.loc[0:100,['State']]
y=ds.loc[0:100,['Shape Reported']]
x.apply(pd.value_counts).plot(kind='bar', subplots=True)
y.apply(pd.value_counts).plot(kind='bar', subplots=True)
Do you know a better solution with Matplotlib to this problem?
This is what I want
It's not exactly clear how you want to compare them.
The simplest way of drawing a bar chart is:
df['State'].value_counts().plot.bar()
df['Shape Reported'].value_counts().plot.bar()
If you just want to do it for the first 100 rows as in your example, just add head(100):
df['State'].head(100).value_counts().plot.bar()
df['Shape Reported'].head(100).value_counts().plot.bar()
EDIT:
To compare the two values you can plot a bivariate distribution plot. This is easily done with seaborn:
import seaborn
sns.displot(df,x='State', y='Shape Reported', height=6, aspect=1.33)
Result:

FFT of exponentially decaying sinusoidal function

I have a set of simulation data to which I want to perform an FFT. I am using matplotlib to do this. However, the FFT is looking strange, so I don't know if I am missing something in my code. Would appreciate any help.
Original data:
time-varying data
FFT:
FFT
Code for the FFT calculation:
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack as fftpack
data = pd.read_csv('table.txt',header=0,sep="\t")
fig, ax = plt.subplots()
mz_res=data[['mz ()']].to_numpy()
time=data[['# t (s)']].to_numpy()
ax.plot(time[:300],mz_res[:300])
ax.set_title("Time-varying mz component")
ax.set_xlabel('time')
ax.set_ylabel('mz amplitude')
fft_res=fftpack.fft(mz_res[:300])
power=np.abs(fft_res)
frequencies=fftpack.fftfreq(fft_res.size)
fig2, ax_fft=plt.subplots()
ax_fft.plot(frequencies[:150],power[:150]) // taking just half of the frequency range
I am just plotting the first 300 datapoints because the rest is not important.
Am I doing something wrong here? I was expecting single frequency peaks not what I got. Thanks!
Link for the input file:
Pastebin
EDIT
Turns out the mistake was in the conversion of the dataframe to a numpy array. For a reason I have yet to understand, if I convert a dataframe to a numpy array it is converted as an array of arrays, i.e., each element of the resulting array is itself an array of a single element. When I change the code to:
mz_res=data['mz ()'].to_numpy()
so that it is a conversion from a pandas series to a numpy array, then the FFT behaves as expected and I get single frequency peaks from the FFT.
So I just put this here in case someone else finds it useful. Lesson learned: the conversion from a pandas series to a numpy array yields a different result than the conversion from a pandas dataframe.
Solution:
Using the conversion from pandas series to numpy array instead of pandas dataframe to numpy array.
Code:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack as fftpack
data = pd.read_csv('table.txt',header=0,sep="\t")
fig, ax = plt.subplots()
mz_res=data['mz ()'].to_numpy() #series to array
time=data[['# t (s)']].to_numpy() #dataframe to array
ax.plot(time,mz_res)
ax.set_title("Time-varying mz component")
ax.set_xlabel('time')
ax.set_ylabel('mz amplitude')
fft_res=fftpack.fft(mz_res)
power=np.abs(fft_res)
frequencies=fftpack.fftfreq(fft_res.size)
indices=np.where(frequencies>0)
freq_pos=frequencies[indices]
power_pos=power[indices]
fig2, ax_fft=plt.subplots()
ax_fft.plot(freq_pos,power_pos) # taking just half of the frequency range
ax_fft.set_title("FFT")
ax_fft.set_xlabel('Frequency (Hz)')
ax_fft.set_ylabel('FFT Amplitude')
ax_fft.set_yscale('linear')
Yields:
Time-dependence
FFT

Seaborn y labels are overlapping

So I tried to make a categorical plot of my data and this is what my code and the graph.
import pandas as pd
import numpy as np
import matplotlib as plt
import seaborn as sns
sns.set(style="whitegrid")
sns.set_style("ticks")
sns.set_context("paper", font_scale=1, rc={"lines.linewidth": 6})
sns.catplot(y = "Region",x = "Interest by subregion",data = sample)
Image:
How can I make the y-labels more spread out and have a bigger font?
Try using sns.figure(figsize(x,y)) and sns.set_context(context=None,font_scale=1).
Try different values for these parameters to get the best results.

Cutting up the x-axis to produce multiple graphs with seaborn?

The following code when graphed looks really messy at the moment. The reason is I have too many values for 'fare'. 'Fare' ranges from [0-500] with most of the values within the first 100.
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
titanic = sns.load_dataset("titanic")
y =titanic.groupby([titanic.fare//1,'sex']).survived.mean().reset_index()
sns.set(style="whitegrid")
g = sns.factorplot(x='fare', y= 'survived', col = 'sex', kind ='bar' ,data= y,
size=4, aspect =2.5 , palette="muted")
g.despine(left=True)
g.set_ylabels("Survival Probability")
g.set_xlabels('Fare')
plt.show()
I would like to try slicing up the 'fare' of the plots into subsets but would like to see all the graphs at the same time on one screen. I was wondering it this is possible without having to resort to groupby.
I will have to play around with the values of 'fare' to see what I would want each graph to represent, but for a sample let's use break up the graph into these 'fare' values.
[0-18]
[18-35]
[35-70]
[70-300]
[300-500]
So the total would be 10 graphs on one page, because of the juxtaposition with the opposite sex.
Is it possible with Seaborn? Do I need to do a lot of configuring with matplotlib? Thanks.
Actually I wrote a little blog post about this a while ago. If you are plotting histograms you can use the by keyword:
import matplotlib.pyplot as plt
import seaborn.apionly as sns
sns.set() #rescue matplotlib's styles from the early '90s
data = sns.load_dataset('titanic')
data.hist(by='class', column = 'fare')
plt.show()
Otherwise if you're just plotting value-counts, you have to roll your own grid:
def categorical_hist(self,column,by,layout=None,legend=None,**params):
from math import sqrt, ceil
if layout==None:
s = ceil(sqrt(self[column].unique().size))
layout = (s,s)
return self.groupby(by)[column]\
.value_counts()\
.sort_index()\
.unstack()\
.plot.bar(subplots=True,layout=layout,legend=None,**params)
categorical_hist(data, by='class', column='embark_town')
Edit If you want survival rate by fare range, you could do something like this
data.groupby(pd.cut(data.fare,10)).apply(lambda x.survived.sum(): x./len(x))