【问题标题】:Correctly Interpolate 4D Data (on Grid) using Python使用 Python 正确插入 4D 数据(在网格上)
【发布时间】:2022-01-03 08:08:33
【问题描述】:

目标

我在特定的 3D 坐标 x y z 处给出了值 v。数据存储为 pandas 数据框:

          x      y       z         v
0     -68.5  68.50  -10.00  0.297845
1     -68.5 -23.29   61.10  0.148683
2     -68.5 -23.29   63.47  0.142325
3     -68.5 -23.29   65.84  0.135908
4     -68.5 -23.29   68.21  0.129365
    ...    ...     ...       ...
91804  68.5  23.29  151.16  0.118460
91805  68.5  23.29  153.53  0.119462
91806  68.5  23.29  155.90  0.120386
91807  68.5  23.29  139.31  0.112257
91808  68.5 -68.50  227.00  0.127948

我想在不属于数据框的新坐标处找到值,因此我正在研究如何有效地插入数据。

我做了什么:

由于坐标在网格上,我可以使用interpn

import numpy as np
from scipy.interpolate import interpn

# Extract the list of coordinates (I know that they are on a grid)
xs = np.array(df["x"].to_list())
ys = np.array(df["y"].to_list())
zs = np.array(df["z"].to_list())
# Extract the associated values
vs = np.array(df["v"].to_list())

重塑数据以适应 scipy 函数:

points = (np.unique(xs), np.unique(ys), np.unique(zs))
values= vs.reshape(len(np.unique(xs)), len(np.unique(ys)), len(np.unique(zs)))

为了测试插值,如果我输入与原始点相同的点,我想看看是否得到相同的值:

request = (xs,ys,zs)
output = interpn(points, values, request)

... 但是

我在想,我做错了什么??

其他:

数据集

请在此处找到完整的数据集:https://filebin.net/u10lrw956enqhg5i

可视化

from mayavi import mlab
# Create figure
fig = mlab.figure(1, fgcolor=(0, 0, 0), bgcolor=(0, 0, 0))

        
mlab.points3d(xs,ys,zs,output)
mlab.view(azimuth=270, elevation=90, roll=180, figure=fig)

# View plot
mlab.show()

【问题讨论】:

  • 我根据您显示的数据的 sn-p 质疑您重塑 values 的有效性。尝试使用 np.uniquereturn_inverse 参数放置在网格上
  • @MadPhysicist 非常好。我也怀疑这一点,但现在,我不确定如何检查有效性或修复它。你有什么建议吗?
  • @jlandercy。这里太笼统了。网格上的插值在可用时要简单得多,而且可用。

标签: python numpy scipy interpolation


【解决方案1】:

我强烈怀疑您的数据在网格上时没有排序,以便对值进行简单的重塑。您有两种可用的解决方案,都涉及以不同方式重新排序数据。

解决方案 1

由于您已经使用np.unique 来提取网格,您可以使用return_inverse 参数获得vs 的正确顺序:

px, ix = np.unique(xs, return_inverse=True)
py, iy = np.unique(ys, return_inverse=True)
pz, iz = np.unique(zs, return_inverse=True)

points = (px, py, pz)

values = np.empty_like(vs, shape=(px.size, py.size, pz.size))
values[ix, iy, iz] = vs

return_inverse 有点神奇,主要是因为它非常违反直觉。在这种情况下,对于值的每个元素,它会告诉您它对应于哪个唯一的、已排序的总位置。

顺便说一句,如果您缺少网格元素,您可能需要将np.empty_like(vs, shape=(px.size, py.size, pz.size)) 替换为np.zeros_like(vs, shape=(px.size, py.size, pz.size))np.empty_like(vs, np.nan, shape=(px.size, py.size, pz.size))。在后一种情况下,您可以先在网格中插入nans。

解决方案 2

更明显的解决方案是重新排列索引,以便您可以按照您尝试的方式重塑 vs。仅当您确定没有丢失的网格元素时,这才有效。最简单的方法是对整个数据框进行排序,因为 pandas 方法比 np.lexsort (IMO) 更不烦人:

df.sort_values(['x', 'y', 'z'], inplace=True, ignore_index=True)

当你提取时,高效地做:

xs, ys, zs, vs = df.to_numpy().T

由于所有内容都已排序,您不再需要np.unique 来识别网格。唯一 x 值的数量为:

nx = np.count_nonzero(np.diff(xs)) + 1

唯一值是:

bx = xs.size // nx
ux = xs[::bx]

y 值在每个 bx 元素中经历一个完整的循环,所以

ny = np.count_nonzero(np.diff(ys[:bx])) + 1
by = bx // ny
uy = ys[:bx:by]

对于z (bz == 1):

nz = by
uz = zs[:nz]

现在你可以构造你的原始数组了:

points = (ux, uy, uz)
values = vs.reshape(nx, ny, nz)

【讨论】:

  • 非常感谢您的回答!我已经尝试过了,但出现以下错误:TypeError: argument for empty() given by name ('shape') and position (position 0)
  • @henry。如果忘记在我的匆忙中附加_like。现已修复
  • 哇,完美运行!非常感谢你的帮助!!我将不得不阅读神奇的“return_inverse”选项以及“np.empty_like”函数。
  • @henry。我添加了一个更新。顺便说一句,df['x'].to_numpy()np.array(list(df['x'])) 好得多。当你发现自己在 numpy 或 pandas 中使用列表操作(包括推导式)时,你可能做错了。
  • 哇,非常感谢您的更新!在重塑之前如何对数据框中的值进行排序非常好。 np.count_nonzero(np.diff(...)) 方法是否比 np.unique 更快?另外,感谢您指出“.to_numpy()”方法。太方便了,我不知道。
猜你喜欢
  • 2012-12-16
  • 2020-12-20
  • 1970-01-01
  • 2018-06-02
  • 2017-12-25
  • 1970-01-01
  • 2018-07-13
  • 2019-09-15
  • 1970-01-01
相关资源
最近更新 更多