如何用现有的xyz数据制作矩阵

J.A*_*ado 3 python numpy matplotlib matrix coordinates

我想使用matplotlib.pyplot.pcolormesh绘制深度图。

我有一个xyz文件三列,即x(lat),y(lon),z(dep)。

所有列的长度相等

pcolormesh需要矩阵作为输入。因此,使用numpy.meshgrid,我可以将x和y转换为矩阵:

xx,yy = numpy.meshgrid(x_data,y_data)
Run Code Online (Sandbox Code Playgroud)

这很好用...但是,我不知道如何创建我的深度(z)数据矩阵...如何为我的z_data创建与x_data和y_data矩阵相对应的矩阵?

jed*_*rds 5

根据是否生成z,至少有两个不同的选项。

如果要生成z(例如,您知道它的公式),则非常简单(请参见method_1()下文)。

如果你只需要短短的(列表xyz)元组,它很难(见method_2()下文,也许method_3())。

常数

# min_? is minimum bound, max_? is maximum bound, 
#   dim_? is the granularity in that direction
min_x, max_x, dim_x = (-10, 10, 100)
min_y, max_y, dim_y = (-10, 10, 100)
Run Code Online (Sandbox Code Playgroud)

方法1:生成 z

# Method 1:
#   This works if you are generating z, given (x,y)
def method_1():
    x = np.linspace(min_x, max_x, dim_x)
    y = np.linspace(min_y, max_y, dim_y)

    X,Y = np.meshgrid(x,y)

    def z_function(x,y):
        return math.sqrt(x**2 + y**2)

    z = np.array([z_function(x,y) for (x,y) in zip(np.ravel(X), np.ravel(Y))])
    Z = z.reshape(X.shape)

    plt.pcolormesh(X,Y,Z)
    plt.show()
Run Code Online (Sandbox Code Playgroud)

生成以下图形:

方法_1

这相对容易,因为您可以z在任意点生成。

如果您没有该功能,则会获得固定的(x,y,z)。您可以执行以下操作。首先,我定义一个生成假数据的函数:

def gen_fake_data():
    # First we generate the (x,y,z) tuples to imitate "real" data
    # Half of this will be in the + direction, half will be in the - dir.
    xy_max_error = 0.2

    # Generate the "real" x,y vectors
    x = np.linspace(min_x, max_x, dim_x)
    y = np.linspace(min_y, max_y, dim_y)

    # Apply an error to x,y
    x_err = (np.random.rand(*x.shape) - 0.5) * xy_max_error
    y_err = (np.random.rand(*y.shape) - 0.5) * xy_max_error
    x *= (1 + x_err)
    y *= (1 + y_err)

    # Generate fake z
    rows = []
    for ix in x:
        for iy in y:
            z = math.sqrt(ix**2 + iy**2)
            rows.append([ix,iy,z])

    mat = np.array(rows)
    return mat
Run Code Online (Sandbox Code Playgroud)

在这里,返回的矩阵如下所示:

mat = [[x_0, y_0, z_0],
       [x_1, y_1, z_1],
       [x_2, y_2, z_2],
       ...
       [x_n, y_n, z_n]]
Run Code Online (Sandbox Code Playgroud)

方法2:z在常规网格上内插给定点

# Method 2:
#   This works if you have (x,y,z) tuples that you're *not* generating, and (x,y) points 
#   may not fall evenly on a grid.
def method_2():
    mat = gen_fake_data()

    x = np.linspace(min_x, max_x, dim_x)
    y = np.linspace(min_y, max_y, dim_y)

    X,Y = np.meshgrid(x, y)

    # Interpolate (x,y,z) points [mat] over a normal (x,y) grid [X,Y]
    #   Depending on your "error", you may be able to use other methods
    Z = interpolate.griddata((mat[:,0], mat[:,1]), mat[:,2], (X,Y), method='nearest')

    plt.pcolormesh(X,Y,Z)
    plt.show()
Run Code Online (Sandbox Code Playgroud)

此方法产生以下图形:

误差= 0.2 方法_2(错误率= 0.2)

误差= 0.8 method_2(err = 0.8

方法3:无插值(对采样数据的约束)

根据您(x,y,z)的设置,还有第三种选择。此选项需要两件事:

  1. x个不同的采样位置的数量等于y个不同的采样位置的数量。
  2. 对于每个可能的唯一(x,y)对,您的数据中都有一个对应的(x,y,z)。

由此得出,对的数量(x,y,z)必须等于唯一x点数量的平方(其中唯一x位置的数量等于唯一y位置的数量)。

通常,对于采样数据,这将是不正确的。但是如果是这样,您可以避免插值:

def method_3():
    mat = gen_fake_data()

    x = np.unique(mat[:,0])
    y = np.unique(mat[:,1])

    X,Y = np.meshgrid(x, y)

    # I'm fairly sure there's a more efficient way of doing this...
    def get_z(mat, x, y):
        ind = (mat[:,(0,1)] == (x,y)).all(axis=1)
        row = mat[ind,:]
        return row[0,2]

    z = np.array([get_z(mat,x,y) for (x,y) in zip(np.ravel(X), np.ravel(Y))])
    Z = z.reshape(X.shape)

    plt.pcolormesh(X,Y,Z)
    plt.xlim(min(x), max(x))
    plt.ylim(min(y), max(y))
    plt.show()
Run Code Online (Sandbox Code Playgroud)

误差= 0.2 method_3(错误= 0.2)

误差= 0.8 method_3(错误= 0.8)