Есть ли способ ускорить этот цикл Python?

#python #numpy

#python #numpy

Вопрос:

У меня есть 2-D np-массив, количество столбцов в котором в 100 раз больше, чем количество строк. Например, если количество строк равно 1000, количество столбцов равно 100 000, а все значения являются целыми числами. Моя цель — вернуть 1000 уникальных целых чисел для каждого из 1000 индексов строк. Не все значения в столбце уникальны (могут быть дубликаты), и поэтому мне приходится выполнять поиск по всем значениям в каждой строке, чтобы выбрать первое целочисленное значение в строке, которое еще не было выбрано в предыдущей операции. У меня есть этот воспроизводимый цикл, который отлично работает для меньших num_rows около ~ 1000. Но когда дело доходит до работы с более чем 10 000 строк, это мучительно медленно. Есть ли более эффективный способ справиться с этим?

 import numpy as np
maxval = 5000
matrix = np.random.randint(maxval,size=(maxval, maxval*100))
neighbours = maxval - 1
indices = [] #this array will contain the outputs after the loop gets completed
for e in matrix:
    i = 0
    while i < neighbours:
        if e[i] in indices:
            i  = 1
        else:
            indices.append(e[i])
            break 
  

Комментарии:

1. Быстрое исправление, которое ускорит работу вашего кода, используйте a set для индексов, по крайней мере, для searching ( if e[i] in indices )

2. Что делать, если количество уникальных элементов в строке превышает 1000? Кроме того, если это меньше 1000, то у вас будет переменное количество уникальных элементов в строке. Каким должен быть формат вывода?

Ответ №1:

Не простой способ, но если row имеет 100 000 элементов, то

 import random

random.sample(set(row), 1000)
  

Это случайная выборка из 1000 уникальных элементов из него.

Примечания:

  • Если число встречается намного чаще, чем другое, у них все равно есть те же шансы быть выбранными
  • Если количество уникальных значений меньше 1000, это вызывает ValueError
  • Может существовать эквивалент numpy обоих, я не знаю

Ответ №2:

Вы можете использовать a set вместо списка для поиска:

 import numpy as np
maxval = 50
matrix = np.random.randint(maxval,size=(maxval, maxval*100))
neighbours = maxval - 1
indices = set() #this array will contain the outputs after the loop gets completed
for e in matrix:
    i = 0
    while i < neighbours:
        if e[i] in indices:
            i  = 1
        else:
            indices.add(e[i])
            break 
  

Здесь у вас есть живой пример

Ответ №3:

Использование словарей будет намного быстрее, но я не знаю, достаточно ли:

 from collections import OrderedDict

indx = OrderedDict()

for e in matrix:
    i = 0
    while i < neighbours:
        v = e[i]
        if indx.get(v) is None:
            indx[v] = True
            break
        i  = 1

results = list(indx.keys())