numpy: контент для индексации, индекс для контента - PullRequest
0 голосов
/ 24 апреля 2018

Мой вопрос касается содержимого массива Numpy для индексации, индексации для содержимого. Есть ли эффективный и элегантный способ?

из этого (одно измерение, миллионное значение):

a = np.array ([0,1,1,1,3,3,5,1,2,3,6,9,10,....]) 

к списку или ndarray:

output = [[0],[1,2,3,7],[8],[4,5,9],[],[6],[10],[],[],[11],[12],....]

output[0] = value 0 , result:[0]       = locatoin 0 in a 
output[1] = value 1 , result:[1,2,3,7] = location 1 ,2 ,3 , 7 in a
output[2] = value 2 , result:[8] = location 8 
output[3] = value 3 , result:[4,5,9] = location 4,5,9 
output[4] = value 4 , result:[] = location nothing
........

Ответы [ 4 ]

0 голосов
/ 24 апреля 2018

Простое решение Python - собрать значения в словаре:

In [181]: dd = {i:[] for i in range(0,11)}
In [182]: a = np.array([0,1,1,1,3,3,5,1,2,3,6,9,10]) 
In [183]: for i,v in enumerate(a.tolist()):
     ...:     dd[v].append(i)
     ...:     
In [184]: dd
Out[184]: 
{0: [0],
 1: [1, 2, 3, 7],
 2: [8],
 3: [4, 5, 9],
 4: [],
 5: [6],
 6: [10],
 7: [],
 8: [],
 9: [11],
 10: [12]}

Если вы не заботитесь о случаях [], вы можете использовать collections.defaultdictionary.

Я предлагаю tolist(), потому что итерация в списке быстрее, чем итерация в массиве. Но помогает ли этот шаг в общем времени, я не знаю. Для такого рода проблем требуются временные тесты.

Я уверен, что есть предыдущие вопросы, подобные этому; Я смутно помню, как отвечал на один вопрос за последние полгода. Но поиск займет больше времени, чем написание этого ответа.

0 голосов
/ 24 апреля 2018

Поскольку вы имеете дело с одномерными массивами *, вы можете использовать широковещательную рассылку , чтобы сравнить ваш массив с его уникальными элементами и найти желаемые позиции.

In [68]: a = np.array ([0,1,1,1,3,3,5,1,2,3,6,9,10, 10, 9, 9]) 

In [69]: arr = np.unique(a)

In [70]: x, y= np.where(arr[:,None] == a)

In [71]: inds = np.where(x[:-1] - x[1:] != 0)[0] + 1

In [72]: np.split(y, inds)
Out[72]: 
[array([0]),
 array([1, 2, 3, 7]),
 array([8]),
 array([4, 5, 9]),
 array([6]),
 array([10]),
 array([11, 14, 15]),
 array([12, 13])]

Если действительно необходимо найти пропущенные элементы, хотя неясно, какова логика ожидаемого результата, но кажется, что вы находите индексы для всех элементов от a.min() до a.max().В этом случае вы можете использовать np.arange(a.min(), a.max()) в качестве arr, а затем поставить arr[:,None] == a в маске, тогда вы можете найти индексы пропущенных предметов следующим образом:

In [115]: missed = np.where((~mask).all(1))[0]

In [116]: missed
Out[116]: array([4, 7, 8])

*Из документации : для 3-мерных массивов это, безусловно, эффективно с точки зрения строк кода, а для небольших наборов данных оно также может быть эффективным в вычислительном отношении.Однако для больших наборов данных создание большого трехмерного массива может привести к снижению производительности.Кроме того, широковещательная рассылка является мощным инструментом для написания короткого и обычно интуитивно понятного кода, который очень эффективно выполняет свои вычисления на языке C. Однако существуют случаи, когда широковещательная передача использует излишне большие объемы памяти для конкретного алгоритма.В этих случаях лучше написать внешний цикл алгоритма на Python.Это также может привести к получению более читабельного кода, поскольку алгоритмы, использующие широковещание, становятся все труднее интерпретировать по мере увеличения числа измерений в широковещании.

0 голосов
/ 24 апреля 2018

Вы можете использовать scipy.sparse примерно так:

>>> from scipy import sparse
>>>
>>> def enum_loc_per_val(a):
...     x = sparse.csr_matrix((np.ones(a.shape, dtype=np.int8), a, np.arange(a.size+1))).tocsc()
...     return np.split(x.indices, x.indptr[1:-1])
... 
>>> 
>>> enum_loc_per_val(a)
[array([0], dtype=int32), array([1, 2, 3, 7], dtype=int32), array([8], dtype=int32), array([4, 5, 9], dtype=int32), array([], dtype=int32), array([6], dtype=int32), array([10], dtype=int32), array([], dtype=int32), array([], dtype=int32), array([11], dtype=int32), array([12], dtype=int32)]
0 голосов
/ 24 апреля 2018

Я не могу думать о решении без цикла полностью, но решение, которое будет работать, включает использование функции where.Я проверил его в списке случайных целых чисел, и это довольно быстро.

import numpy as np

a = np.array([0,1,1,1,3,3,5,1,2,3,6,9,10]) 

output = [np.where(a == x)[0] if x in a else [] for x in range(a.min(), a.max())]

И вот вы получаете output=

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