Заменить повторяющиеся элементы в массиве Numpy на основе диапазона - PullRequest
3 голосов
/ 25 апреля 2019

У меня есть 1d массив numy arr, как показано ниже:

arr = np.array([9, 7, 0, 4, 7, 4, 2, 2, 3, 7])

Для дублирующих элементов я хочу произвольно выбрать любой из индексов, содержащих тот же элемент, и заменить его отсутствующим значениеммежду 0 и arr.shape[0].

например, в данном массиве 7 присутствует в индексах 1, 4 и 9. Следовательно, я хочу случайным образом выбрать индекс между 1, 4 и 9 и установитьего значение путем случайного выбора некоторого элемента, такого как 8, который отсутствует в массиве.В конце концов, arr должен содержать arr.shape[0] уникальных элементов, лежащих между 0 и arr.shape[0] - 1 (оба включительно)

Как я могу сделать это эффективно, используя Numpy (возможно, без необходимости использования какого-либо явного цикла)?

Ответы [ 2 ]

3 голосов
/ 25 апреля 2019

Вот один на основе np.isin -

def create_uniques(arr):
    # Get unique ones and the respective counts
    unq,c = np.unique(arr,return_counts=1)

    # Get mask of matches from the arr against the ones that have 
    # respective counts > 1, i.e. the ones with duplicates
    m = np.isin(arr,unq[c>1])

    # Get the ones that are absent in original array and shuffle it
    newvals = np.setdiff1d(np.arange(len(arr)),arr[~m])
    np.random.shuffle(newvals)

    # Assign the shuffled values into the duplicate places to get final o/p
    arr[m] = newvals
    return ar

Образцы прогонов -

In [53]: arr = np.array([9, 7, 0, 4, 7, 4, 2, 2, 3, 7])

In [54]: create_uniques(arr)
Out[54]: array([9, 7, 0, 1, 6, 4, 8, 2, 3, 5])

In [55]: arr = np.array([9, 7, 0, 4, 7, 4, 2, 2, 3, 7])

In [56]: create_uniques(arr)
Out[56]: array([9, 4, 0, 5, 6, 2, 7, 1, 3, 8])

In [57]: arr = np.array([9, 7, 0, 4, 7, 4, 2, 2, 3, 7])

In [58]: create_uniques(arr)
Out[58]: array([9, 4, 0, 1, 7, 2, 6, 8, 3, 5])
2 голосов
/ 26 апреля 2019

Расширение ответа Дивакара (и у меня практически нет опыта работы с Python, так что это, вероятно, очень обходной и непитонный способ сделать это, но):

import numpy as np
def create_uniques(arr):
    np.random.seed()
    indices = []
    for i, x in enumerate(arr):
        indices.append([arr[i], [j for j, y in enumerate(arr) if y == arr[i]]])
        indices[i].append(np.random.choice(indices[i][1]))
        indices[i][1].remove(indices[i][2])
    sidx = arr.argsort()
    b = arr[sidx]
    new_vals = np.setdiff1d(np.arange(len(arr)),arr)
    arr[sidx[1:][b[:-1] == b[1:]]] = new_vals
    for i,x in enumerate(arr):
        if x == indices[i][0] and i != indices[i][2]:
            arr[i] = arr[indices[i][2]]
            arr[indices[i][2]] = x
    return arr

Пример:

arr = np.array([9, 7, 0, 4, 7, 4, 2, 2, 3, 7])
print(arr)
print(create_uniques(arr))
arr = np.array([9, 7, 0, 4, 7, 4, 2, 2, 3, 7])
print(create_uniques(arr))
arr = np.array([9, 7, 0, 4, 7, 4, 2, 2, 3, 7])
print(create_uniques(arr))
arr = np.array([9, 7, 0, 4, 7, 4, 2, 2, 3, 7])
print(create_uniques(arr))

Выходы:

[9 7 0 4 7 4 2 2 3 7]
[9 7 0 4 6 5 2 1 3 8]
[9 8 0 4 6 5 1 2 3 7]
[9 8 0 4 6 5 2 1 3 7]
[9 7 0 5 6 4 2 1 3 8]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...