Help us understand the problem. What is going on with this article?

【Python】matplotlib の「TypeError: Input z must be a 2D array.」でお困りの方へ【3次元プロット】

More than 1 year has passed since last update.

「x, y, z 座標を適当に Matplotlib の関数に渡したらエラー吐いた」

誰もが通る道です。
以下のようにしてデータを変換しましょう。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.interpolate import griddata

# x, y, z をそれぞれ1次元配列やリストに格納してしまった!
x = []
y = []
z = []
for i in range(-10, 10):
    for j in range(-10, 10):
        x.append(j)
        y.append(i)
        z.append(i ** 2 + j ** 2)

# そのままプロットしようとしてエラー!
# plt.contourf(x, y, z)  # --> TypeError: Input z must be a 2D array.

# そういうときは、scipy.interpolate.griddata() でサンプリングしなおしましょう。
x_new, y_new = np.meshgrid(np.unique(x), np.unique(y))
z_new = griddata((x, y), z, (x_new, y_new))

# これでちゃんと描画できます
ax = Axes3D(plt.figure())
ax.plot_surface(x_new, y_new, z_new)
plt.show()

index.png

x, y, z をそれぞれ2次元配列で用意できたら

等高線

plt.contour(x, y, z)
plt.colorbar()

等高線を塗りつぶす

plt.contourf(x, y, z)
plt.colorbar()

勾配

dx = np.c_[np.gradient(x)]
dy = np.c_[np.gradient(y)]
dz = np.c_[np.gradient(z)]
dz_dx, dz_dy = np.linalg.solve(np.c_[[dx, dy]].T, dz.T).T

plt.contour(x, y, z)
plt.quiver(x, y, dz_dx, dz_dy)

plt.contour(x, y, z)
plt.streamplot(x, y, dz_dx, dz_dy)

補足: 2変数関数をプロットするときに2次元配列が3つ必要な理由

例えば、放物線の方程式 $y = x^2$ をプロットするとき、x 座標と y 座標を1次元配列で用意しますよね?
実はこれ、曲線上の点 $(x, y)$ を、次式のように配列の添字 i媒介変数表示していることに相当します。

$$
\begin{cases}
x(i) = i \\
y(i) = i^2
\end{cases}
$$

import numpy as np
import matplotlib.pyplot as plt

x = np.empty([10])
y = np.empty([10])

for i in range(10):
    x[i] = i
    y[i] = i ** 2

plt.plot(x, y)
plt.show()

では、空間曲面を描画するときはどうするかというと、点 $(x, y, z)$ を2つの媒介変数 $i$ と $j$ で表現します。x, y, z をそれぞれ2次元配列で渡すのは、これが理由です。

$$
\begin{cases}
x(i, j) = j \\
y(i, j) = i \\
z(i, j) = i^2 + j^2
\end{cases}
$$

import numpy as np
import matplotlib.pyplot as plt

x = np.empty([10, 10])
y = np.empty([10, 10])
z = np.empty([10, 10])

for i in range(10):
    for j in range(10):
        x[i, j] = j
        y[i, j] = i
        z[i, j] = i ** 2 + j ** 2

plt.contourf(x, y, z)
plt.colorbar()
plt.show()

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away