How to plot 3D surface plots using Plotly in Python? - python

I am able to get a Surface Plot using matplotlib with this code:
ax = figure.gca(projection = "3d")
ax.plot_surface(meshed_slopes, meshed_intercepts, errors.reshape(1, meshed_slopes.shape[0]), cmap = cm.autumn_r)
But when I try to do the same using Plotly I get a blank graph.
This is the code am using to plot the surface plot-
import plotly.graph_objects as go
import numpy as np
meshed_slopes, meshed_intercepts = np.meshgrid(slopes, intercepts)
fig = go.Figure(go.Surface(
x = meshed_slopes,
y = meshed_intercepts,
z = errors.reshape(1, meshed_slopes.shape[0])
))
fig.show()
How can I fix this?
Thanks in advance!!!

Since you haven't provided the data so we can take a look I'm going to explain what plotly needs to make the plot work :
x and y needs to be both (n,) shape and same shape
z should be a matrix or a table with (n,n) size
I would suggest a dataframe as it might be easier for you to create everything
(Since I have low rep, I can't write comments so I'm posting this as an answear)

Make sure that x, y, z are 2D arrays.
import plotly.graph_objects as go
import numpy as np
x, y = np.mgrid[-2:2:50j, -2:2:50j]
z = np.cos(x**2 + y**2)
fig = go.Figure([
go.Surface(x=x, y=y, z=z)
])
fig

Related

Need help in understanding how to 3d surface plot using plotly

I am trying to plot a function z= sinx cosy over -pi to pi
This is what I'm hoping to get
Also shown like this
This is the code I have written in an attempt to do the same:
import plotly.graph_objs as go
from scipy.linalg import toeplitz
x=np.linspace(-np.pi,np.pi,30)
z = [(np.sin(i)*np.cos(i)) for i in x]
fig = go.Figure(data=[go.Surface(x=x, y=x, z=toeplitz(z))])
fig.show()
plotly output that I'm getting
I have not been able to understand what 'grid' or '2d array' format I have to convert my z co-ordinate column data into for getting the right graph. Toeplitz was an attempt to do the same, but it seems symmetric unlike the required graph. Please help
I think I've got it, if you're facing similar issue you can refer/use the code below
import numpy as np
import plotly.graph_objs as go
f = lambda x,y: np.sin(x) * np.cos(y)
x = np.linspace(-np.pi, np.pi, 30)
y = np.linspace(-np.pi, np.pi, 30)
X,Y = np.meshgrid(x,y)
F = f(X,Y)
fig = go.Figure(data=[go.Surface(x=X, y=Y, z=F)])
fig.show()

Plotly library not showing markers in 3D scatter plot

In the default tutorial provided by plotly, the following produces a nice image, and has markers appearing on the plot (in accordance with https://plotly.com/python/3d-scatter-plots/#3d-scatter-plot-with-plotly-express):
import plotly.graph_objects as go
import numpy as np
# Helix equation
t = np.linspace(0, 10, 50)
x, y, z = np.cos(t), np.sin(t), t
fig = go.Figure(data=[go.Scatter3d(x=x, y=y, z=z,mode='markers')])
fig.show()
However if I try to plot some random scatter as follows:
import plotly.graph_objects as go
import numpy as np
x = np.random.randn(10,1)
fig = go.Figure(data=[go.Scatter3d(x=x, y=x, z=x,mode='markers')])
fig.show()
Nothing shows. It is a blank axis with no markers appearing. Would anyone happen to know why?
I've tried to change dimensions, transpose, variable names etc, but still nothing?
It will work if you flatten the array, e.g. if you add x = x.flatten() before the plot.

How to make Python chart that only contain Vertical and horizontal Lines?

How to draw something like this?
There's kind of like a horizontal line until next data point show up, then a vertical line to adjust the location y. The usual plot function in matplotlib just plot a straight line between two data point, which doesn't satisfy what I need.
You may use one of the drawstyles "steps-pre", "steps-mid", "steps-post" to get a a step-like appearance of your curve.
plt.plot(x,y, drawstyle="steps-pre")
Full example:
import matplotlib.pyplot as plt
import numpy as np; np.random.seed()
x = np.arange(12)
y = np.random.rand(12)
styles = ["default","steps-pre","steps-mid", "steps-post"]
fig, axes = plt.subplots(nrows=len(styles), figsize=(4,7))
for ax, style in zip(axes, styles):
ax.plot(x,y, drawstyle=style)
ax.set_title("drawstyle={}".format(style))
fig.tight_layout()
plt.show()
Just as #cricket_007 said in the comments -- make each y value repeat at the next x value. Below a way how to achieve this with numpy.
EDIT:
Thanks to the comment by #ImportanceOfBeingErnest I replaced the original code that extended the data with a much simpler solution.
from matplotlib import pyplot as plt
import numpy as np
#producing some sample data
x = np.linspace(0,1,20)
y = np.random.rand(x.shape[0])
#extending data to repeat each y value at the next x value
##x1 = np.zeros(2*x.shape[0]-1)
##x1[::2] = x
##x1[1::2] = x[1:]
x1 = np.repeat(x,2)[1:]
##y1 = np.zeros(2*y.shape[0]-1)
##y1[::2] = y
##y1[1::2] = y[:-1]
y1 = np.repeat(y,2)[:-1]
plt.plot(x1, y1)
plt.show()
The result looks like this:

How to slice list from matplotlib ginput

I have a list of values in Python, which I'm plotting with matplotlib. I'm then trying to use ginput in matplotlib to click two points on the graph, from which the X coordinates will be taken, between which to slice my original list. However, I can't seem to find a way to do this.
I already have a list of numbers called MIList, and the following code isn't working for me:
startinput = plt.ginput(2)
print("clicked", startinput)
startinputxvalues = [x[0] for x in startinput]
print(startinputxvalues)
x1 = startinputxvalues[0]
print(x1)
x2 = startinputxvalues[1]
print(x2)
slicedMIList = [MIList[int(x1):int(x2)]]
plt.plot(slicedMIList)
This gives me an array, but it doesn't plot these values on my graph - does anyone have any input as to what I'm doing wrong?
Thanks
The main point is that you need to redraw the canvas, once changes have been made to it. So in order for the new plot to become visible you can call
plt.gcf().canvas.draw()
Here is a complete working code:
import matplotlib.pyplot as plt
import numpy as np
X = np.arange(10)
Y = np.sin(X)
plt.plot(X, Y)
startinput = plt.ginput(2)
x, y = zip(*startinput)
Ysliced = Y[int(x[0]):int(x[1])+1]
Xsliced = X[int(x[0]):int(x[1])+1]
plt.plot(Xsliced, Ysliced, color="C3", linewidth=3)
#draw the canvas, such that the new plot becomes visible
plt.gcf().canvas.draw()
plt.show()

Basic scatter plot with reference data on diagonal (identity line)

I have two arrays x,y obtained from a machine learning calculations and I wish to make a scatter plot with the reference data x on the diagonal in a way to visualize better the predicted values y against the true ones x. Please can you suggest me how to do it in python or gnuplot?
import numpy as np
import matplotlib.pyplot as plt
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
plt.scatter(x, y, c=colors)
plt.plot( [0,1],[0,1] )
plt.savefig('a.png')
This will produce:
Check this page for more information.
a simple example:
import matplotlib.pyplot as plt
import numpy as np
x=np.linspace(0,100,101)
y=np.random.normal(x) # add some noise
plt.plot(x,y,'r.') # x vs y
plt.plot(x,x,'k-') # identity line
plt.xlim(0,100)
plt.ylim(0,100)
plt.show()
In matplotlib, you can also draw an "infinite" line in order to avoid having to define the exact coordinates. For example, if you have an axes ax, you can do:
pt = (0, 0)
ax.axline(pt, slope=1, color='black')
where pt is an intersection point. Note if pt isn't included in the limits of the plot, the limits will be modified to include it.

Categories