Создание трехмерного numpy.ndarray без фиксированного второго измерения - PullRequest
0 голосов
/ 07 апреля 2019

Иногда данные, такие как речевые данные, имеют известное количество наблюдений (n), неизвестную продолжительность и известное количество измерений (k).

В двумерном случае в NumPy ясно, как данные с известным числом наблюдений (n) и неизвестной продолжительностью представлены с помощью массива формы (n, ). Например:

import numpy as np

x = np.array([ [ 1, 2 ],
               [ 1, 2, 3 ]
             ])

print(x.shape) ### Returns: (2, )

Есть ли эквивалент для трехмерного случая в NumPy, где мы могли бы иметь ndarray формы (n, , k)? Лучшая альтернатива, которую я могу придумать, это иметь 2D ndarray формы (n, ), и каждый элемент также должен быть 2D с (транспонированной) формой (k, ). Например,

import numpy as np

x = np.array([ [ [1,2], [1,2] ],
               [ [1,2], [1,2], [1,2] ]
             ])

print(x.shape) ### Returns: (2, ); Desired: (2, , 2)

В идеале, решение могло бы сообщить нам свойства размерности ndarray без необходимости рекурсивного вызова (возможно, с альтернативой shape?).

Ответы [ 2 ]

2 голосов
/ 07 апреля 2019

Вы, кажется, неправильно поняли, что означает форма (2,). Это не значит (2, <unknown>); запятая не является разделителем между 2 и неким пустым измерением. (2,) - это синтаксис Python для одноэлементного кортежа, один элемент которого равен 2. Python использует этот синтаксис, потому что (2) будет означать целое число 2, а не кортеж.

Вы не создаете двумерный массив со вторым измерением произвольной длины. Вы создаете одномерный массив объекта dtype. Его элементы - это обычные списки Python. Подобный массив несовместим практически со всеми полезными функциями в NumPy.

Невозможно создать массивы NumPy с размерами переменной длины, будь то в 2D-случае, который, по вашему мнению, работал, или в 3D-случае, когда вы пытаетесь заставить работать.

0 голосов
/ 07 апреля 2019

Просто чтобы рассмотреть 1d случай:

In [33]: x = np.array([[1,2],[1,2,3]])                                          
In [34]: x.shape                                                                
Out[34]: (2,)
In [35]: x                                                                      
Out[35]: array([list([1, 2]), list([1, 2, 3])], dtype=object)

В результате получается массив из 2 элементов списков, где, как мы начали со списка списков.Не большая разница.

Но учтите, что если списки имеют одинаковый размер, np.array создает числовой двумерный массив:

In [36]: x = np.array([[1,2,4],[1,2,3]])                                        
In [37]: x                                                                      
Out[37]: 
array([[1, 2, 4],
       [1, 2, 3]])

Так что не рассчитывайте на поведение, которое мы видим в [33].

Я мог бы создать массив двумерных объектов:

In [59]: x = np.empty((2,2),object)                                             
In [60]: x                                                                      
Out[60]: 
array([[None, None],                  # in this case filled with None
       [None, None]], dtype=object)

Я могу назначить каждому элементу объект другого типа и размера:

In [61]: x[0,0] = np.arange(3)                                                  
In [62]: x[0,0] = [1,2,3]                                                       
In [63]: x[1,0] = 'abc'                                                         
In [64]: x[1,1] = np.arange(6).reshape(2,3)                                     
In [65]: x                                                                      
Out[65]: 
array([[list([1, 2, 3]), None],
       ['abc', array([[0, 1, 2],
       [3, 4, 5]])]], dtype=object)

Этовсе еще 2d.Для большинства целей это как список или список списков, содержащих объекты.Буфер данных на самом деле имеет указатели на объекты, хранящиеся где-то еще в памяти (как в буфере списка).

На самом деле не существует такого понятия, как трехмерный массив с переменной last измерением.В лучшем случае мы можем получить 2d массив, который содержит списки или массивы различных размеров.


Создайте список из 2 2d массивов:

In [69]: alist = [np.arange(6).reshape(2,3), np.arange(4.).reshape(2,2)]        
In [70]: alist                                                                  
Out[70]: 
[array([[0, 1, 2],
        [3, 4, 5]]), array([[0., 1.],
        [2., 3.]])]

В этом случае, передав егоnp.array выдает ошибку: в [71]: np.array (alist)
--------------------------------------------------------------------------- ValueError: не удалосьшироковещательный входной массив из shape (2,3) в shape (2)

Мы могли бы заполнить массив объектов элементами из этого списка:

In [72]: x = np.empty((4,),object)                                              
In [73]: x[0]=alist[0][0]                                                       
In [74]: x[1]=alist[0][1]                                                       
In [75]: x[2]=alist[1][0]                                                       
In [76]: x[3]=alist[1][1]                                                       
In [77]: x                                                                      
Out[77]: 
array([array([0, 1, 2]), array([3, 4, 5]), array([0., 1.]),
       array([2., 3.])], dtype=object)

и изменить его на 2d

In [78]: x.reshape(2,2)                                                         
Out[78]: 
array([[array([0, 1, 2]), array([3, 4, 5])],
       [array([0., 1.]), array([2., 3.])]], dtype=object)

Результатом является 2d массив, содержащий 1d массивы.Чтобы получить формы элементов, я должен сделать что-то вроде:

In [87]: np.frompyfunc(lambda i:i.shape, 1,1)(Out[78])                          
Out[87]: 
array([[(3,), (3,)],
       [(2,), (2,)]], dtype=object)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...