Индексирование массива numpy по порядку с повторением - PullRequest
2 голосов
/ 16 января 2020

У меня есть массив numpy следующим образом:

arr = np.array([0.166667, 0., 0., 0.333333, 0., 0.166667, 0.166667, np.nan]

I wi sh для ранжирования выше массива в порядке убывания, так что highest value получает 1. и np.nan получает последний значение, но без увеличения ранга во время повторений значений!

Ожидание:

ranks = [2, 3, 3, 1, 3, 2, 2, 4]

i.e.
>>>>
1 0.333333
2 0.166667
2 0.166667
2 0.166667
3 0.0
3 0.0
3 0.0
4 -inf

То, что я до сих пор достиг, ниже,

Я дважды использовал np.argsort и заполнил значение np.nan с наименьшим возможным значением с плавающей запятой, но ранги увеличиваются даже с тем же значением!

# The Logic
arr = np.nan_to_num(arr, nan=float('-inf'))
ranks = list(np.argsort(np.argsort(arr)[::-1]) + 1)

# Pretty Print
sorted_ = sorted([(r, a) for a, r, in zip(arr, ranks)], key=lambda v: v[0])
for r, a in sorted_:
  print(r, a)

>>>>
1 0.333333
2 0.166667
3 0.166667
4 0.166667
5 0.0
6 0.0
7 0.0
8 -inf

Есть идеи о том, как управлять рангами без приращений?

https://repl.it/@MilindDalvi / MidnightblueUnselfishCategories

Ответы [ 5 ]

1 голос
/ 16 января 2020

Вот подход pandas с использованием DataFrame.rank настройки method="min" и na_option ='bottom':

s = pd.Series(arr).rank(method="min", na_option ='bottom', ascending=False)
u = np.sort(s.unique())
s.map(dict(zip(u, range(len(u))))).add(1).values
# array([2, 3, 3, 1, 3, 2, 2, 4], dtype=int64)
0 голосов
/ 16 января 2020

Вот один из подходов:

v = sorted(arr, reverse = 1)
for i,j in enumerate(set(v)):
    if np.isnan(j): k = i+1

print([list(set(v)).index(i)+1 if not np.isnan(i) else k for i in arr])

Вывод

[2, 3, 3, 1, 3, 2, 2, 4]
0 голосов
/ 16 января 2020

numpy.unique сортирует уникальные значения по возрастанию, поэтому использование -arr дает правильный порядок. Индекс для отмены этой операции - ваш ранг (минус один).

arr_u, inv = np.unique(-arr, return_inverse=True)
rank = inv + 1
0 голосов
/ 16 января 2020

Не обязательно лучший способ - просто еще один способ решения этой проблемы

arr = sorted(np.array([0.166667, 0., 0., 0.333333, 0., 0.166667, 0.166667, np.nan]), reverse=True)
count = 1
mydict = {}

for a in arr:
    if a not in mydict:
        mydict[a] = count
        count += 1

for i in arr:
    print(mydict[i], i)
0 голосов
/ 16 января 2020

Попробуйте что-то подобное до последнего l oop:

k = 1;
for i in (1, len(sorted_)):
  if sorted_[i][1] != sorted_[i - 1][1] then
     k = k + 1
  sorted_[i][0] = k
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...