How to overlay plots in python with matplotlib - python

I'm using two related packages that generate plots I want to overlay for comparison. I call a method called plot_spectro from each package which plots to plt. Then I must do plt.legend() and plt.show() to see them. What happens is two plots with the same data ranges appear, but I would like to overlay (superimpose) them.
import matplotlib.pyplot as plt
s.plot_spectro(xaxis=x, yaxis=y)
plt.xlim(-6,2)
plt.ylim(-2.5,2.5)
o1.plot_spectro(xaxis=x, yaxis=y, color='b')
plt.xlim(-6,2)
plt.ylim(-2.5,2.5)
plt.legend()
plt.show()

Create an axis instance and pass it to both the plots as shown below
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
s.plot_spectro(xaxis=x, yaxis=y, ax=ax) # <--- pass ax=ax here
o1.plot_spectro(xaxis=x, yaxis=y, color='b', ax=ax) # <--- pass ax=ax here
plt.xlim(-6,2)
plt.ylim(-2.5,2.5)
plt.legend()
plt.show()

Related

Combine 2 kde-functions in one plot in seaborn

I have the following code for plotting the histogram and the kde-functions (Kernel density estimation) of a training and validation dataset:
#Plot histograms
import matplotlib.pyplot as plt
import matplotlib
import seaborn as sns
displot_dataTrain=sns.displot(data_train, bins='auto', kde=True)
displot_dataTrain._legend.remove()
plt.ylabel('Count')
plt.xlabel('Training Data')
plt.title("Histogram Training Data")
plt.show()
displot_dataValid =sns.displot(data_valid, bins='auto', kde=True)
displot_dataValid._legend.remove()
plt.ylabel('Count')
plt.xlabel('Validation Data')
plt.title("Histogram Validation Data")
plt.show()
# Try to plot the kde-functions together --> yields an AttributeError
X1 = np.linspace(data_train.min(), data_train.max(), 1000)
X2 = np.linspace(data_valid.min(), data_valid.max(), 1000)
fig, ax = plt.subplots(1,2, figsize=(12,6))
ax[0].plot(X1, displot_dataTest.kde.pdf(X1), label='train')
ax[1].plot(X2, displot_dataValid.kde.pdf(X1), label='valid')
The plotting of the histograms and kde-functions inside one plot works without problems. Now I would like to have the 2 kde-functions inside one plot but when using the posted code, I get the following error AttributeError: 'FacetGrid' object has no attribute 'kde'
Do you have any idea, how I can combined the 2 kde-functions inside one plot (without the histogram)?
sns.displot() returns a FacetGrid. That doesn't work as input for ax.plot(). Also, displot_dataTest.kde.pdf is never valid. However, you can write sns.kdeplot(data=data_train, ax=ax[0]) to create a kdeplot inside the first subplot. See the docs; note the optional parameters cut= and clip= that can be used to adjust the limits.
If you only want one subplot, you can use fig, ax = plt.subplots(1, 1, figsize=(12,6)) and use ax=ax instead of ax=ax[0] as in that case ax is just a single subplot, not an array of subplots.
The following code has been tested using the latest seaborn version:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
fig, ax = plt.subplots(figsize=(12, 6))
sns.kdeplot(data=np.random.normal(0.1, 1, 100).cumsum(),
color='crimson', label='train', fill=True, ax=ax)
sns.kdeplot(data=np.random.normal(0.1, 1, 100).cumsum(),
color='limegreen', label='valid', fill=True, ax=ax)
ax.legend()
plt.tight_layout()
plt.show()

How to add grid graph as a background of one graph plot?

I want to add grid graph as a background of a signal plot generated from the following code?
dff = pd.read_csv("abc.csv")
x = dff['A']
times = np.arange(len(x))/360
plt.subplot(121)
plt.plot(times, x)
plt.tight_layout()
plt.show()
What should I change in this code. Can anyone help me out.Thanks in advance!
To add gridlines to PyPlot plots, you can use the grid() tool:
import matplotlib.pyplot as plt
plt.subplot(121)
plt.plot()
plt.tight_layout()
plt.grid(axis='both')
plt.show()
You can see more about its arguments here.
Note that in matplotlib you might have a better time using figures with the "axes" object, rather than the functional interface. E.g.:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot()
ax.grid()
This allows you to index axs objects like lists, and pass plots as arguments.

Create a discrete colorbar in matplotlib

I've tried the other threads, but can't work out how to solve. I'm attempting to create a discrete colorbar. Much of the code appears to be working, a discrete bar does appear, but the labels are wrong and it throws the error: "No mappable was found to use for colorbar creation. First define a mappable such as an image (with imshow) or a contour set (with contourf)."
Pretty sure the error is because I'm missing an argument in plt.colorbar, but not sure what it's asking for or how to define it.
Below is what I have. Any thoughts gratefully received:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
norm = mpl.colors.BoundaryNorm(np.arange(-0.5,4), cmap.N)
ex2 = sample_data.plot.scatter(x='order_count', y='total_value',c='cluster', marker='+', ax=ax, cmap='plasma', norm=norm, s=100, edgecolor ='none', alpha=0.70)
plt.colorbar(ticks=np.linspace(0,3,4))
plt.show()
Indeed, the fist argument to colorbar should be a ScalarMappable, which would be the scatter plot PathCollection itself.
Setup
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({"x" : np.linspace(0,1,20),
"y" : np.linspace(0,1,20),
"cluster" : np.tile(np.arange(4),5)})
cmap = mpl.colors.ListedColormap(["navy", "crimson", "limegreen", "gold"])
norm = mpl.colors.BoundaryNorm(np.arange(-0.5,4), cmap.N)
Pandas plotting
The problem is that pandas does not provide you access to this ScalarMappable directly. So one can catch it from the list of collections in the axes, which is easy if there is only one single collection present: ax.collections[0].
fig, ax = plt.subplots()
df.plot.scatter(x='x', y='y', c='cluster', marker='+', ax=ax,
cmap=cmap, norm=norm, s=100, edgecolor ='none', alpha=0.70, colorbar=False)
fig.colorbar(ax.collections[0], ticks=np.linspace(0,3,4))
plt.show()
Matplotlib plotting
One could consider using matplotlib directly to plot the scatter in which case you would directly use the return of the scatter function as argument to colorbar.
fig, ax = plt.subplots()
scatter = ax.scatter(x='x', y='y', c='cluster', marker='+', data=df,
cmap=cmap, norm=norm, s=100, edgecolor ='none', alpha=0.70)
fig.colorbar(scatter, ticks=np.linspace(0,3,4))
plt.show()
Output in both cases is identical.

errorbar, but not line, as marker symbol in python matplotlib legend

I have a errorbar plot with only one data point (i.e. one errorbar) per data set. Therefore I would like to have a single errorbar symbol in the legend as well.
The single one can be achieved by legend(numpoints=1). Using this in the following code:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.errorbar(x=[0.3], y=[0.7], xerr=[0.2], marker='+', markersize=10, label='horizontal marker line')
ax.errorbar(x=[0.7], y=[0.3], yerr=[0.2], marker='+', markersize=10, label='is too long')
ax.set_xlim([0,1])
ax.set_ylim([0,1])
ax.legend(numpoints=1) # I want only one symbol
plt.show()
results in these symbols in the legend:
As you see, the errorbars are mixed up with horizontal lines, that make sense when there are more than one error bars to be connected (using legend(numpoints=2) or higher), but look ugly in my case.
How can I get rid of the lines in the legend markers without loosing the errorbars?
This is due to the default settings in matplotlib. At the start of your code you can change them by changing the settings using rcParams:
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rcParams['legend.handlelength'] = 0
mpl.rcParams['legend.markerscale'] = 0
fig, ax = plt.subplots()
ax.errorbar(x=[0.3], y=[0.7], xerr=[0.2], marker='+', markersize=10, label='horizontal marker')
ax.errorbar(x=[0.7], y=[0.3], yerr=[0.2], marker='+', markersize=10, label='is gone')
ax.set_xlim([0,1])
ax.set_ylim([0,1])
ax.legend(numpoints=1)
plt.show()
Note: This changes the settings for all the graphs that will be plotted in the code.

Why I get additional empty plot in matplotlib?

I have the following code in my IPython notebook:
import matplotlib.pyplot as plt
plt.setp(plt.xticks()[1], rotation=45)
plt.figure(figsize=(17, 10)) # <--- This is the problematic line!!!!!!!!!!!!!
plt.plot_date(df['date'],df['x'], color='black', linestyle='-')
plt.plot_date(df['date'],df['y'], color='red', linestyle='-')
plt.plot_date(df['date'],df['z'], color='green', linestyle='-')
In the above example df is pandas data frame.
Without the marked line (containig figsize) the plot is too small. With the mentioned line I have an increased image as I want but before it I have an additional empty plot.
Does anybody know why it happens an how this problem can be resolved?
Try reversing the first two lines after the import. plt.setp is opening a figure.
here's how I would do this:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(17, 10))
plt.setp(plt.xticks()[1], rotation=45)
ax.plot_date(df['date'],df['x'], color='black', linestyle='-')
ax.plot_date(df['date'],df['y'], color='red', linestyle='-')
ax.plot_date(df['date'],df['z'], color='green', linestyle='-')
It's a good practice to explicitly create and operate on your your Figure and Axes objects.

Categories

Resources