如何将字典与数组作为numpy数组中的值应用

时间:2018-10-03 14:21:26

标签: python numpy dictionary

我正在尝试映射这本词典

dict = {
5: np.array([1,1,1,1,1], dtype='int'),
4: np.array([1,1,1,1,0], dtype='int'),
3: np.array([1,1,1,0,0], dtype='int'),
2: np.array([1,1,0,0,0], dtype='int'),
1: np.array([1,0,0,0,0], dtype='int'),
0: np.array([0,0,0,0,0], dtype='int'),
-1: np.array([-1,0,0,0,0], dtype='int'),
-2: np.array([-1,-1,0,0,0], dtype='int'),
-3: np.array([-1,-1,-1,0,0], dtype='int'),
-4: np.array([-1,-1,-1,-1,0], dtype='int'),
-5: np.array([-1,-1,-1,-1,-1], dtype='int')}

在这个numpy数组中

target
array([[ 2,  0,  2,  0,  0,  3,  0,  0,  1,  0,  0, -2,  4, -2,  0,  0,
        -3, -3, -5,  1,  0,  0,  0,  2],
       [ 4,  4,  3,  2,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,
         1, -1, -2, -1, -2, -2, -3, -4],...])

numpy数组上的元素是int32。我该如何映射?

4 个答案:

答案 0 :(得分:2)

您可以简单地使用嵌套列表理解:

[[mydict[j] for j in i] for i in target]

这将产生:

[[array([1, 1, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([1, 1, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([1, 1, 1, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([1, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([-1, -1,  0,  0,  0]), array([1, 1, 1, 1, 0]), array([-1, -1,  0,  0,  0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([-1, -1, -1,  0,  0]), array([-1, -1, -1,  0,  0]), array([-1, -1, -1, -1, -1]), array([1, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([1, 1, 0, 0, 0])], [array([1, 1, 1, 1, 0]), array([1, 1, 1, 1, 0]), array([1, 1, 1, 0, 0]), array([1, 1, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([1, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([0, 0, 0, 0, 0]), array([1, 0, 0, 0, 0]), array([-1,  0,  0,  0,  0]), array([-1, -1,  0,  0,  0]), array([-1,  0,  0,  0,  0]), array([-1, -1,  0,  0,  0]), array([-1, -1,  0,  0,  0]), array([-1, -1, -1,  0,  0]), array([-1, -1, -1, -1,  0])]]

此外,避免使用dict作为变量名,它会覆盖dict内置的Python。

答案 1 :(得分:2)

您可以使用列表推导并向np.array供稿:

res = np.array([list(map(d.__getitem__, row)) for row in target])

array([[[ 1,  1,  0,  0,  0],
        [ 0,  0,  0,  0,  0],
        [ 1,  1,  0,  0,  0],
        ...
        [ 0,  0,  0,  0,  0],
        [ 0,  0,  0,  0,  0],
        [ 1,  1,  0,  0,  0]],

       [[ 1,  1,  1,  1,  0],
        [ 1,  1,  1,  1,  0],
        [ 1,  1,  1,  0,  0],
        ...
        [-1, -1,  0,  0,  0],
        [-1, -1, -1,  0,  0],
        [-1, -1, -1, -1,  0]]])

请注意,字典已重命名为d:请勿隐藏内置字典。

答案 2 :(得分:1)

您可以尝试遍历target数组并创建一个具有所需值的新列表,以后可以根据需要将其转换为数组。

类似这样的东西:

new_target = []
for e in target:
    new_target.append(the_dict[e])

new_target = np.array(new_target)

编辑:如果您需要的尺寸大于1,则可以选择第二个循环。

import numpy as np

my_dict = {
     5: np.array([ 1, 1, 1, 1, 1], dtype='int'),
     4: np.array([ 1, 1, 1, 1, 0], dtype='int'),
     3: np.array([ 1, 1, 1, 0, 0], dtype='int'),
     2: np.array([ 1, 1, 0, 0, 0], dtype='int'),
     1: np.array([ 1, 0, 0, 0, 0], dtype='int'),
     0: np.array([ 0, 0, 0, 0, 0], dtype='int'),
    -1: np.array([-1, 0, 0, 0, 0], dtype='int'),
    -2: np.array([-1,-1, 0, 0, 0], dtype='int'),
    -3: np.array([-1,-1,-1, 0, 0], dtype='int'),
    -4: np.array([-1,-1,-1,-1, 0], dtype='int'),
    -5: np.array([-1,-1,-1,-1,-1], dtype='int'),
}

target = np.array([
    [ 2,  0,  2,  0,  0,  3,  0,  0,  1,  0,
      0, -2,  4, -2,  0,  0, -3, -3, -5,  1,
      0,  0,  0,  2],
    [ 4,  4,  3,  2,  0,  0,  0,  1,  0,  0,
      0,  0,  0,  0,  0,  0,  1, -1, -2, -1,
     -2, -2, -3, -4],
])

new_target = []
for num_list in target:
    sub_new_target = []
    print(num_list)
    for n in num_list:
        sub_new_target.append(my_dict[n])
    new_target.append(sub_new_target)

new_target = np.array(new_target)

print(target.shape)
print(target)
print(new_target.shape)
print(new_target)

答案 3 :(得分:1)

由于字典中的键是连续的,因此我建议在此处仅使用一个数组以提高性能,因此创建这种数组的模式非常简单:

mapper = np.stack([i[1] for i in sorted(d.items())])

array([[-1, -1, -1, -1, -1],
       [-1, -1, -1, -1,  0],
       [-1, -1, -1,  0,  0],
       [-1, -1,  0,  0,  0],
       [-1,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0],
       [ 1,  0,  0,  0,  0],
       [ 1,  1,  0,  0,  0],
       [ 1,  1,  1,  0,  0],
       [ 1,  1,  1,  1,  0],
       [ 1,  1,  1,  1,  1]])

现在,您只需要稍微更新一下索引即可。此处的总体思路是,当前在字典中具有与值匹配的键时,现在应该在映射器数组中具有与行索引匹配的值。与使用大型数组时,使用字典相比,这将是一个比使用字典更高效的选择:

对于您当前的数组,这涉及将每个值简单地增加5,现在您已进行矢量化索引:

mapper[target+5]

array([[[ 1.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  0.],
        [ 1.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  0.],
        ...
        [ 0.,  0.,  0.,  0.,  0.],
        [ 1.,  1.,  0.,  0.,  0.]],

       [[ 1.,  1.,  1.,  1.,  0.],
        [ 1.,  1.,  1.,  1.,  0.],
        [ 1.,  1.,  1.,  0.,  0.],
        [ 1.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  0.],
        ...
        [-1., -1.,  0.,  0.,  0.],
        [-1.,  0.,  0.,  0.,  0.]]])

时间

big_target = np.repeat(target, 10000, axis=0)

In [307]: %%timeit
 ...: mapper = np.stack([i[1] for i in sorted(d.items())])
 ...: mapper[big_target+5]
 ...:
10.5 ms ± 54.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [309]: %%timeit
     ...: np.array([list(map(d.__getitem__, row)) for row in big_target])
     ...:
368 ms ± 1.31 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [311]: %timeit np.array([[d[j] for j in i] for i in big_target])
361 ms ± 4.35 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

即使从字典中创建数组所需的开销很小,我们也希望将(20000, 24)形状数组的速度提高35倍。