Reputation: 457
As the title indicates I would like to make a contour plot by using three 1D arrays. Let's say that
x = np.array([1,2,3])
and
y = np.array([1,2,3])
and
z = np.array([20,21,45])
To do a contourplot in matplotlib i meshed the x
and y
coordinate as X,Y = meshgrid(x,y)
but then the z
array must also be a 2D array. How do I then turn z
into a 2d array so it can be used?
Upvotes: 9
Views: 30459
Reputation: 33830
Although OP realized that it is not possible to draw a contour plot with the data in the question, this is still a relevant question in situations where the data can be thought of a 3d surface.
There are basically three options
This one is super-simple. Just use the plt.tricontourf function like this (see creation of the example data in the appendix)
from matplotlib import pyplot as plt
plt.tricontourf(xdata, ydata, zdata)
plt.show()
If one has gridded data stored in three 1D-arrays, and for some reason does not want to use tricontourf, there is how you could make a contourf plot out of it. (Example data given in the Appendix)
import pandas as pd
from matplotlib import pyplot as plt
df = pd.DataFrame(dict(x=xdata, y=ydata, z=zdata))
xcol, ycol, zcol = "x", "y", "z"
df = df.sort_values(by=[xcol, ycol])
xvals = df[xcol].unique()
yvals = df[ycol].unique()
zvals = df[zcol].values.reshape(len(xvals), len(yvals)).T
plt.contourf(xvals, yvals, zvals)
plt.show()
df
as intermediate medium.unique()
in the next step, sorted.unique()
. This is kind of the inverse of "meshgrid" operation.reshape()
method to create the needed 2d-array.zvals
will be a (N,M) 2d-array which can be fed to plt.contour.import numpy as np
import pandas as pd
xs, ys = np.linspace(-4, 4), np.linspace(-4, 4)
xgrid, ygrid = np.meshgrid(xs, ys)
xdata, ydata = np.ravel(xgrid), np.ravel(ygrid)
zdata = (
2.3 * (1 - xdata) ** 2 * np.exp(-(ydata ** 2) - (xdata + 0.9) ** 2)
- 13.3
* (ydata / 2.2 - ydata ** 3 - xdata ** 4)
* np.exp(-(ydata ** 2) - xdata ** 2)
- 0.8 * np.exp(-((ydata + 1) ** 2) - xdata ** 2)
)
Upvotes: 22
Reputation: 33
I encounter this issue frequently if I am using data that I had raveled for easier manipulation. In the raveled data a 2-D array is flattened.
The original data has x, y, and z values for every coordinate:
x = [0, 1, 2; 0, 1, 2]
y = [0, 0, 0; 1, 1, 1]
z = [0.1 , 0.2, 0.3 ; 0.2, 0.3, 0.4]
Using np.ravel() for all three arrays makes them a one-dimensional 6 element long array.
xx = np.ravel(x); yy = np.ravel(y) ; zz = np.ravel(z)
Now xx = ([0, 1, 2, 0, 1, 2]), and similarly for yy and zz.
If this is the kind of data you are working with and the data is thoroughly sampled, you can simulate a contourf plot using a scatter plot. This only works if your dataset is sampled well enough to fill in all of the space.
plt.scatter(xx,yy,c=zz,cmap=cm.Reds)
Upvotes: 2
Reputation: 302
It seems to me that you're describing a one-dimensional curve through the space rather than a surface. I say that bacause I assume x[i]
, y[i]
and z[i]
are the coordinates of a point. You cannot use these points to define a surface in an easy way, because your points only depend on one variable i
and so only describes a shape with one degree of freedom. Consider that you can connect each point in the list to the next, and that this only gives you a one dimensional chain of points. In oder to make a surface out of three arrays, you must define 9 z values, not 3.
I'm sorry that this isn't a helpful answer, but I don't have the reputation to post a comment.
Upvotes: 0
Reputation: 205
Your z
is wrong. It needs to give the values at every point of the mesh. If z
is a function of x
and y
, calculate z
at what I refer to as X_grid
below:
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return (x[:,0]**2 + x[:,1]**2)
x = np.array([1,2,3])
y = np.array([1,2,3])
xx, yy = np.meshgrid(x, y)
X_grid = np.c_[ np.ravel(xx), np.ravel(yy) ]
z = f(X_grid)
z = z.reshape(xx.shape)
plt.contour(xx, yy, z)
Upvotes: -2