1

If I have specific x and y values corresponding to a z value separated by array, how would I make a contour plot? For example:

Array 1 (X):
1
4
6
7
8
2
6

Array 2 (Y):
7
7
8
9
0
1
2

Array 3 (Z):
8
9 
7
1
2
2
3

Would I have to do X1, Y1 = np.meshgrid(X, Y) and shape the Z array somehow? Is there another way to do this without using meshgrid? Also, if I add a fourth array and name it Z1 with the same x and y values corresponding to a particular Z1, can I plot this contour plot together with the first contour plot?

Cosmoman
  • 101
  • 1
  • 12

2 Answers2

2

If you do not have a regular grid, using triangular surface interpolation may be a good choice.

In this example and the above one, if you have longer data, you only have to check the boundary of the plot.

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.tri as tri

sns.set(style="white")

x = np.array([1,4,6,7,8,2,6])
y = np.array([7,7,8,9,0,1,2])
z = np.array([8,9,7,1,2,2,3])

fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111)

nptsx, nptsy = 100, 100
xg, yg = np.meshgrid(np.linspace(x.min(), x.max(), nptsx),
                     np.linspace(y.min(), y.max(), nptsy))

triangles = tri.Triangulation(x, y)
tri_interp = tri.CubicTriInterpolator(triangles, z)
zg = tri_interp(xg, yg)

# change levels here according to your data
levels = np.linspace(0, 10, 5)
colormap = ax.contourf(xg, yg, zg, levels,
                       cmap=plt.cm.Blues,
                       norm=plt.Normalize(vmax=z.max(), vmin=z.min()))

# plot data points
ax.plot(x, y, color="#444444", marker="o", linestyle="", markersize=10)

# add a colorbar
fig.colorbar(colormap,
             orientation='vertical',  # horizontal colour bar
             shrink=0.85)

# graph extras: look at xlim and ylim
ax.set_xlim((0, 10))
ax.set_ylim((0, 10))
ax.set_aspect("equal", "box")

plt.show()

This is the output :

enter image description here

Ger
  • 9,076
  • 10
  • 37
  • 48
1

I think you need to do an interpolation:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from scipy import interpolate
x = np.array([1,4,6,7,8,2,6])
y = np.array([7,7,8,9,0,1,2])
z = np.array([8,9,7,1,2,2,3])
points = np.column_stack((x,y))
values = z.T

gridx, gridy = np.mgrid[0:8:100j, 0:8:100j]
gridz = interpolate.griddata(points, values, (gridx, gridy), method='cubic')

fig = plt.figure(figsize=(12,5))

ax1 = fig.add_subplot(121,projection='3d')
ax1.plot3D(x,y,z, 'k.', ms=10)
ax1.contour(gridx,gridy,gridz)

ax2 = fig.add_subplot(122,projection='3d')
ax2.plot3D(x,y,z, 'k.', ms=10)
ax2.plot_wireframe(gridx, gridy, gridz,rstride=5,cstride=5)
plt.savefig('contour_wire.png')

This gives:

enter image description here

Mahdi
  • 3,188
  • 2
  • 20
  • 33
  • 1
    This is very helpful, but say that I have a large data set of 411 points for each x, y, and z arrays. What would I need to change in this program? – Cosmoman Dec 12 '16 at 03:39
  • No, I just have three arrays with (x(array 1),y(array 2)) corresponding to a particular z values( array 3). – Cosmoman Dec 12 '16 at 19:39