Выражение цепного неравенства для каждой комбинации элементов нескольких массивов в сжатой и масштабируемой форме - PullRequest
0 голосов
/ 05 мая 2019

У меня есть три одномерных массива a, b, c разных размеров, и я хотел бы вычислить цепное неравенство x < y < z для каждой комбинации x in a, y in b, z in c.Например:

import numpy as np

a = np.random.randint(100, size=100)
b = np.random.randint(100, size=200)
c = np.random.randint(100, size=300)

expected = np.empty(shape=(a.size, b.size, c.size), dtype=bool)
for i, x in enumerate(a):
    for j, y in enumerate(b):
        for k, z in enumerate(c):
            expected[i, j, k] = x < y < z

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

result1 = (a[:, None] < b)[:, :, None] & (b[:, None] < c)[None, :, :]
result2 = (a[:, None, None] < b[:, None]) & (b[None, :, None] < c[None, :])

Оба требуют большого изменения формы и вставки дополнительных измерений и не очень очевидны или выразительны.Я чувствую, что должен быть более краткий способ добиться этого, я изучал np.ufunc.outer, но я не мог понять, как использовать его для этой цели, так как при выполнении &два операнда должны иметь общую ось.

Масштабирование до произвольного числа массивов: В качестве дополнительного вопроса я хотел бы спросить, существует ли краткий способ масштабирования вышеуказанной операции до произвольнойколичество одномерных массивов, например a < b < c < d < ... < g для каждой комбинации элементов, например, с учетом списка arrays.

1 Ответ

2 голосов
/ 05 мая 2019

np.ix_ здесь удобно:

A,B,C = np.ix_(a,b,c)
(A<B)&(B<C)

произвольное количество массивов:

l = [np.random.randint(10*i, size=i) for i in range(2,6)]
L = np.ix_(*l)
np.bitwise_and.reduce(list(map(np.less, L, L[1:])))

или используя functools (немного быстрее)

import functools as ft
ft.reduce(np.bitwise_and, map(np.less, L, L[1:]))
...