3D plot in maplotlib - python

I try to visualize 3D surface using Matplolib.
I got a RESULTS.csv file with results:
T1,T2,Energy
0,0.0,0.0,0.0
1,0.0,-1.0,0.02326751
2,0.0,1.0,0.0232677
3,0.0,-2.0,0.09329646
4,0.0,2.0,0.0932964
5,0.0,-3.0,0.20991799
6,0.0,3.0,0.2099179
7,0.0,-4.0,0.37299244
8,0.0,4.0,0.37299269
9,0.0,-5.0,0.58232459
10,0.0,5.0,0.58232482
11,0.0,-6.0,0.83765862
12,0.0,6.0,0.83765867
13,-1.0,0.0,0.02297095
14,1.0,0.0,0.02297112
15,-1.0,-1.0,0.09457491
16,-1.0,1.0,-0.00195612
17,1.0,-1.0,-0.00195583
18,1.0,1.0,0.09457513
19,-1.0,-2.0,0.21270257
20,-1.0,2.0,0.01988884
21,1.0,-2.0,0.01988887
22,1.0,2.0,0.21270261
23,-1.0,-3.0,0.37714697
24,-1.0,3.0,0.08936601
25,1.0,-3.0,0.08936597
26,1.0,3.0,0.37714726
27,-1.0,-4.0,0.58764634
28,-1.0,4.0,0.20399978
29,1.0,-4.0,0.20399997
30,1.0,4.0,0.58764618
Subsequently, I wrote a script:
#!/usr/bin/env python
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
FRAME = pd.read_csv('RESULTS.csv')
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-4, 4, 1.0)
xlen = len(X)
Y = np.arange(-4, 4, 1.0)
ylen = len(Y)
X, Y = np.meshgrid(X, Y)
Z = np.array(FRAME['Energy'])
colortuple = ('y', 'b')
colors = np.empty(X.shape, dtype=str)
for y in range(ylen):
for x in range(xlen):
colors[x, y] = colortuple[(x + y) % len(colortuple)]
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=colors,
linewidth=0, antialiased=False)
ax.set_zlim3d(-1, 1)
ax.w_zaxis.set_major_locator(LinearLocator(6))
plt.show()
Unfortunately it doesn't work in an expecting way and am getting the following error in return:
File "./test.py", line 27, in <module>
linewidth=0, antialiased=False)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 1586, in plot_surface
X, Y, Z = np.broadcast_arrays(X, Y, Z)
File "/usr/local/lib/python2.7/site-packages/numpy/lib/stride_tricks.py", line 191, in broadcast_arrays
shape = _broadcast_shape(*args)
File "/usr/local/lib/python2.7/site-packages/numpy/lib/stride_tricks.py", line 126, in _broadcast_shape
b = np.broadcast(*args[:32])
ValueError: shape mismatch: objects cannot be broadcast to a single shape
Any tips how to fix this error?

Why do you need this buggy "pandas"-module at all?
Everytime I see someone perform "pandas" operations together with numpy and matplotlib there appear absurd errors..
If you read your .csv-file conventionally with xlrd and add each cell value to a numpy array, and all 3 arrays "X", "Y" and "Z" have same length, there is no problem plotting it...
See matplotlib example
http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
print len(X)
print len(Y)
print len(Z) #all 3 arrays must have same length!
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

Related

Python plot using surface

I have this file : https://pastebin.com/WK6K97jv (columns are respectively x,y,z=f(x,y)).
I would like to plot using matplotlib (pyplot) unfortunately I never have to deal with 3d plot and I've tried to do this :
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
fig = plt.figure()
ax = fig.gca(projection='3d')
X=np.genfromtxt('./jpdf1/jpdf1.000533048.dat',usecols=(0,))
Y=np.genfromtxt('./jpdf1/jpdf1.000533048.dat',usecols=(1,))
X, Y = np.meshgrid(X, Y)
Z=np.genfromtxt('./jpdf1/jpdf1.000533048.dat',usecols=(2,))
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
but interpreter back me this :
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/homebrew/lib/python3.9/site-packages/matplotlib/_api/deprecation.py", line 431, in wrapper
return func(*inner_args, **inner_kwargs)
File "/opt/homebrew/lib/python3.9/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 1658, in plot_surface
raise ValueError("Argument Z must be 2-dimensional.")
ValueError: Argument Z must be 2-dimensional.
check the Z.shape whether equal to X.shape or Y.shape.
Z.shape == X.shape
then give your a example.
# import package
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
fig = plt.figure()
ax = fig.gca(projection='3d')
# generate x and y data
X = np.arange(20) # shape: 20
Y = np.arange(30) # shape:30
X, Y = np.meshgrid(X, Y) # convert x y data shape to new shape
print(X.shape) # (20,30)
print(Y.shape) # (20, 30)
Z= np.cos(X**2 + Y**2) # shape =(20,30)
printt(Z.shape) # (20, 30)
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)

How to add R squared (R^2) in matplotlib?

I want to calculate and add R^2 and R in my line chart as a legend, but I only know how to add equations in the chart. Here is my code.My English is poor,I make a mistake in the last question,I don't want to reject your approve.I'm sorry,I hope you can see this question.
import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
y = df["rain"]
x = df["SITE"]
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set(xlabel='year', ylabel='P', title='rain')
ax.grid()
z = np.polyfit(x, y, 1)
p = np.poly1d(z)
plt.plot(x,p(x), "y--")
plt.plot(x, y, 'og-', label=("y=%.6fx+(%.6f)"%(z[0],z[1])))
plt.legend()
You can calculate and plot R^2 as follows given your code:
from sklearn.metrics import r2_score
import matplotlib.pyplot as plt
import numpy as np
import pylab as pl
import pylab
y = df["rain"]
x = df["SITE"]
z = np.polyfit(x, y, 1)
p = np.poly1d(z)
r_squared = r2_score(x, y)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set(xlabel='year', ylabel='P', title='rain')
ax.grid()
pylab.plot(x,p(x), "y--")
pl.plot(x, y, 'og-', label=("y=%.6fx+(%.6f) - $R^2$=%.6f"%(z[0],z[1], r_squared)))
pl.legend()
You can try "$r^2$" (or any combination in a f-string). The $ renders Latex chars in matplotlib labels:
x = np.arange(0, 100)
y = x**2
plt.figure(figsize=(15,10))
plt.plot(x, y, label="y=$x^2$")
plt.legend()

How to add correlation coefficient (R^2) in line chart?

I want to add R^2 and R in my line chart.But I just know how to add equation in the chart.Here is my code.Thanks a lot!
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from sympy import S, symbols, printing
import pylab as pl
# Data for plotting
y = df["rain"]
x = df["SITE"]
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set(xlabel='year', ylabel='P',
title='rain')
ax.grid()
z = np.polyfit(x, y, 1)
p = np.poly1d(z)
pylab.plot(x,p(x),"y--")
pl.plot(x, y, 'og-', label=("y=%.6fx+(%.6f)"%(z[0],z[1])))
pl.legend()

How to make my surface plot appear using Axes3D?

I'm trying to create a surface plot using Python Matplotlib. I've read the documentation in an attempt to figure out where my code was wrong or if I've left anything out, but was having trouble.
The code that I've written is
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def computeCost(X, y, theta):
m = len(y)
predictions = np.dot(X, theta)
squareErros = (predictions - y) ** 2
J = (1 / (2 * m)) * sum(squareErrors)
return J
data = np.loadtxt("./data1.txt", delimiter=',')
X = data[:, 0].reshape(-1, 1)
y = data[:, 1].reshape(-1, 1)
m = len(y)
X = np.concatenate((np.ones((m, 1)), X), axis=1)
theta0_vals = np.linspace(-10, 10, 100) # size (100,)
theta1_vals = np.linspace(-1, 4, 100) # size (100,)
J_vals = np.zeros((len(theta0_vals), len(theta1_vals)))
for i in range(len(x_values)):
for j in range(len(y_values)):
t = np.array([theta0_vals[i], theta1_vals[j]]).reshape(-1, 1)
J_vals[i][j] = computeCost(X, y, t) # size (100, 100)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(theta0_vals, theta1_vals, J_vals)
plt.show()
When I invoke plt.show() I get no output. The surface plot that I'm expecting to see is similar to this:
Would anybody be kind enough to let me know where my usage of the surface plot library went wrong? Thank you.
EDIT
I've tried to run the demo code provided here and it works fine. Here's the code for that:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
# Make data.
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
# Customize the z axis.
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
I think I've figured out the issue by changing a couple of the last lines of code from
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(theta0_vals, theta1_vals, J_vals)
to
ax = plt.axes(projection='3d')
surf = ax.plot_surface(theta0_vals, theta1_vals, J_vals, rstride=1, cstride=1, cmap='viridis', edgecolor='none')
Making this change gives me a surface plot such that:
The link that gave me reference to this was this.

Fixing jagged edges of 3D plot, selecting an appropriate mask

So I have some 3D data that I am able to plot just fine except the edges look jagged.
The relevant code:
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
x = np.arange(-1, 1, 0.01)
y = np.arange(-1, 1, 0.01)
x, y = np.meshgrid(x, y)
rho = np.sqrt(x**2 + y**2)
# Attempts at masking shown here
# My Mask
row=0
while row<np.shape(x)[0]:
col=0
while col<np.shape(x)[1]:
if rho[row][col] > 1:
rho[row][col] = None
col=col+1
row=row+1
# Calculate & Plot
z = rho**2
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x, y, z, rstride=8, cstride=8, cmap=cm.bone, alpha=0.15, linewidth=0.25)
plt.show()
Produces:
This is so close to what I want except the edges are jagged.
If I disable my mask in the code above & replace it with rho = np.ma.masked_where(rho > 1, rho) it gives:
It isn't jagged but not want I want in the corners.
Any suggestions on different masking or plotting methods to get rid of this jaggedness?
Did you consider using polar coordinates (like in this example) ?
Something like:
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# create supporting points in polar coordinates
r = np.linspace(0,1.25,50)
p = np.linspace(0,2*np.pi,50)
R,P = np.meshgrid(r,p)
# transform them to cartesian system
x, y = R * np.cos(P), R * np.sin(P)
rho = np.sqrt(x**2 + y**2)
# Calculate & Plot
z = rho**2
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x, y, z, rstride=1, cstride=1, cmap=cm.bone, alpha=0.15, linewidth=0.25)
plt.show()

Categories