# Plot 3d data

I've been unable to find any viable solution although I'm quite sure there's an easy one.

I'd like to plot a surface from a matrix with some hundred rows that specify a point each, i.e. x y z. The point3d function does the ranges right but lacks the surface option; list_plot3d provides the surface, but does plot by the row/colum indeces instead of the x,y values.

Which function would do the trick?

Ben

(Edit) Thank you both, Frédéric and Emmanuel! Unfortunately, I cannot apply your answers to my problem properly, mainly because I dont fully understand them.

• In Frédéric's answer, M seem's to be a 2x2x3 array and I'm unable to transfer the approach to my Nx3 matrix.
• Emmanuel's list(zip(X,Y,Z)) looks very much like list(myMatrix), but with list_plot3d I still don't get anything like the anticipated result.

I'll try to provide my example here:

myMatrix=[(0.5, 0.0, 29.0),
(1.5, 0.0, 29.0),
(2.5, 0.0, 30.0),
(3.5, 0.0, 38.0),
(5.0, 0.0, 45.0),
(5.01, 0.0, 0.0),
(6.0, 0.0, 0.0),
(0.0, 0.8, 26.0),
(0.5, 0.8, 25.0),
(1.5, 0.8, 24.0),
(2.5, 0.8, 25.0),
(3.5, 0.8, 35.0),
(5.0, 0.8, 39.0),
(5.01, 0.8, 0.0),
(6.0, 0.8, 0.0),
(0.0, 1.8, 27.0),
(0.5, 1.8, 25.0),
(1.5, 1.8, 22.0),
(2.5, 1.8, 22.0),
(3.5, 1.8, 27.0),
(5.0, 1.8, 38.0),
(5.01, 1.8, 0.0),
(6.0, 1.8, 0.0),
(0.0, 2.8, 22.0),
(0.5, 2.8, 20.0),
(1.5, 2.8, 19.0),
(2.5, 2.8, 22.0),
(3.5, 2.8, 28.0),
(5.0, 2.8, 42.0),
(5.01, 2.8, 0.0),
(6.0, 2.8, 0.0),
(0.0, 3.8, 14.0),
(0.5, 3.8, 12.0),
(1.5, 3.8, 10.0),
(2.5, 3.8, 13.0),
(3.5, 3.8, 21.0),
(5.0, 3.8, 39.0),
(5.01, 3.8, 0.0)]
myLiPlo3d=list_plot3d(myMatrix,aspect_ratio=[1,1,0.02])
myLiPlo3dLi=list_plot3d(list(myMatrix),aspect_ratio=[1,1,0.02])
myPlo3d=point3d(myMatrix,size=20,aspect_ratio=[1,1,0.02])


Now

show(myPlo3d)


does result in the plot I'm looking for, except for the fact that it's just points and not a connected surface. However, both,

show(myLiPlo3dLi)
show(myLiPlo3d)


result in a totally different z-scale and shape.

Thinking as I'm editing: May this strange scaling be an artifact of perfect polynomial fitting? That's not what I'm looking for, I don't want any overswings (is that an English word?); I'd even be ok with bilinear interpolation.

edit retag close merge delete

( 2022-05-13 10:18:50 +0100 )edit

give us a toy minimal example of the data you want to plot

( 2022-05-13 15:48:16 +0100 )edit

@BenBoggart : your data may be questionable :

sage: list_plot3d(myMatrix, interpolation_type='linear', aspect_ratio=[8, 8, 1])
/usr/local/sage-9/local/var/lib/sage/venv-python3.10/lib/python3.10/site-packages/sage/repl/rich_output/display_manager.py:605: UserWarning: Warning: converting a masked element to nan.
return obj._rich_repr_(self)
Launched html viewer for Graphics3d Object

( 2022-06-03 23:46:33 +0100 )edit

Res ipsa loquitur...

Playing with parametric_plot3d and more suitable interpolation functions may be a better idea...

( 2022-06-04 00:00:41 +0100 )edit

Awesome, your answer solves my problem as well as it teaches me two or three things about sagemath! Thanks a lot.

I've re-checked the data and don't see any two point having the same x,y-coordinates. The gradient from 5.00 to 5.01 could be a bit steep, but with linear interpolation, I don't really see a numerical issue. Anyway, the plot looks fine for me, so I won't dig into that.

Btw, it may entertain you to know that this is to visualize my floor and get an impression of where to apply some floating screed.

( 2022-06-04 18:30:46 +0100 )edit

Sort by » oldest newest most voted

WorksForMe(TM) in Sagecell and in Sage 9.6.rc3. Let's assess the density of a bivariate standard normal by plotting 1000 random points (I use R's functions by pure laziness...) :

set_random_seed(0)
X=r.rnorm(1000,0,1)._sage_()
Y=r.rnorm(1000,0,1)._sage_()
Z=r.dnorm(list(map(lambda u,v:sqrt(u^2+v^2), X, Y)),0,1)._sage_()
P=list_plot3d(list(zip(X,Y,Z)))
show(P, aspect_ratio=[1,1,5])


See for yourself !

HTH,

more

The final solution is in Emmanuel's 3rd comment and the link there.

( 2022-06-04 18:33:39 +0100 )edit

Shooting in the dark, here is a tentative

def plot_cloud_matrix(M):
m = len(M)
n = len(M[0])
P = point3d(M[0][0])
for i in range(m-1):
for j in range(n-1):
pta = M[i][j]
ptb = M[i+1][j]
ptc = M[i+1][j+1]
ptd = M[i][j+1]
P += polygon3d([pta,ptb,ptc,ptd])
return P

plot_cloud_matrix([[(0,1,2),(0,1,1.2)],[(0.5,1,2),(0.1,1,1.1)]])

more