Перебрать массив и применить его к функции - PullRequest
0 голосов
/ 07 февраля 2020

В python Я перебираю каждый столбец в P и 4,4 массива с функцией "q". как:

P = np.array([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 0.5, 0], [0, 0, 0.5, 0]])


def q(q_u):
    q = np.array(
        [
            [np.dot(0, 2, q_u)],
            [np.zeros((4, 1), dtype=int)],
            [np.zeros((2, 1), dtype=int)],
        ],
        dtype=object,
    )

    return q


np.apply_along_axis(q, axis=0, arr=P)

Я получаю массив (3,1,4), применяя функцию q к массиву P. Это правильно. Но как можно сохранить и затем вызвать 4 (3,1) массивы в диктонар, чтобы затем применить его к другой функции printR, которой нужен массив (3,1).

printR(60, res, q)

Следует ли добавить 4 массива в словарь для итерации с PrintR или есть другой метод?

Ответы [ 2 ]

1 голос
/ 07 февраля 2020

Исправление загадки dot в

        [np.dot(0.2, q_u)], 

приводит к ost в вашем другом вопросе.

Я все еще удивляюсь, почему вы настаиваете на использовании apply_along_axis. Это не имеет никаких преимуществ в скорости. Сравните эти временные значения:

In [36]: timeit np.apply_along_axis(q, axis=0, arr=P)                                          
141 µs ± 112 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [37]: timeit np.stack([q(P[:,i]) for i in range(P.shape[1])], axis=2)                       
72.1 µs ± 500 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [38]: timeit [q(P[:,i]) for i in range(P.shape[1])]                                         
53 µs ± 42.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Эта строка dot(0.2, q_u) просто делает 0.2*q_u, что для P может быть 0.2*P или 0.2*P.T.

Давайте изменим q чтобы опустить размеры 1, чтобы сделать более компактный дисплей:

In [49]: def q1(q_u): 
    ...:     q = np.array( 
    ...:         [ 
    ...:             np.dot(0.2, q_u), 
    ...:             np.zeros((4,), dtype=int), 
    ...:             np.zeros((2,), dtype=int), 
    ...:         ], 
    ...:         dtype=object, 
    ...:     ) 
    ...:     return q 
    ...:                                                                                       
In [50]: np.apply_along_axis(q1, axis=0, arr=P)                                                
Out[50]: 
array([[array([0.2, 0. , 0. , 0. ]), array([0. , 0.2, 0. , 0. ]),
        array([0. , 0. , 0.1, 0.1]), array([0.2, 0. , 0. , 0. ])],
       [array([0, 0, 0, 0]), array([0, 0, 0, 0]), array([0, 0, 0, 0]),
        array([0, 0, 0, 0])],
       [array([0, 0]), array([0, 0]), array([0, 0]), array([0, 0])]],
      dtype=object)
In [51]: _.shape                                                                               
Out[51]: (3, 4)

Мы можем генерировать одинаковые числа, расположенные немного по-разному с помощью:

In [52]: [0.2 * P.T, np.zeros((4,4),int), np.zeros((4,2),int)]                                 
Out[52]: 
[array([[0.2, 0. , 0. , 0. ],
        [0. , 0.2, 0. , 0. ],
        [0. , 0. , 0.1, 0.1],
        [0.2, 0. , 0. , 0. ]]), 
 array([[0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0]]), 
 array([[0, 0],
        [0, 0],
        [0, 0],
        [0, 0]])]

Вы делаете 3 2d массивы, каждый с одной строкой на столбец P.

Понимание списка, которое я рассчитал в [38], дает 4 массива размера (3,), то есть один массив на столбец P. apply_along_axis затемняет это, соединяя их в последнем измерении (как это делает мой stack с axis = 2).

In [53]: [q1(P[:,i]) for i in range(P.shape[1])]                                                                                     
Out[53]: 
[array([array([0.2, 0. , 0. , 0. ]), array([0, 0, 0, 0]), array([0, 0])],
       dtype=object),
 array([array([0. , 0.2, 0. , 0. ]), array([0, 0, 0, 0]), array([0, 0])],
       dtype=object),
 array([array([0. , 0. , 0.1, 0.1]), array([0, 0, 0, 0]), array([0, 0])],
       dtype=object),
 array([array([0.2, 0. , 0. , 0. ]), array([0, 0, 0, 0]), array([0, 0])],
       dtype=object)]

Понимание списка не только быстрое, но оно также сохраняет q выведите «intact», что облегчает переход к другой функции.

1 голос
/ 07 февраля 2020

Используйте transpose, zip для создания словаря.

Чтобы создать 4 из (1,3), просто передайте их dict

arr = np.apply_along_axis(q, axis=0, arr=P)

d = dict(zip(range(arr.size), arr.T))

Out[259]:
{0: array([[0, array([[0],
        [0],
        [0],
        [0]]),
         array([[0],
        [0]])]], dtype=object), 1: array([[0, array([[0],
        [0],
        [0],
        [0]]),
         array([[0],
        [0]])]], dtype=object), 2: array([[0, array([[0],
        [0],
        [0],
        [0]]),
         array([[0],
        [0]])]], dtype=object), 3: array([[0, array([[0],
        [0],
        [0],
        [0]]),
         array([[0],
        [0]])]], dtype=object)}

In [260]: d[0].shape
Out[260]: (1, 3)

Чтобы создать 4 из (3,1), используйте понимание слова

d = {k: v.T for k, v in zip(range(arr.size), arr.T)}

Out[269]:
{0: array([[0],
        [array([[0],
        [0],
        [0],
        [0]])],
        [array([[0],
        [0]])]], dtype=object), 1: array([[0],
        [array([[0],
        [0],
        [0],
        [0]])],
        [array([[0],
        [0]])]], dtype=object), 2: array([[0],
        [array([[0],
        [0],
        [0],
        [0]])],
        [array([[0],
        [0]])]], dtype=object), 3: array([[0],
        [array([[0],
        [0],
        [0],
        [0]])],
        [array([[0],
        [0]])]], dtype=object)}

In [270]: d[0].shape
Out[270]: (3, 1)

Примечание : я намеренно использую arr.size, чтобы позволить обрезать кортежи на молнии исключительно исходя из длины arr.T

...