Предотвращение numpy от создания многомерного массива

NumPy действительно полезно при создании массивов. Если первый аргумент для numpy.array имеет __getitem__ и __len__ они используются на основе того, что это может быть допустимая последовательность.

К сожалению, я хочу создать массив, содержащий dtype=object без NumPy, который будет «полезным».

Разбитый до минимального примера, класс хотел бы:

 import numpy as np class Test(object): def __init__(self, iterable): self.data = iterable def __getitem__(self, idx): return self.data[idx] def __len__(self): return len(self.data) def __repr__(self): return '{}({})'.format(self.__class__.__name__, self.data) 

и если «iterables» имеют разную длину, все в порядке, и я получаю именно тот результат, который хочу получить:

 >>> np.array([Test([1,2,3]), Test([3,2])], dtype=object) array([Test([1, 2, 3]), Test([3, 2])], dtype=object) 

но NumPy создает многомерный массив, если они имеют одинаковую длину:

 >>> np.array([Test([1,2,3]), Test([3,2,1])], dtype=object) array([[1, 2, 3], [3, 2, 1]], dtype=object) 

К сожалению, есть только аргумент ndmin поэтому мне было интересно, есть ли способ принудительно выполнить ndmax или каким-то образом запретить NumPy интерпретировать пользовательские классы в качестве другого измерения (без удаления __len__ или __getitem__ )?

  • Python не обнаруживает файлы .pyc
  • Как подключить удаленный отладчик к процессу Python?
  • Как удалить пакет на OSX Mavericks?
  • Как получить pandas.read_csv () для вывода типов datetime и timedelta из столбцов файла CSV?
  • Как вы делаете простой «chmod + x» изнутри python?
  • Каков наилучший способ вызова сценария Python из другого сценария Python?
  • Проверка Python на действительный адрес электронной почты?
  • Назначение кортежа Python и проверка в условных операторах
  • 2 Solutions collect form web for “Предотвращение numpy от создания многомерного массива”

    Обходной путь – это, конечно, создание массива желаемой формы, а затем копирование данных:

     In [19]: lst = [Test([1, 2, 3]), Test([3, 2, 1])] In [20]: arr = np.empty(len(lst), dtype=object) In [21]: arr[:] = lst[:] In [22]: arr Out[22]: array([Test([1, 2, 3]), Test([3, 2, 1])], dtype=object) 

    Обратите внимание, что в любом случае я не удивлюсь, если поведение numpy будет интерпретировать итерируемые объекты (что вы хотите использовать, верно?) Зависит от версии numpy. И, возможно, глючит. Или, может быть, некоторые из этих ошибок являются на самом деле функциями. Во всяком случае, я бы с осторожностью относился к поломке при изменении версии numpy.

    Наоборот, копирование в предварительно созданный массив должно быть более надежным.

    Это поведение обсуждалось несколько раз раньше (например, переопределить dict с поддержкой numpy ). np.array пытается сделать как можно больше размерного массива. Модельный пример – вложенные списки. Если он может итерации, и подсписчики равны по длине, он будет «сверлить» вниз.

    Здесь он опустился на 2 уровня, прежде чем столкнуться с списками разной длины:

     In [250]: np.array([[[1,2],[3]],[1,2]],dtype=object) Out[250]: array([[[1, 2], [3]], [1, 2]], dtype=object) In [251]: _.shape Out[251]: (2, 2) 

    Без параметра shape или ndmax он не знает, хочу ли я быть (2,) или (2,2) . Оба они будут работать с dtype.

    Это скомпилированный код, поэтому не легко увидеть, какие именно тесты он использует. Он пытается итерации по спискам и кортежам, но не по наборам или словарям.

    Самый надежный способ создания массива объектов с заданным измерением – начать с пустого и заполнить его

     In [266]: A=np.empty((2,3),object) In [267]: A.fill([[1,'one']]) In [276]: A[:]={1,2} In [277]: A[:]=[1,2] # broadcast error 

    Другой способ – начать, по крайней мере, с одного другого элемента (например, None ), а затем заменить его.

    Существует более примитивный создатель, ndarray который формируется:

     In [280]: np.ndarray((2,3),dtype=object) Out[280]: array([[None, None, None], [None, None, None]], dtype=object) 

    Но это в основном то же самое, что и np.empty (если только я не дам ему буфер).

    Это выдумки, но они не дорогие (с учетом времени).

    ================ (редактировать)

    https://github.com/numpy/numpy/issues/5933 , Enh: Object array creation function. это запрос расширения. Также https://github.com/numpy/numpy/issues/5303 the error message for accidentally irregular arrays is confusing .

    dtype=object разработчик предпочитает отдельную функцию для создания dtype=object , один с большим контролем над начальными размерами и глубиной итерации. Они могут даже усилить проверку ошибок, чтобы np.array создавал «нерегулярные» массивы.

    Такая функция может обнаруживать форму регулярного вложенного итеративного значения до заданной глубины и строить массив типов объектов, который должен быть заполнен.

     def objarray(alist, depth=1): shape=[]; l=alist for _ in range(depth): shape.append(len(l)) l = l[0] arr = np.empty(shape, dtype=object) arr[:]=alist return arr 

    С различными глубинами:

     In [528]: alist=[[Test([1,2,3])], [Test([3,2,1])]] In [529]: objarray(alist,1) Out[529]: array([[Test([1, 2, 3])], [Test([3, 2, 1])]], dtype=object) In [530]: objarray(alist,2) Out[530]: array([[Test([1, 2, 3])], [Test([3, 2, 1])]], dtype=object) In [531]: objarray(alist,3) Out[531]: array([[[1, 2, 3]], [[3, 2, 1]]], dtype=object) In [532]: objarray(alist,4) ... TypeError: object of type 'int' has no len() 
    Python - лучший язык программирования в мире.