Pull out chunks of a plot made in python and re-display - python-3.x

I have made a plot in jupyter that has an x-axis spanning for about 40 seconds. I want to pull out sections that are milliseconds long and re-display them as separate plots (so that they can be better viewed). How would I go about doing this?

You could use some subplots, and slice the original data arrays. For example:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0,40,1000)
y = np.random.random(1000)
fig, [ax1,ax2,ax3] = plt.subplots(3,1)
ax1.plot(x,y)
ax2.plot(x[100:120],y[100:120])
ax3.plot(x[500:520],y[500:520])
plt.show()

Related

plotting time and temperature in xy plot

I want to plot a xy plot where x axis contain temperature values(first column) and y axis contain time in hr:min:sec(second column) .
8.8900 06:09:95.50
9.4500 06:09:00.56
10.5800 08.06:95.48
11.6500 09:07:73.58
56.3650 00:08:00.47
85.7823 07:01:03.23
I just want to plot a xy plot.
I tried code
import numpy as np
import matplotlib.pyplot as plt
data=np.loadtxt("inpdata.txt")
plt.plot(data[:,0],data[:,1])
plt.show()
But it does not give plot.hope experts may help.Thanks.
The simplest approach would be to use pandas.
Load the file as whitespace delimited file into pandas.DataFrame object as:
import pandas as pd
from matplotlib import pyplot as plt
df = pd.read_csv('inpdata.txt', names=['temp', 'time'], delim_whitespace=True)
Then create a line plot with time as x axis:
df.plot.line(x='time')
and show the plot
plt.show()

Break a pandas line plot at specific date

I have a time-series dataframe with missing data for some time period. I would like to create a line plot and break a line where there is missing data.
data_site1_ave[["samples", "lkt"]].plot(figsize=(15,4), title = "Site 1", xlabel='')
Is it possible to create a gap, let's say from 2018-05-01 to 2018-10-30 in the line plot?
Yes, you can create arbitrary gaps by simply calling df.plot() several times, on the appropriate slices of the full dataframe. To make everything appear in the same plot, you can pass the ax keyword argument to plt.plot() via the df.plot() method. Turn the legend off for all but one call, so that the legend only has the one entry.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# create sample time series
N = 365
np.random.seed(42)
x = pd.date_range('2018-01-01', freq='d', periods=N)
y = np.cumsum(np.random.rand(N, 1) - 0.5)
df = pd.DataFrame(y, columns=['y'], index=x)
# plot time series with gap
fig, ax = plt.subplots()
df.loc[:'2018-05-01'].plot(ax=ax, c='blue')
df.loc['2018-10-31':].plot(ax=ax, c='blue', legend=False);

How to set figure size in lmplot seaborn? [duplicate]

How do I change the size of my image so it's suitable for printing?
For example, I'd like to use to A4 paper, whose dimensions are 11.7 inches by 8.27 inches in landscape orientation.
You can also set figure size by passing dictionary to rc parameter with key 'figure.figsize' in seaborn set method:
import seaborn as sns
sns.set(rc={'figure.figsize':(11.7,8.27)})
Other alternative may be to use figure.figsize of rcParams to set figure size as below:
from matplotlib import rcParams
# figure size in inches
rcParams['figure.figsize'] = 11.7,8.27
More details can be found in matplotlib documentation
You need to create the matplotlib Figure and Axes objects ahead of time, specifying how big the figure is:
from matplotlib import pyplot
import seaborn
import mylib
a4_dims = (11.7, 8.27)
df = mylib.load_data()
fig, ax = pyplot.subplots(figsize=a4_dims)
seaborn.violinplot(ax=ax, data=df, **violin_options)
Note that if you are trying to pass to a "figure level" method in seaborn (for example lmplot, catplot / factorplot, jointplot) you can and should specify this within the arguments using height and aspect.
sns.catplot(data=df, x='xvar', y='yvar',
hue='hue_bar', height=8.27, aspect=11.7/8.27)
See https://github.com/mwaskom/seaborn/issues/488 and Plotting with seaborn using the matplotlib object-oriented interface for more details on the fact that figure level methods do not obey axes specifications.
first import matplotlib and use it to set the size of the figure
from matplotlib import pyplot as plt
import seaborn as sns
plt.figure(figsize=(15,8))
ax = sns.barplot(x="Word", y="Frequency", data=boxdata)
You can set the context to be poster or manually set fig_size.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
np.random.seed(0)
n, p = 40, 8
d = np.random.normal(0, 2, (n, p))
d += np.log(np.arange(1, p + 1)) * -5 + 10
# plot
sns.set_style('ticks')
fig, ax = plt.subplots()
# the size of A4 paper
fig.set_size_inches(11.7, 8.27)
sns.violinplot(data=d, inner="points", ax=ax)
sns.despine()
fig.savefig('example.png')
This can be done using:
plt.figure(figsize=(15,8))
sns.kdeplot(data,shade=True)
In addition to elz answer regarding "figure level" methods that return multi-plot grid objects it is possible to set the figure height and width explicitly (that is without using aspect ratio) using the following approach:
import seaborn as sns
g = sns.catplot(data=df, x='xvar', y='yvar', hue='hue_bar')
g.fig.set_figwidth(8.27)
g.fig.set_figheight(11.7)
This shall also work.
from matplotlib import pyplot as plt
import seaborn as sns
plt.figure(figsize=(15,16))
sns.countplot(data=yourdata, ...)
For my plot (a sns factorplot) the proposed answer didn't works fine.
Thus I use
plt.gcf().set_size_inches(11.7, 8.27)
Just after the plot with seaborn (so no need to pass an ax to seaborn or to change the rc settings).
See How to change the image size for seaborn.objects for a solution with the new seaborn.objects interface from seaborn v0.12, which is not the same as seaborn axes-level or figure-level plots.
Adjusting the size of the plot depends if the plot is a figure-level plot like seaborn.displot, or an axes-level plot like seaborn.histplot. This answer applies to any figure or axes level plots.
See the the seaborn API reference
seaborn is a high-level API for matplotlib, so seaborn works with matplotlib methods
Tested in python 3.8.12, matplotlib 3.4.3, seaborn 0.11.2
Imports and Data
import seaborn as sns
import matplotlib.pyplot as plt
# load data
df = sns.load_dataset('penguins')
sns.displot
The size of a figure-level plot can be adjusted with the height and/or aspect parameters
Additionally, the dpi of the figure can be set by accessing the fig object and using .set_dpi()
p = sns.displot(data=df, x='flipper_length_mm', stat='density', height=4, aspect=1.5)
p.fig.set_dpi(100)
Without p.fig.set_dpi(100)
With p.fig.set_dpi(100)
sns.histplot
The size of an axes-level plot can be adjusted with figsize and/or dpi
# create figure and axes
fig, ax = plt.subplots(figsize=(6, 5), dpi=100)
# plot to the existing fig, by using ax=ax
p = sns.histplot(data=df, x='flipper_length_mm', stat='density', ax=ax)
Without dpi=100
With dpi=100
# Sets the figure size temporarily but has to be set again the next plot
plt.figure(figsize=(18,18))
sns.barplot(x=housing.ocean_proximity, y=housing.median_house_value)
plt.show()
Some tried out ways:
import seaborn as sns
import matplotlib.pyplot as plt
ax, fig = plt.subplots(figsize=[15,7])
sns.boxplot(x="feature1", y="feature2",data=df) # where df would be your dataframe
or
import seaborn as sns
import matplotlib.pyplot as plt
plt.figure(figsize=[15,7])
sns.boxplot(x="feature1", y="feature2",data=df) # where df would be your dataframe
The top answers by Paul H and J. Li do not work for all types of seaborn figures. For the FacetGrid type (for instance sns.lmplot()), use the size and aspect parameter.
Size changes both the height and width, maintaining the aspect ratio.
Aspect only changes the width, keeping the height constant.
You can always get your desired size by playing with these two parameters.
Credit: https://stackoverflow.com/a/28765059/3901029

Y-axis values not showing in matplotlib.pyplot plot

My plot is not showing any indication of what the order of magnitude of my y-values are on the axis. How do I force python to indicate some values on the y-axis?
import numpy as np
import matplotlib.pyplot as plt
BERfinal = [0.4967843137254903, 0.49215686274509757, 0.4938823529411763,
0.49170588235294116, 0.48852941176470605, 0.48203921568627417,
0.4797058823529405, 0.47454901960784257, 0.4795686274509802,
0.474901960784313, 0.4732549019607838, 0.4703137254901953,
0.4705490196078425]
x = np.linspace(-4,8,len(BERfinal))
plt.semilogy(x,BERfinal)
plt.title("BER vs SNR")
plt.ylabel("Bit Error Rate(BER)")
plt.xlabel("Signal-to-Noise Ratio(SNR)[dB]")
plt.xlim(-4,8)
I ended up playing around with:
plt.ylim(4.7*10**-1, 5*10**-1)
and changed the values until I found an appropriate range. It now shows 5x10^-1 on the y-axis.

Timeserie datetick problems when using pandas.DataFrame.plot method

I just discovered something really strange when using plot method of pandas.DataFrame. I am using pandas 0.19.1. Here is my MWE:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
t = pd.date_range('1990-01-01', '1990-01-08', freq='1H')
x = pd.DataFrame(np.random.rand(len(t)), index=t)
fig, axe = plt.subplots()
x.plot(ax=axe)
plt.show(axe)
xt = axe.get_xticks()
When I try to format my xticklabels I get strange beahviours, then I insepcted objects to understand and I have found the following:
t[-1] - t[0] = Timedelta('7 days 00:00:00'), confirming the DateTimeIndex is what I expect;
xt = [175320, 175488], xticks are integers but they are not equals to a number of days since epoch (I do not have any idea about what it is);
xt[-1] - xt[0] = 168 there are more like index, there is the same amount that len(x) = 169.
This explains why I cannot succed to format my axe using:
axe.xaxis.set_major_locator(mdates.HourLocator(byhour=(0,6,12,18)))
axe.xaxis.set_major_formatter(mdates.DateFormatter("%a %H:%M"))
The first raise an error that there is to many ticks to generate
The second show that my first tick is Fri 00:00 but it should be Mon 00:00 (in fact matplotlib assumes the first tick to be 0481-01-03 00:00, oops this is where my bug is).
It looks like there is some incompatibility between pandas and matplotlib integer to date conversion but I cannot find out how to fix this issue.
If I run instead:
fig, axe = plt.subplots()
axe.plot(x)
axe.xaxis.set_major_formatter(mdates.DateFormatter("%a %H:%M"))
plt.show(axe)
xt = axe.get_xticks()
Everything works as expected but I miss all cool features from pandas.DataFrame.plot method such as curve labeling, etc. And here xt = [726468. 726475.].
How can I properly format my ticks using pandas.DataFrame.plot method instead of axe.plot and avoiding this issue?
Update
The problem seems to be about origin and scale (units) of underlying numbers for date representation. Anyway I cannot control it, even by forcing it to the correct type:
t = pd.date_range('1990-01-01', '1990-01-08', freq='1H', origin='unix', units='D')
There is a discrepancy between matplotlib and pandas representation. And I could not find any documentation of this problem.
Is this what you are going for? Note I shortened the date_range to make it easier to see the labels.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as dates
t = pd.date_range('1990-01-01', '1990-01-04', freq='1H')
x = pd.DataFrame(np.random.rand(len(t)), index=t)
# resample the df to get the index at 6-hour intervals
l = x.resample('6H').first().index
# set the ticks when you plot. this appears to position them, but not set the label
ax = x.plot(xticks=l)
# set the display value of the tick labels
ax.set_xticklabels(l.strftime("%a %H:%M"))
# hide the labels from the initial pandas plot
ax.set_xticklabels([], minor=True)
# make pretty
ax.get_figure().autofmt_xdate()
plt.show()

Resources