Необходимое условие
Этот вопрос является продолжением этого сообщения. Итак, часть введения проблемы будет похожа на этот пост.
Проблема
Допустим, result
— это двумерный массив, а values
— это одномерный массив. values
содержит некоторые значения, связанные с каждым элементом в result
. Отображение элемента из values
в result
сохраняется в x_mapping
и y_mapping
. Позиция в result
может быть связана с разными значениями. Пара (x,y)
из x_mapping
и y_mapping
связана с results[-y,x]
. Мне нужно найти уникальное количество значений, сгруппированных по ассоциациям.
Пример для лучшего пояснения.
result
массив:
[[ 0., 0.],
[ 0., 0.],
[ 0., 0.],
[ 0., 0.]]
values
массив:
[ 1., 2., 1., 1., 5., 6., 7., 1.]
Примечание. Здесь массивы result
и values
имеют одинаковое количество элементов. Но это может быть не так. Между размерами вообще нет никакой связи.
x_mapping
и y_mapping
имеют отображения из 1D values
в 2D result
. Размеры x_mapping
, y_mapping
и values
будут одинаковыми.
x_mapping
- [0, 1, 0, 0, 0, 0, 0, 0]
y_mapping
- [0, 3, 2, 2, 0, 3, 2, 0]
Здесь 1-е значение (значения [0]), 5-е значение (значения [4]) и 8-е значение (значения [7]) имеют x как 0 и y как 0 (x_mapping [0] и y_mapping [0]) и, следовательно, связаны с результатом [0, 0]. Если мы вычислим количество различных значений из этой группы (1,5,1), в результате мы получим 2. @WarrenWeckesser Давайте посмотрим, как пара [1, 3]
(x, y) из x_mapping
и y_mapping
способствует results
. Поскольку существует только одно значение, т.е. 2, связанное с этой конкретной группой, results[-3,1]
будет иметь единицу, так как количество различных значений, связанных с этой ячейкой, равно единице.
Другой пример. Давайте вычислим значение results[-1,1]
. Из сопоставлений, поскольку с ячейкой не связано никакого значения, значение results[-1,1]
будет равно нулю.
Точно так же позиция [-2, 0]
в results
будет иметь значение 2.
Обратите внимание, что если связи вообще нет, то значение по умолчанию для result
будет равно нулю.
result
после вычисления,
[[ 2., 0.],
[ 1., 1.],
[ 2., 0.],
[ 0., 0.]]
Текущее рабочее решение
Используя ответ от @Divakar, я смог найти рабочее решение.
x_mapping = np.array([0, 1, 0, 0, 0, 0, 0, 0])
y_mapping = np.array([0, 3, 2, 2, 0, 3, 2, 0])
values = np.array([ 1., 2., 1., 1., 5., 6., 7., 1.], dtype=np.float32)
result = np.zeros([4, 2], dtype=np.float32)
m,n = result.shape
out_dtype = result.dtype
lidx = ((-y_mapping)%m)*n + x_mapping
sidx = lidx.argsort()
idx = lidx[sidx]
val = values[sidx]
m_idx = np.flatnonzero(np.r_[True,idx[:-1] != idx[1:]])
unq_ids = idx[m_idx]
r_res = np.zeros(m_idx.size, dtype=np.float32)
for i in range(0, m_idx.shape[0]):
_next = None
arr = None
if i == m_idx.shape[0]-1:
_next = val.shape[0]
else:
_next = m_idx[i+1]
_start = m_idx[i]
if _start >= _next:
arr = val[_start]
else:
arr = val[_start:_next]
r_res[i] = np.unique(arr).size
result.flat[unq_ids] = r_res
Вопрос
Теперь приведенное выше решение требует 15 мс для работы со значениями 19943. Я ищу способ вычислить результат быстрее. Есть ли более эффективный способ сделать это?
Примечание
Я использую Numpy версии 1.14.3 с Python 3.5.2.
Правки
Благодаря @WarrenWeckesser, указав, что я не объяснил, как элемент в results
связан с (x,y)
из сопоставлений. Я обновил сообщение и добавил примеры для ясности.
result[0,0]
, с остальными значениями вresult
(которые генерируются кодом, который, как вы говорите, работает). Например, в массивахx_mapping
иy_mapping
пара (x, y)[1, 3]
встречается один раз. Насколько я понимаю, это индексы столбцов и строк вresult
. Так почему жеresult[3, 1]
не равно 1? И в вычисленномresult
у вас естьresult[1, 0] = 1
иresult[1, 1] = 1
, но ни одна из пар (x, y) [0, 1] и [1, 1] не встречается в массивах отображения. - person Warren Weckesser   schedule 28.11.2018(x,y)
связана с элементами вresults
. Каждая пара(x,y)
связана сresults[-y,x]
. Я обновил сообщение и добавил примеры для ясности. Спасибо. - person tpk   schedule 28.11.2018