Сожмите ndarray вдоль оси, применив кортеж () вдоль этой оси - PullRequest
1 голос
/ 10 июня 2019

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

Предположим, у меня есть трехмерный массив, приведенный ниже, который в основном генерируется numpy.indices из двумерного массива.

    idx = array([[[0, 0, 0, 0],
                  [1, 1, 1, 1],
                  [2, 2, 2, 2]],

                 [[0, 1, 2, 3],
                  [0, 1, 2, 3],
                  [0, 1, 2, 3]]])

Я пытался использовать numpy.apply_along_axis с tuple().

numpy.apply_along_axis(tuple, 0, idx)

Это не сработало. Итак, создали фиктивную оболочку вокруг tuple() и передали эту функцию, чтобы проверить, работает ли tuple(), как ожидалось, или нет.

def dtuple(x):
    print(tuple(x))
    return tuple(x)

Вывод был:

(0, 0)
(0, 1)
(0, 2)
(0, 3)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
array([[[0, 0, 0, 0],
        [1, 1, 1, 1],
        [2, 2, 2, 2]],

       [[0, 1, 2, 3],
        [0, 1, 2, 3],
        [0, 1, 2, 3]]])

Ясно, что tuple() работает нормально, но странно, он не возвращал ndarray из tuple объектов, вместо этого он возвращал тот же ndarray. Я также попытался передать idx.astype(object) вместо idx, но это тоже не сработало. Обратите внимание, что я пытаюсь избежать цикла for здесь. Ожидаемый результат выглядит следующим образом:

array([[(0, 0), (0, 1), (0, 2), (0, 3)],
       [(1, 0), (1, 1), (1, 2), (1, 3)],
       [(2, 0), (2, 1), (2, 2), (2, 3)]], dtype=object)

1 Ответ

1 голос
/ 10 июня 2019

Давайте попробуем несколько альтернатив:

In [563]: x=np.arange(12).reshape(3,4)                                                                 
In [564]: np.apply_along_axis(lambda i:[12],1,x)                                                       
Out[564]: 
array([[12],
       [12],
       [12]])
In [565]: np.apply_along_axis(lambda i:(1,2,3),1,x)                                                    
Out[565]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])
In [566]: np.apply_along_axis(lambda i:i,1,x)                                                          
Out[566]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
In [567]: np.apply_along_axis(lambda i:i*2,1,x)                                                        
Out[567]: 
array([[ 0,  2,  4,  6],
       [ 8, 10, 12, 14],
       [16, 18, 20, 22]])

Посмотрим на документы:

out : ndarray  (Ni..., Nj..., Nk...)
    The output array. The shape of `out` is identical to the shape of
    `arr`, except along the `axis` dimension. This axis is removed, and
    replaced with new dimensions equal to the shape of the return value
    of `func1d`. So if `func1d` returns a scalar `out` will have one
    fewer dimensions than `arr`.

Независимо от того, возвращает ли функция число, список, кортеж или массив,это все еще принимает это как измерение.Тип d остается числовым.

Почему вы пытаетесь избежать петли?apply_along_axis не избегает цикла, он просто скрывает его в функции.

Вот хороший цикл:

In [578]: arr = np.empty(x.shape[0],object)                                                            
In [579]: for i,v in enumerate(x): 
     ...:     arr[i] = tuple(v.tolist()) 
     ...:                                                                                              
In [580]: arr                                                                                          
Out[580]: array([(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)], dtype=object)

====

С вашимidx, вот способ, через структурированный массив.Это немного более запутанно, чем я хотел бы, но сейчас мое время ложиться спать.

In [596]: arr = np.zeros((3,4),'i,i')                                                                  
In [597]: arr['f0']=idx[0]                                                                             
In [598]: arr['f1']=idx[1]                                                                             
In [599]: arr                                                                                          
Out[599]: 
array([[(0, 0), (0, 1), (0, 2), (0, 3)],
       [(1, 0), (1, 1), (1, 2), (1, 3)],
       [(2, 0), (2, 1), (2, 2), (2, 3)]],
      dtype=[('f0', '<i4'), ('f1', '<i4')])
In [600]: arr.tolist()                                                                                 
Out[600]: 
[[(0, 0), (0, 1), (0, 2), (0, 3)],
 [(1, 0), (1, 1), (1, 2), (1, 3)],
 [(2, 0), (2, 1), (2, 2), (2, 3)]]
In [601]: arr1=np.empty((3,4),object)                                                                  
In [602]: arr1[...] = _600                                                                             
In [603]: arr1                                                                                         
Out[603]: 
array([[(0, 0), (0, 1), (0, 2), (0, 3)],
       [(1, 0), (1, 1), (1, 2), (1, 3)],
       [(2, 0), (2, 1), (2, 2), (2, 3)]], dtype=object)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...