根据行总和在2D Numpy数组中设置值

时间:2018-11-27 10:26:01

标签: python arrays numpy

使用Numpy并以良好的性能可以做到吗?

初始2D数组:

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

如果每行的总和小于4,则将每行的最后一项设置为1:

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

将每行中的每一项与每行的总和相除,得到这个  结果:

array([[0, 0.25, 0.25, 0.25, 0.25, 0],
   [0, 0, 0.5, 0, 0, 0.5],
   [0.5, 0, 0, 0, 0, 0.5]])

3 个答案:

答案 0 :(得分:1)

您可以使用一些聪明的布尔索引在一行中进行条件赋值:

arr = np.array([[0, 1, 1, 1, 1, 0],
                    [0, 0, 1, 0, 0, 0],
                    [1, 0, 0, 0, 0, 1]])

arr[arr.sum(axis=1) < 4, -1] = 1
print(arr)

输出:

[[0 1 1 1 1 0]
 [0 0 1 0 0 1]
 [1 0 0 0 0 1]]

然后您可以像这样将每一行除以总和:

arr = arr / arr.sum(axis=1, keepdims=True)
print(arr)

输出:

[[0.   0.25 0.25 0.25 0.25 0.  ]
 [0.   0.   0.5  0.   0.   0.5 ]
 [0.5  0.   0.   0.   0.   0.5 ]]

说明

让我们将布尔索引数组arr.sum(axis=1) >= 4命名为boolixboolix看起来像:

[ True False False]

如果用arrboolix进行切片,它将返回一个数组,其中包含arr的所有行,boolix中的对应值为{{1} }。因此,True的结果是一个数组,其中包含arr[boolix]的第1行和第2行:

arr

在上面的代码中,[[0 0 1 0 0 0] [1 0 0 0 0 1]] 被切片为arr。在切片arr[boolix, -1]中添加第二个索引将使切片仅包含每行中的最后一个值(即,最后一列中的值)。因此arr[anything, -1]将返回:

arr[boolix, -1]

由于也可以将这些片分配给它们,因此将[0 1] 分配给片1可解决您的问题。

答案 1 :(得分:1)

numpy.where在这里也可以找到符合您条件的行

import numpy as np
a = np.array([[0, 1, 1, 1, 1, 0],
              [0, 0, 1, 0, 0, 0],
              [1, 0, 0, 0, 0, 1]])

a[np.sum(a,axis=1) < 4, -1] = 1
a = a/a.sum(axis=1)[:,None]

print(a)

# Output 
# [[0.   0.25 0.25 0.25 0.25 0.  ]
#  [0.   0.   0.5  0.   0.   0.5 ]
#  [0.5  0.   0.   0.   0.   0.5 ]]

PS:@tel建议后编辑:)

答案 2 :(得分:0)

我认为您需要:

x = np.array([[0, 1, 1, 1, 1, 0],
   [0, 0, 1, 0, 0, 0],
   [1, 0, 0, 0, 0, 1]])

x[:,-1][x.sum(axis=1) < 4] = 1
# array([[0, 1, 1, 1, 1, 0],
#   [0, 0, 1, 0, 0, 1],
#  [1, 0, 0, 0, 0, 1]])

print(x/x.sum(axis=1)[:,None])

输出:

array([[0.  , 0.25, 0.25, 0.25, 0.25, 0.  ],
       [0.  , 0.  , 0.5 , 0.  , 0.  , 0.5 ],
       [0.5 , 0.  , 0.  , 0.  , 0.  , 0.5 ]])