查找 table 使用 2 列来标识行

Lookup table using 2 columns to identify rows

我有一个 xy 坐标的 numpy 查找 table,其中列 0=xa、1=ya、2=xb、3=yb。

lookup=
[[0,    0,  0,      0]
[2,     0,  1.98,   -0.01]
[4,     0,  3.99,   -0.01]
[6,     0,  6.03,   -0.01]
[8,     0,  8.02,   -0.03]
[10,    0,  9.98,   -0.01]
[12,    0,  11.99,  0]
[14,    0,  13.99,  0]
[0,     1,  -0.03,  0.88]
[2,     1,  1.95,   0.86]
[4,     1,  3.97,   0.85]
[6,     1,  5.97,   0.87]
[8,     1,  7.96,   0.86]
[10,    1,  9.95,   0.92]
[12,    1,  11.95,  0.92]
[14,    1,  13.97,  0.87]]

我有一个 table 数据,其 x 和 y 位置的格式为 xa ya,我希望使用查找 table:

将其更改为 xb yb
gridloc=
[[6,    0]
 [8,    0]
 [8,    0]
 [10,   0]
 [8,    1]
 [10,   1]
 [12,   1]
 [14,   1]

所以我希望结果是这样的:

newloc=
[[6.03,   -0.01]
 [8.02,   -0.03]
 [8.02,   -0.03]
 [9.98,   -0.01]
 [7.96,   0.86]
 [9.95,   0.92]
 [11.95,  0.92]
 [13.97,  0.87]]

我试过用它来创建字典,但出现错误:

mapping = dict(zip(lookup[:,0:2], range(len(lookup))))

Traceback (most recent call last):

  File "<ipython-input-12-528fb6616ce0>", line 1, in <module>
    mapping = dict(zip(lookup[:,0:2], range(len(lookup))))

TypeError: unhashable type: 'numpy.ndarray'

有人有什么建议吗?我的 table 应该首先放在 numpy 中吗? dict是解决问题的方法吗?

首先,列表是可变的,不能用作字典键。这就是您需要将数据转换为元组的原因:

mapping = dict(zip(map(tuple, lookup[:, :2]), map(tuple, lookup[:, 2:])))#
mapping
#{(0.0, 0.0): (0.0, 0.0),
# (0.0, 1.0): (-0.029999999999999999, 0.88),
# (2.0, 0.0): (1.98, -0.01),
# (2.0, 1.0): (1.95, 0.85999999999999999),
# (4.0, 0.0): (3.9900000000000002, -0.01),
# (4.0, 1.0): (3.9700000000000002, 0.84999999999999998),
# (6.0, 0.0): (6.0300000000000002, -0.01),
# (6.0, 1.0): (5.9699999999999998, 0.87),
# (8.0, 0.0): (8.0199999999999996, -0.029999999999999999),
# (8.0, 1.0): (7.96, 0.85999999999999999),
# (10.0, 0.0): (9.9800000000000004, -0.01),
# (10.0, 1.0): (9.9499999999999993, 0.92000000000000004),
# (12.0, 0.0): (11.99, 0.0),
# (12.0, 1.0): (11.949999999999999, 0.92000000000000004),
# (14.0, 0.0): (13.99, 0.0),
# (14.0, 1.0): (13.970000000000001, 0.87)}

现在要实现您的目标,您需要将 gridloc 转换为元组列表,然后将 mapping 映射到它:

gridloc = list(map(mapping.get, map(tuple, gridloc)))
gridloc
#[(6.0300000000000002, -0.01),
# (8.0199999999999996, -0.029999999999999999),
# (8.0199999999999996, -0.029999999999999999),
# (9.9800000000000004, -0.01),
# (7.96, 0.85999999999999999),
# (9.9499999999999993, 0.92000000000000004),
# (11.949999999999999, 0.92000000000000004),
# (13.970000000000001, 0.87)]

P.S。 Floating point math is not broken.

这是一种 Numpythonic 方法:

In [89]: mask = np.logical_and(gridloc[:,0] == lookup[:,None,0], gridloc[:,1] == lookup[:,None, 1])

In [90]: ind = np.where(mask)[0]

In [91]: lookup[ind, 2:]
Out[91]: 
array([[ 6.030e+00, -1.000e-02],
       [ 8.020e+00, -3.000e-02],
       [ 8.020e+00, -3.000e-02],
       [ 9.980e+00, -1.000e-02],
       [ 7.960e+00,  8.600e-01],
       [ 9.950e+00,  9.200e-01],
       [ 1.195e+01,  9.200e-01],
       [ 1.397e+01,  8.700e-01]])

一种选择是使用 Pandas 索引功能:

import numpy as np
import pandas as pd

lookup = np.array(
    [[0,    0,  0,      0],
     [2,     0,  1.98,   -0.01],
     [4,     0,  3.99,   -0.01],
     [6,     0,  6.03,   -0.01],
     [8,     0,  8.02,   -0.03],
     [10,    0,  9.98,   -0.01],
     [12,    0,  11.99,  0],
     [14,    0,  13.99,  0],
     [0,     1,  -0.03,  0.88],
     [2,     1,  1.95,   0.86],
     [4,     1,  3.97,   0.85],
     [6,     1,  5.97,   0.87],
     [8,     1,  7.96,   0.86],
     [10,    1,  9.95,   0.92],
     [12,    1,  11.95,  0.92],
     [14,    1,  13.97,  0.87]])
gridloc = np.array(
    [[6,    0],
     [8,    0],
     [8,    0],
     [10,   0],
     [8,    1],
     [10,   1],
     [12,   1],
     [14,   1]])

idx = pd.MultiIndex.from_arrays([lookup[:, 0], lookup[:, 1]], names=('xa', 'ya'))
df = pd.DataFrame(lookup[:, 2:], columns=('xb', 'yb'), index=idx)
# This should work but is not implemented for multidimensional arrays
# newloc = df.loc[gridloc].values
# Converting to list of tuples works
newloc = df.loc[list(map(tuple, gridloc))].values  # Add .copy() if need writing
print(newloc)

输出:

[[  6.03000000e+00  -1.00000000e-02]
 [  8.02000000e+00  -3.00000000e-02]
 [  8.02000000e+00  -3.00000000e-02]
 [  9.98000000e+00  -1.00000000e-02]
 [  7.96000000e+00   8.60000000e-01]
 [  9.95000000e+00   9.20000000e-01]
 [  1.19500000e+01   9.20000000e-01]
 [  1.39700000e+01   8.70000000e-01]]