Numpy: Как найти наиболее частые ненулевые значения в массиве? - PullRequest
1 голос
/ 04 августа 2020

Предположим, у меня есть массив numpy формы (1,4,5),

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

И я хотел бы найти наиболее частое ненулевое значение в массиве по указанной оси c, и возвращает ноль, только если нет других ненулевых значений.

Допустим, я смотрю на ось = 2, я хотел бы получить что-то вроде [[3,2,0,2]] из этого массива (для последней строки либо 1 или 2 подойдут). Есть ли хороший способ реализовать это?

Я пробовал решение в следующем вопросе ( Link ), но я не уверен, как изменить его, чтобы исключить специфику c значение. Еще раз спасибо!

Ответы [ 2 ]

2 голосов
/ 04 августа 2020

Мы можем использовать numpy .apply_along_axis и простую функцию для решения этой проблемы. Здесь мы используем numpy .bincount для подсчета вхождений числовых c значений, а затем numpy .argmax для получения наибольшего вхождения. Если нет других значений, кроме exclude, мы возвращаем его.

Код:

def get_freq(array, exclude):
    count = np.bincount(array[array != exclude])
    if count.size == 0:
        return exclude
    else:  
        return np.argmax(count) 

np.apply_along_axis(lambda x: get_freq(x, 0), axis=2, arr=arr)

Вывод:

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

Обратите внимание, что он также будет верните exclude, если вы передадите пустой массив.

EDIT: Как заметил Эхсан, приведенное выше решение не будет работать для отрицательных значений в данном массиве. В этом случае используйте Counter из коллекций :

arr = np.array([[[ 0,  -3,  0,  3,  0],
                 [ 0,  0,  2,  3,  2],
                 [ 0,  0,  0,  0,  0],
                 [ 2,  -5,  0,  -5, 0]]])

from collections import Counter

def get_freq(array, exclude):
    count = Counter(array[array != exclude]).most_common(1)
    if not count:
        return exclude
    else:  
        return count[0][0]

Вывод:

array([[-3,  2,  0, -5]])

most_common(1) возвращает наиболее часто встречающееся значение в Counter объект как один список элементов с кортежем, в котором первый элемент является значением, а второй - его количеством вхождений. Это возвращается в виде списка, поэтому выполняется двойная индексация. Если список пуст, то most_common не обнаружил ни одного вхождения (только исключить или пусто).

0 голосов
/ 04 августа 2020

Это альтернативное решение (возможно, не такое эффективное, как предыдущее, но уникальное) -

#Gets the positions for the highest frequency numbers in axis=2
count_max_pos = np.argmax(np.sum(np.eye(5)[arr][:,:,:,1:], axis=2), axis=2)[0]+1

#gets the max values in based on the indices
k = enumerate(count_max_pos)
result = [arr[0][i] for i in k]

print(result)
[3,2,0,1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...