【问题标题】:How to apply dictionary with array as value in numpy array如何在numpy数组中应用数组作为值的字典
【发布时间】:2018-10-03 14:21:26
【问题描述】:

我正在尝试映射这本词典

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。我怎样才能映射这个?

【问题讨论】:

  • 你能解释一下吗!!不明白你想要什么!!
  • 我想在这个 numpy 数组上应用这个字典。因此,numpy 数组的第一行 [2, 0, 2, 0, 0, 3, 0, 0, 1, 0, 0, -2, 4, -2, 0, 0, -3, -3, -5, 1, 0, 0, 0, 2] 应该是 [ [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,1,0,0], [0,0,0,0,0], [0,0,0,0,0], [1,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,0,0,0], [0,0,0,0,0], [0,0,0,0,0], [-1,-1,-1,0,0], [-1,-1,-1,0,0], [-1,-1,- 1,-1,-1], [1,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0], [0,0, 0,0,0], [1,1,0,0,0] ]

标签: python numpy dictionary


【解决方案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 倍的加速。

【讨论】:

    【解决方案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:不要隐藏内置插件。

    【讨论】:

      【解决方案3】:

      您可以简单地使用嵌套列表推导:

      [[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 作为变量名,它会覆盖 Python 内置的 dict

      【讨论】:

      • 这就是我想要的!谢谢!
      【解决方案4】:

      您可以尝试遍历 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)
      

      【讨论】:

      • 这会抛出TypeError: unhashable type: 'numpy.ndarray'
      • @rahlf23 这是因为这个答案假设target 是一个单维数组。对于二维数组,这最终会传递一个列表来查找一个有问题的字典。
      • 我现在看到@Ralf 在他的回答的后半部分澄清了这一点。
      • 你的方法给了我一个 (240,5) 的形状(使用 10 暗淡)我需要像 (10,24,5) 这样的东西
      猜你喜欢
      • 1970-01-01
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-23
      • 1970-01-01
      • 2016-01-08
      • 2021-12-16
      相关资源
      最近更新 更多