Эффективное добавление массивов numpy с повторяющимися индексами назначения [duplicate]

Per спецификация W3C HTML5 :

^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$

Контекст:

Действительный адрес электронной почты - это строка, которая соответствует ABNF production [...].

Примечание. Это требование является преднамеренным нарушением в RFC 5322 , который определяет синтаксис адресов электронной почты, который является одновременно слишком строгий (до символа «@»), слишком неопределенный (после символа «@») и слишком слабый (позволяющий использовать комментарии, пробельные символы и кавычки в манерах, незнакомых большинству пользователей).

Следующее регулярное выражение, совместимое с JavaScript и Perl, является реализацией указанного выше определения.

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

8
задан duckworthd 28 May 2014 в 19:06
поделиться

3 ответа

Для полноты в numpy> = 1.8 вы также можете использовать метод np.add at:

In [8]: m, n = np.random.rand(2, 10)

In [9]: m_idx, n_idx = np.random.randint(10, size=(2, 20))

In [10]: m0 = m.copy()

In [11]: np.add.at(m, m_idx, n[n_idx])

In [13]: m0 += np.bincount(m_idx, weights=n[n_idx], minlength=len(m))

In [14]: np.allclose(m, m0)
Out[14]: True

In [15]: %timeit np.add.at(m, m_idx, n[n_idx])
100000 loops, best of 3: 9.49 us per loop

In [16]: %timeit np.bincount(m_idx, weights=n[n_idx], minlength=len(m))
1000000 loops, best of 3: 1.54 us per loop

. Помимо очевидного недостатка производительности, он имеет несколько преимуществ:

  1. np.bincount преобразует его веса в плавающие значения с двойной точностью, .at будет работать с вашим родным типом массива. Это делает его самым простым вариантом для решения, например. с комплексными числами.
  2. np.bincount только добавляет веса вместе, у вас есть метод at для всех ufuncs, поэтому вы можете многократно multiply или logical_and или что хотите.

Но для вашего случая использования np.bincount, вероятно, способ пойти.

11
ответ дан Jaime 25 August 2018 в 20:36
поделиться

Для наглядности давайте определим

>>> m_ind, n_ind = w.T

Затем цикл for

for i, j in zip(m_ind, n_ind):
    M[i] += N[j]

обновляет записи M[np.unique(m_ind)]. Значения, которые записываются в него, - N[n_ind], которые должны быть сгруппированы по m_ind. (Тот факт, что есть n_ind в дополнение к m_ind, фактически тангенциальен для вопроса, вы можете просто установить N = N[n_ind].) Существует, по-видимому, класс SciPy, который выполняет именно это: scipy.sparse.csr_matrix .

Пример данных:

>>> m_ind, n_ind = array([[0, 0, 1, 1], [2, 3, 0, 1]])
>>> M = np.arange(2, 6)
>>> N = np.logspace(2, 5, 4)

Результат цикла for заключается в том, что M становится [110002 1103 4 5]. Мы получаем тот же результат с csr_matrix следующим образом. Как я уже говорил ранее, n_ind не имеет значения, поэтому мы избавимся от этого.

>>> N = N[n_ind]
>>> from scipy.sparse import csr_matrix
>>> update = csr_matrix((N, m_ind, [0, len(N)])).toarray()

Конструктор CSR строит матрицу с требуемыми значениями по требуемым индексам; третья часть его аргумента представляет собой индекс сжатого столбца, что означает, что значения N[0:len(N)] имеют индексы m_ind[0:len(N)]. Дубликаты суммируются:

>>> update
array([[ 110000.,    1100.]])

Это имеет форму (1, len(np.unique(m_ind))) и может быть добавлено непосредственно:

>>> M[np.unique(m_ind)] += update.ravel()
>>> M
array([110002,   1103,      4,      5])
1
ответ дан Fred Foo 25 August 2018 в 20:36
поделиться

Используя также m_ind, n_ind = w.T, просто сделайте M += np.bincount(m_ind, weights=N[n_ind], minlength=len(M))

3
ответ дан seberg 25 August 2018 в 20:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: