我有一个类似的数组
Nbank = np.array([[2, 3, 1],
[1, 2, 2],
[3, 2, 1],
[3, 2, 1],
[2, 3, 2],
[2, 2, 3],
[1, 1, 3],
[2, 1, 1],
[2, 2, 3],
[1, 1, 1],
[2, 1, 1],
[2, 3, 1],
[1, 2, 1]])
我想返回一个只有一列的数组。条件是返回每行中最常用的值;如果多个值的出现次数相同,只需返回其中的最大值。
我用了这个代码
most_f = np.array([np.bincount(row).argmax() for row in Nbank])
如果多个值的出现次数相同,则返回第一个项,而不是最大值。我该如何解决这个问题?
按行降序排序后,可以使用Counter。有一个most_common
会返回您想要的内容。由于它已经排序了,所以第一个元素总是最大的或最频繁的。
import numpy as np
from collections import Counter
Nbank = np.array([[2, 3, 1],
[1, 2, 2],
[3, 2, 1],
[3, 2, 1],
[2, 3, 2],
[2, 2, 3],
[1, 1, 3],
[2, 1, 1],
[2, 2, 3],
[1, 1, 1],
[2, 1, 1],
[2, 3, 1],
[1, 2, 1]])
np.array([Counter(sorted(row, reverse=True)).most_common(1)[0][0] for row in Nbank])
输出
array([3, 2, 3, 3, 2, 2, 1, 1, 2, 1, 1, 3, 1])
我相信这会解决问题。你可能会把它写成一句话,并有一些奇特的列表理解,但我认为这不值得。
most_f = []
for n in Nbank: #iterate over elements
counts = np.bincount(n) #count the number of elements of each value
most_f.append(np.argwhere(counts == np.max(counts))[-1][0]) #append the last and highest
您可以欺骗一点并反转每一行,以使np.argmax
返回与最大项目对应的最右边出现的标记:
N = np.max(arr)
>>> [N - np.argmax(np.bincount(row, minlength=N+1)[::-1]) for row in Nbank]
[3, 2, 3, 3, 2, 2, 1, 1, 2, 1, 1, 3, 1]
如果你想充分利用numpy
,你可能还想避免循环,这绝对是明智的。不幸的是,np.bincount
不支持2D阵列,但您可以手动执行:
N, M = arr.shape[0], np.max(arr)+1
bincount_2D = np.zeros(shape=(N, M), dtype=int)
advanced_indexing = np.repeat(np.arange(N), arr.shape[1]), arr.ravel()
np.add.at(bincount_2D, advanced_indexing, 1)
>>> bincount_2D
array([[0, 1, 1, 1],
[0, 1, 2, 0],
[0, 1, 1, 1],
[0, 1, 1, 1],
[0, 0, 2, 1],
[0, 0, 2, 1],
[0, 2, 0, 1],
[0, 2, 1, 0],
[0, 0, 2, 1],
[0, 3, 0, 0],
[0, 2, 1, 0],
[0, 1, 1, 1],
[0, 2, 1, 0]])
然后对所有行同时重复该过程:
>>> M -1 - np.argmax(bincount_2D[:,::-1], axis=1)
array([3, 2, 3, 3, 2, 2, 1, 1, 2, 1, 1, 3, 1], dtype=int64)