5

I am trying to create a 3D surface plot using float arrays. I tried the available answer but was not successful.

My code:

     ydata       xdata      zdata
0  667.029710  38.666953  2156.370026
1  673.518030  38.578639  2167.733673
2  928.285970  39.558060  2984.315454
3  947.973966  39.329530  3065.414025
4  904.826638  40.241960  3071.355114
5  901.673720  40.259228  2947.752668
6  910.980404  41.478425  2906.467214
7  916.008852  41.813555  2933.900440
8  913.971114  41.583315  2955.543549
9  933.040692  42.577816  2979.264288 

import plotly.graph_objects as go
import plotly.graph_objs
import pandas as pd
import numpy as np
xdata = df['xdata'].values
ydata = df['ydata'].values
zdata = df['zdata'].values
plotly.offline.plot({"data":[go.Surface(z=zdata, x=xdata, y=ydata)],
"layout":plotly.graph_objs.Layout(title='Some data', autosize=False,
                  width=500, height=500,
                  margin=dict(l=65, r=50, b=65, t=90))})

It is not producing the output. I see the 3d plot but not any data.

rpanai
  • 12,515
  • 2
  • 42
  • 64
Mainland
  • 4,110
  • 3
  • 25
  • 56
  • 1
    Does this answer your question? [Plotly Plot surface 3D not displayed](https://stackoverflow.com/questions/48966097/plotly-plot-surface-3d-not-displayed) – dm2 Aug 10 '20 at 22:21
  • @dm2 No. I mean I tried to understand it but could not. Could you help me how to make `zdata` as a surface based on the referred answer? – Mainland Aug 10 '20 at 23:01
  • I'm just learning plotly myself, but from the documentation and from the answer in the previous link, zdata would need to be 2-dimensional, with a value for each x and y pair. So, if you have an xdata array of size 5, a ydata array of size 5, you would need a 5*5 array with 25 values in zdata. All of your values a 1-dimensional arrays with a size of 10, and thus there's not really an area to display – dm2 Aug 10 '20 at 23:04
  • @dm2 Thanks a lot for helping to understand the surface plot. Does it mean, to draw a 3D plot, z-data must be a function of x and y? I mean, we cannot simply draw for 3 independent data values? – Mainland Aug 10 '20 at 23:07
  • 1
    I would imagine you could, but the shape/size/dimensionality requirements still apply, so you would still need a z value for each x/y pair. For example, following the code from the linked answer, if you do `go.Surface(z = [zdata]*10, x = xdata, y = ydata)` it should work (I tried and it did work, if I remember the code correctly). Although similarly as in 2-d line graphs, I would think Surface plots imply some sort of relationship between the variables. – dm2 Aug 10 '20 at 23:12
  • 1
    @dm2 Ok. If I interpret the answer rightly, `z=[zdata.tolist()]*len(xdata)` is this correct? – Mainland Aug 10 '20 at 23:18
  • 1
    I think so (although the code I wrote should work too). As I've said, I'm still learning this, so check documentation as well. – dm2 Aug 10 '20 at 23:20
  • @dm2 ok. I tried this. It did not give any error but it did not plot the data, just empty 3d plot appeared. – Mainland Aug 10 '20 at 23:26
  • Might be some other issue, I've tried several different ways of reforming zdata and all worked fine. – dm2 Aug 11 '20 at 00:31
  • @dm2 Thanks a ton for working on this. The problem is, my actual df length is 4000. I am wondering whether this is affecting the plot? Whether the plotly surface plot works only for integers? not float? – Mainland Aug 11 '20 at 00:34

1 Answers1

3

If the data is specified in one dimension, it won't be displayed because it won't be configured with 3D information. If you specify the entire data frame, as in the code, it will be displayed. Official Reference

import pandas as pd
import numpy as np
import io

data = '''
 ydata xdata zdata
0 667.029710 38.666953 2156.370026
1 673.518030 38.578639 2167.733673
2 928.285970 39.558060 2984.315454
3 947.973966 39.329530 3065.414025
4 904.826638 40.241960 3071.355114
5 901.673720 40.259228 2947.752668
6 910.980404 41.478425 2906.467214
7 916.008852 41.813555 2933.900440
8 913.971114 41.583315 2955.543549
9 933.040692 42.577816 2979.264288 
'''

df = pd.read_csv(io.StringIO(data), sep='\s+')

import plotly.graph_objects as go
import plotly.graph_objs

# xdata = df['xdata'].values
# ydata = df['ydata'].values
# zdata = df['zdata'].values

plotly.offline.plot({"data":[go.Surface(z=df.values)],
"layout":plotly.graph_objs.Layout(title='Some data', autosize=False,
                  width=500, height=500,
                  margin=dict(l=65, r=50, b=65, t=90))})

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32
  • Thanks a ton for helping me with this. I am trying to understand the surface plot in general. In the above plot, what constitutes x and y axis? – Mainland Aug 11 '20 at 02:59
  • I don't use 3D graphs, so I'm not sure, but I think y(0-9) and x(01,2) show the number of indices for each. – r-beginners Aug 11 '20 at 03:12
  • Your answer did help me to see what I wanted. I used `plotly.offline.plot({"data":[go.Surface(x=df['x'].values,y=df['y'].values,z=df[['x','y','z']].values)], "layout":plotly.graph_objs.Layout(title='Some data', autosize=False,width=500, height=500,scene = dict(xaxis_title='X AXIS TITLE',yaxis_title='Y AXIS TITLE',zaxis_title='Z AXIS TITLE'),margin=dict(l=15, r=10, b=15, t=90))})` This worked perfectly. Thanks a ton. – Mainland Aug 11 '20 at 03:22
  • A final question: do know how to save this created html image? `plotly.offline.plot(fig, filename='temp-plot.html')` is this? – Mainland Aug 11 '20 at 03:33
  • You can click on the camera icon in the menu displayed (top left corner of the graph) to save the image locally in PNG format. The menu will appear when you click on the blank part of the graph. – r-beginners Aug 11 '20 at 03:36
  • Right, that's for PNG. I want to save html. – Mainland Aug 11 '20 at 03:38
  • Are there any HTML files saved from the browser menu or displayed locally in the program files? – r-beginners Aug 11 '20 at 04:54