plot_surface reduces density of points - matplotlib

Trying to plot a surface using matplotlib. However, the plotted surface has lower grid density than the meshgrid.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
xgrid = np.arange(0,1,1/100)
ygrid = xgrid.copy()
xx, yy = np.meshgrid(xgrid,ygrid)
fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')
ax.plot_surface(xx,yy,np.square(xx)+np.square(yy))
The meshgrid was defined to have 100 segments in each direction. However, the surface in the figure doesn't have 100 segments. Is there anyway to render the surface with the same density?
Don't worry, you don't have to count the number of segments, so I overlap the plot with a scatter plot with the same points
ax.scatter3D(xx,yy,np.square(xx)+np.square(yy))
Upon zooming in, you can see that each grid of the surface plot has a scatter point in the middle, which shows that the plot_surface changed the density of the points.
Usually it doesn't matter for smooth plots such as these, but I have singular points in my data which sometimes disappear in the surface plot because of this

Related

How to entend the area/boudaries that shows the data from a Axes3D with matplolib when using the set_box_aspect zoom

I'm trying to zoom in a 3D plot. I'm using the ax.set_box_aspect() fonction. When doing so, the axis are zoomed in, they appear bigger, but the area where the data can be seen stay at the same size as before (the plot are not using the total available space).
The aim in the end is to have two axis, the first one 3d, the other one 2d. I would have wanted the first plot to take all the space available at the top half of the figure.
Here is the code before the Zoom
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
#---- generate data
nn = 100
X = np.random.randn(nn)*20 + 0
Y = np.random.randn(nn)*50 + 30
Z = np.random.randn(nn)*10 + -5
#---- check aspect ratio
asx, asy, asz = np.ptp(X), np.ptp(Y), np.ptp(Z)
fig = plt.figure(figsize=(15,15))
ax = fig.add_subplot(211, projection='3d')
#---- set box aspect ratio
ax.set_box_aspect((asx,asy,asz))
scat = ax.scatter(X, Y, Z, c=X+Y+Z, s=500, alpha=0.8)
ax.set_xlabel('X-axis'); ax.set_ylabel('Y-axis'); ax.set_zlabel('Z-axis')
ax = fig.add_subplot(212)
plt.show()
Before using the zoom
And now when I zoom in, the scatter is limitted in a square frame :
ax.set_box_aspect((asx,asy,asz), zoom = 2 )
After using the zoom
(The data used for the plot doesn't matter here, it is just to showcase my issue.)
I tried changing the axis limit with set_xlim3d or set_xlim, but in either case, the result is the same.
It seems like the showing area (I can't find the right word for it) stays a square no matter what.
I didn't find any usefull information on that matter online, (maybe from the lack of vocabulary to describe my problem).

Data visualization using Matplotlib

By using this code I'm able to generate 20 data points on y-axis corresponding to x-axis, but I want to mark the 25 data points on the line as downward pointed triangles without changing arr_x=np.linspace(0.0,5.0,20) to arr_x=np.linspace(0.0,5.0,25).
will it possible to mark additional data points on y-axis without changing x-axis ?
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
def multi_curve_plot():
# Write your functionality below
fig=plt.figure(figsize=(13,4))
ax=fig.add_subplot(111)
arr_x=np.linspace(0.0,5.0,20)
arr_y1=np.array(arr_x)
arr_y2=np.array(arr_x**2)
arr_y3=np.array(arr_x**3)
ax.set(title="Linear, Quadratic, & Cubic Equations", xlabel="arr_X",
ylabel="f(arr_X)")
ax.plot(arr_x, arr_y1, label="y = arr_x", color="green", marker="v")
ax.plot(arr_x, arr_y2, label ="y = arr_x**2", color ="blue", marker="s")
ax.plot(arr_x, arr_y3, label="y = arr_x**3", color="red", marker="o")
plt.legend()
return fig
return None
multi_curve_plot()
I tried changing arr_x=np.linspace(0.0,5.0,20) to arr_x=np.linspace(0.0,5.0,25). But I want to show 25 data points on y axis without changing x-axis attributes.

Warping Matplotlib/Seaborn Scatter Plot into Parallelogram

I have a 2D scatterplot (in either matplotlib or seaborn) and an angle e.g. 64 degrees. I want to plot a warped version of this scatter plot where the x-axis of the first plot is held fixed but the second axis is warped such that the y-axis of the first plot is now at the given angle with the x-axis of the new plot (i.e. 64 degrees). How can I do this?
In other words, I want to take the original scatter plot and "push" the y-axis to the right to form a parallelogram-like plot where the angle between the old y axis and the old/new x-axis is the given angle.
Here is an adaption of an old tutorial example:
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D
import mpl_toolkits.axisartist.floating_axes as floating_axes
import numpy as np
fig = plt.figure()
skewed_transform = Affine2D().skew_deg(90 - 64, 0)
grid_helper = floating_axes.GridHelperCurveLinear(skewed_transform, extremes=(-0.5, 1.5, -0.5, 1.5))
skewed_ax = floating_axes.FloatingSubplot(fig, 111, grid_helper=grid_helper)
skewed_ax.set_facecolor('0.95') # light grey background
skewed_ax.axis["top"].set_visible(False)
skewed_ax.axis["right"].set_visible(False)
fig.add_subplot(skewed_ax)
x, y = np.random.rand(2, 100) # random point in a square of [0,1]x[0,1]
skewed_ax.scatter(x, y, transform=skewed_transform + skewed_ax.transData)
plt.show()

Overlay two seaborn barplots of different size

Say there are two datasets: a big "background" set, and much smaller "foreground" set. The foreground set comes from the background, but might be much smaller.
I am interested in showing the entire background distribution in an ordered sns.barplot, and have the foreground set a brighter contrasting color to draw attention to these samples.
The best solution I could find is to display one graph on top of the other, but what happens is the graph shrinks down to the smaller domain. Here's what I mean:
import matplotlib.pyplot as plt
import seaborn
# Load the example car crash dataset
crashes = sns.load_dataset("car_crashes").sort_values("total", ascending=False)
# states of interest
txcahi = crashes[crashes['abbrev'].isin(['TX','CA','HI'])]
# Plot the total crashes
f, ax = plt.subplots(figsize=(10, 5))
plt.xticks(rotation=90, fontsize=10)
sns.barplot(y="total", x="abbrev", data=crashes, label="Total", color="lightgray")
# overlay special states onto gray plot as red bars
sns.barplot(y="total", x="abbrev", data=txcahi, label="Total", color="red")
sns.despine(left=True, bottom=True)
This data produces:
But it should look like this (ignore stylistic differences):
Why doesn't this approach work, and what would be a better way to accomplish this?
A seaborn barplot just plots the its n data along the values of 0 to n-1. If instead you'd use a matplotlib bar plot, which is unit aware (from matplotlib 2.2 onwards), it'll work as expected.
import matplotlib.pyplot as plt
import seaborn as sns
# Load the example car crash dataset
crashes = sns.load_dataset("car_crashes").sort_values("total", ascending=False)
# states of interest
txcahi = crashes[crashes['abbrev'].isin(['TX','CA','HI'])]
# Plot the total crashes
f, ax = plt.subplots(figsize=(10, 5))
plt.xticks(rotation=90, fontsize=10)
plt.bar(height="total", x="abbrev", data=crashes, label="Total", color="lightgray")
plt.bar(height="total", x="abbrev", data=txcahi, label="Total", color="red")
sns.despine(left=True, bottom=True)

How to overlay one pyplot figure on another

Searching easily reveals how to plot multiple charts on one figure, whether using the same plotting axes, a second y axis or subplots. Much harder to uncover is how to overlay one figure onto another, something like this:
That image was prepared using a bitmap editor to overlay the images. I have no difficulty creating the individual plots, but cannot figure out how to combine them. I expect a single line of code will suffice, but what is it? Here is how I imagine it:
bigFig = plt.figure(1, figsize=[5,25])
...
ltlFig = plt.figure(2)
...
bigFig.overlay(ltlFig, pos=[x,y], size=[1,1])
I've established that I can use figure.add_axes, but it is quite challenging getting the position of the overlaid plot correct, since the parameters are fractions, not x,y values from the first plot. It also [it seems to me - am I wrong?] places constraints on the order in which the charts are plotted, since the main plot must be completed before the other plots are added in turn.
What is the pyplot method that achieves this?
To create an inset axes you may use mpl_toolkits.axes_grid1.inset_locator.inset_axes.
Position of inset axes in axes coordinates
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
fig, ax= plt.subplots()
inset_axes = inset_axes(ax,
width=1, # inch
height=1, # inch
bbox_transform=ax.transAxes, # relative axes coordinates
bbox_to_anchor=(0.5,0.5), # relative axes coordinates
loc=3) # loc=lower left corner
ax.axis([0,500,-.1,.1])
plt.show()
Position of inset axes in data coordinates
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
fig, ax= plt.subplots()
inset_axes = inset_axes(ax,
width=1, # inch
height=1, # inch
bbox_transform=ax.transData, # data coordinates
bbox_to_anchor=(250,0.0), # data coordinates
loc=3) # loc=lower left corner
ax.axis([0,500,-.1,.1])
plt.show()
Both of the above produce the same plot
(For a possible drawback of this solution see specific location for inset axes)