Stream plot with varying colours in matplotlib giving 2 cmaps - python

A stream plot, or streamline plot, is used to display 2D vector fields. I am creating a stream plot with varying colors in Python but am getting two different cmap on the side. The code used is almost identical to the help file but I am getting multiple cmaps on the third plot. How does one remove the second cmap?
Below is the code that I used followed by the output.
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
x,y = np.meshgrid(np.linspace(-5,5,20),np.linspace(-5,5,20))
xdot = y
ydot = -2*x - 3*y
# subplot2grid
fig = plt.figure(figsize=(18,10))
ax1 = plt.subplot2grid((2,2), (0, 0))
ax2 = plt.subplot2grid((2,2), (0, 1))
ax3 = plt.subplot2grid((2,2), (1, 0))
ax4 = plt.subplot2grid((2,2), (1, 1))
# Plot 1
Q = ax1.quiver(x, y, xdot, ydot, scale=500, angles='xy') # Quiver key
ax1.quiverkey(Q,-10,22.5,30,'5.1.8',coordinates='data',color='k')
ax1.set(xlabel='x', ylabel='y')
ax1.set_title('Quiver plot 6.1.1')
# Plot 2
strm = ax2.streamplot(x, y, xdot, ydot, density=1, color='k', linewidth=2) # streamplot(X,Y,u,v)
fig.colorbar(strm.lines)
ax2.set(xlabel='x', ylabel='y')
ax2.set_title('Stream plot of 6.1.1')
# Plot 4
strm = ax4.streamplot(x, y, xdot, ydot, density=1, color=xdot, linewidth=2, cmap='autumn') # streamplot(X,Y,u,v, density = 1)
fig.colorbar(strm.lines, ax=ax4)
ax4.set(xlabel='x', ylabel='y', title='Stream plot of 6.1.1 with varying color')
plt.show()
The help file for the stream plot has an example that worked to implement this problem that worked as desired. This is what I used to plot the original stream plot.
Stream plot
Constrained Layout Guide
Summary
So to summarize my question. How does one remove the two color maps at the side?
Any help would be highly appreciated.

You should specify the ax of the ax2.streamplot:
import numpy as np
import matplotlib.pyplot as plt
x,y = np.meshgrid(np.linspace(-5,5,20),np.linspace(-5,5,20))
xdot = y
ydot = -2*x - 3*y
# subplot2grid
fig = plt.figure(figsize=(18,10))
ax1 = plt.subplot2grid((2,2), (0, 0))
ax2 = plt.subplot2grid((2,2), (0, 1))
ax3 = plt.subplot2grid((2,2), (1, 0))
ax4 = plt.subplot2grid((2,2), (1, 1))
# Plot 1
Q = ax1.quiver(x, y, xdot, ydot, scale=500, angles='xy') # Quiver key
ax1.quiverkey(Q,-10,22.5,30,'5.1.8',coordinates='data',color='k')
ax1.set(xlabel='x', ylabel='y')
ax1.set_title('Quiver plot 6.1.1')
# Plot 2
strm = ax2.streamplot(x, y, xdot, ydot, density=1, color='k', linewidth=2) # streamplot(X,Y,u,v)
fig.colorbar(strm.lines, ax = ax2) # <--- TO BE DELETED
ax2.set(xlabel='x', ylabel='y')
ax2.set_title('Stream plot of 6.1.1')
# Plot 4
strm = ax4.streamplot(x, y, xdot, ydot, density=1, color=xdot, linewidth=2, cmap='autumn') # streamplot(X,Y,u,v, density = 1)
fig.colorbar(strm.lines, ax=ax4)
ax4.set(xlabel='x', ylabel='y', title='Stream plot of 6.1.1 with varying color')
plt.show()
Alternatively, you can delete the above line of code in order to remove the undesired colorbar:

Related

Difference between plotting a graph with/without axes with/without the same axes name inside a subplot

What is the difference between plotting a graph with/without axes with/without the same name inside a subplot? They all output the same graph.
Plotting a graph with axes with the same name inside a subplot:
from matplotlib import pyplot as plt
plt.figure(figsize=(10,5))
ax = plt.subplot(1, 2, 1)
ax.plot(temperature, months)
ax = plt.subplot(1, 2, 2)
ax.plot(temperature, flights_to_hawaii, 'o')
Plotting a graph with axes with the different names inside a subplot:
from matplotlib import pyplot as plt
plt.figure(figsize=(10,5))
ax1 = plt.subplot(1, 2, 1)
ax1.plot(temperature, months)
ax2 = plt.subplot(1, 2, 2)
ax2.plot(temperature, flights_to_hawaii, 'o')
Plotting a graph without axes inside a subplot:
from matplotlib import pyplot as plt
plt.figure(figsize=(10,5))
plt.subplot(1, 2, 1)
plt.plot(temperature, months)
plt.subplot(1, 2, 2)
plt.plot(temperature, flights_to_hawaii, 'o')
This is actually a great question and the first comment points to a good answer.
The summary is this:
They are both the same for simple plots where there is one line and one axis.
The difference is best highlighted here with this piece of code where we can see the usage of two separate axis (with different colours and scales). ax1 and ax2 will be different.
import numpy as np
from matplotlib import pyplot as plt
# generate some data
time = np.arange(0., 10., 0.2)
velocity = np.zeros_like(time, dtype=float)
distance = np.zeros_like(time, dtype=float)
g = 9.8 # m/s^2
velocity = g * time
distance = 0.5 * g * np.power(time, 2)
# create a plot with TWO acis
fig, ax1 = plt.subplots()
ax1.set_ylabel("distance (m)", color="blue")
ax1.set_xlabel("time")
ax1.plot(time, distance, "blue")
ax1.set_yticks(np.linspace(*ax1.get_ybound(), 10))
ax1.tick_params(axis="y", labelcolor="blue")
ax1.xaxis.grid()
ax1.yaxis.grid()
ax2 = ax1.twinx() # create another y-axis sharing a common x-axis
ax2.set_ylabel("velocity (m/s)", color="green")
ax2.set_xlabel("time")
ax2.tick_params(axis="y", labelcolor="green")
ax2.plot(time, velocity, "green")
ax2.set_yticks(np.linspace(*ax2.get_ybound(), 10))
fig.set_size_inches(7,5)
fig.set_dpi(100)
fig.legend(["Distance", "Velocity"])
plt.show()
Which gives this:
Here we have controlled the two separate axis: ax1 and ax2 and plotted on the same chart.

How to plot in figure coordinates in matplotlib?

I want to retrieve the figure coordinates of one scatter point and set a second point exactly at that point - solely based on figure coordinates and not on axes or data coordinates.
My approach, to plot the red cross (last line) on top of the blue point, does not work yet:
import matplotlib.pyplot as plt
fig, ax0 = plt.subplots()
point0 = ax0.scatter(1, 1)
ax0.set_xlim(0, 2)
ax0.set_ylim(0, 2)
bbox = ax0.get_position()
ax1 = fig.add_axes(bbox)
ax1.set_xlim(0, 2)
ax1.set_ylim(0, 2)
ax1.axis('off')
point1 = ax1.scatter(1, 0.5, marker='x')
x, y = ax0.transData.transform((1, 1))
print('x={}'.format(x), 'y={}'.format(y))
ax1.scatter(x, y, marker='x', color='r', transform=fig.transFigure)
prints: x=221.4 y=144.72
I would be thankful for any hints how to solve this.
It turns out that transformation operations solve this problem:
import matplotlib.pyplot as plt
fig, ax0 = plt.subplots()
point0 = ax0.scatter(1, 1)
bbox = ax0.get_position()
ax0.set_xlim(0, 2)
ax0.set_ylim(0, 2)
mytrans = ax0.transData + ax0.transAxes.inverted()
x, y = mytrans.transform((1, 1))
ax1 = fig.add_axes(bbox)
ax1.axis('off')
ax1.set_xlim(0, 2)
ax1.set_ylim(0, 2)
print('x={}'.format(x), 'y={}'.format(y))
ax1.scatter(x, y, marker='x', color='r', transform=ax1.transAxes)
The point needs to be transformed from data to axes coordinates.

Stacked horizontal plots with multiple Y axis varying in scale

Hi I am trying to create:
horizontally stacked plots
Have secondary axis on both plots
Have different scales on axis - unfortunately, both my Y axis currently have the same scale per subplot... :(
Current code:
# Create axes
fig, (ax1, ax2) = plt.subplots(1, 2)
fig.suptitle("XYZ")
fig.set_figheight(5)
fig.set_figwidth(15)
# First graph
ax1.scatter(
df_PTA_clip_pstar["start_time"],
df_PTA_clip_pstar["pstar"],
s=5,
c="black",
label="P*",
)
plt.ylabel("P*")
ax1.scatter(df_PTA_clipkh["start_time"], df_PTA_clipkh["kh"], s=2, c="cyan", label="Kh")
ax1.secondary_yaxis("right")
plt.ylabel("Kh")
# Second graph - will add the correct data to this once first graph fixed
ax2.scatter(x, y, s=5, c="Red", label="P*")
ax2.scatter(x, z, s=5, c="Green", label="Kh")
ax2.secondary_yaxis("right")
plt.tight_layout()
plt.legend()
plt.show()
Current progress:
You can use .twinx() method on each ax object so you can have two plots on the same ax object sharing x-axis:
import matplotlib.pyplot as plt
import numpy as np
# Create axes
fig, (ax1, ax2) = plt.subplots(1, 2)
## First subplot
x = np.random.random_sample(100)
y = np.random.random_sample(100)
ax1.set_xlim(0, 2)
ax1.scatter(x, y,
s=5,
c="black")
ax11 = ax1.twinx()
x = 1 + x
y = 1 + np.random.random_sample(100)
ax11.scatter(x, y,
s=5,
c="red")
## Second subplot
x = 2 * np.random.random_sample(100) - 1
y = np.random.random_sample(100)
ax2.set_xlim(-1, 2)
ax2.scatter(x, y,
s=5,
c="blue")
ax21 = ax2.twinx()
x = 1 + x
y = 10 + np.random.random_sample(100)
ax21.scatter(x, y,
s=5,
c="orange")
plt.show()

Python - Stacking two histograms with a scatter plot

Having an example code for a scatter plot along with their histograms
x = np.random.rand(5000,1)
y = np.random.rand(5000,1)
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111)
ax.scatter(x, y, facecolors='none')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
fig1 = plt.figure(figsize=(7,7))
ax1 = fig1.add_subplot(111)
ax1.hist(x, bins=25, fill = None, facecolor='none',
edgecolor='black', linewidth = 1)
fig2 = plt.figure(figsize=(7,7))
ax2 = fig2.add_subplot(111)
ax2.hist(y, bins=25 , fill = None, facecolor='none',
edgecolor='black', linewidth = 1)
What I'm wanting to do is to create this graph with the histograms attached to their respected axis almost like this example
I'm familiar with stacking and merging the x-axis
f, (ax1, ax2, ax3) = plt.subplots(3)
ax1.scatter(x, y)
ax2.hist(x, bins=25, fill = None, facecolor='none',
edgecolor='black', linewidth = 1)
ax3.hist(y, bins=25 , fill = None, facecolor='none',
edgecolor='black', linewidth = 1)
f.subplots_adjust(hspace=0)
plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
But I have no idea how to attach the histograms to the y axis and x axis like in the picture I posted above, and on top of that, how to vary the size of the graphs (ie make the scatter plot larger and the histograms smaller in comparison)
Seaborn is the way to go for quick statistical plots. But if you want to avoid another dependency you can use subplot2grid to place the subplots and the keywords sharex and sharey to make sure the axes are synchronized.
import numpy as np
import matplotlib.pyplot as plt
x = np.random.randn(100)
y = np.random.randn(100)
scatter_axes = plt.subplot2grid((3, 3), (1, 0), rowspan=2, colspan=2)
x_hist_axes = plt.subplot2grid((3, 3), (0, 0), colspan=2,
sharex=scatter_axes)
y_hist_axes = plt.subplot2grid((3, 3), (1, 2), rowspan=2,
sharey=scatter_axes)
scatter_axes.plot(x, y, '.')
x_hist_axes.hist(x)
y_hist_axes.hist(y, orientation='horizontal')
You should always look at the matplotlib gallery before asking how to plot something, chances are that it will save you a few keystrokes -- I mean you won't have to ask. There are actually two plots like this in the gallery. Unfortunately the code is old and does not take advantage of subplot2grid, the first one uses rectangles and the second one uses axes_grid, which is a somewhat weird beast. That's why I posted this answer.
I think it's hard to do this solely with matplotlib but you can use seaborn which has jointplot function.
import numpy as np
import pandas as pd
import seaborn as sns
sns.set(color_codes=True)
x = np.random.rand(1000,1)
y = np.random.rand(1000,1)
data = np.column_stack((x,y))
df = pd.DataFrame(data, columns=["x", "y"])
sns.jointplot(x="x", y="y", data=df);

Residual plot not aligned with main graph

What is wrong with my residual plot that is causing to not be aligned with my main graph? My code is below.
import matplotlib.pyplot as plt
from scipy import stats
import numpy as np
x = np.array([0.030956,0.032956,0.034956,0.036956,0.038956,0.040956])
y = np.array([10.57821088,11.90701212,12.55570876,13.97542486,16.05403248,16.36634177])
yerr = [0.101614114,0.363255259,0.057234211,0.09289917,0.093288198,0.420165796]
xerr = [0.00021]*len(x)
fig1 = plt.figure(1)
frame1=fig1.add_axes((.1,.3,.8,.6))
m, b = np.polyfit(x, y, 1)
print 'gradient',m,'intercept',b
plt.plot(x, m*x + b, '-', color='grey', alpha=0.5)
plt.plot(x,y,'.',color='black',markersize=6)
plt.errorbar(x,y,xerr=0,yerr=yerr,linestyle="None",color='black')
plt.ylabel('$1/\sqrt{F}$ $(N)$',fontsize=20)
plt.autoscale(enable=True, axis=u'both', tight=True)
plt.grid(False)
frame2=fig1.add_axes((.1,.1,.8,.2))
s = m*x+b #(np.sqrt(4*np.pi*8.85E-12)/2.23E-8)*x
difference = y-s
plt.plot(x, difference, 'ro')
frame2.set_ylabel('$Residual$',fontsize=20)
plt.xlabel('$2s+d_0$ $(m)$',fontsize=20)
you can specify the axis limits. the problem is that autoscale is moving your two plots differently. if you insert 2 lines of code, each specifying the axis limits, it will fix it.
plt.axis([.030,.0415, 10, 17]) #line 17
plt.axis([.030,.0415, -.6, .8]) #line 26
i believe this is what you're looking for.
Try using GridSpec.
from matplotlib import gridspec
fig = plt.figure()
gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1])
ax0 = plt.subplot(gs[0])
ax1 = plt.subplot(gs[1])
ax0.plot(x, m*x + b, '-', color='grey', alpha=0.5)
ax0.plot(x,y,'.',color='black',markersize=6)
ax1.plot(x, difference, 'ro')
And use set_ylabel instead of ylabel (which you use for plt for example) for axes.

Categories

Resources