ndarray
создается с буфером данных фиксированного размера - достаточно большим, чтобы вместить байты, представляющие элементы.
arr.nbytes == arr.itemsize * arr.size
arr.resize
может изменить массив на месте.Но прочитайте его документы, чтобы увидеть ограничения, особенно в отношении владения собственными данными.Это одна из немногих операций на месте, и она редко используется.
В отличие от этого, список Python хранит указатели объектов в буфере.Буфер имеет некоторую комнату роста, позволяющую эффективно append
.Нужно просто добавить новый указатель на буфер.Когда буфер заполняется, он выделяет новый больший буфер и копирует указатели.
Для массива 1d буферы для ndarray
и list
будут аналогичными, по крайней мере, для 4 или 8 байтов числовых dtypes,Но для многомерных массивов буфер данных может быть очень большим (произведение всех измерений), в то время как верхний буфер эквивалентного вложенного массива просто содержит указатели на внешний слой списков («строки»).
Массивы dtype объекта хранят указатели как список, но буфер данных по-прежнему имеет фиксированный размер (без пространства для роста).Производительность лежит между числовыми массивами и списками.
Я могу представить, как написать добавление на месте, использующее метод resize
, с последующим копированием новых значений в 0 заливок.
In [96]: arr = np.array([[1,3],[2,7]])
In [97]: arr.resize(3,2)
In [98]: arr
Out[98]:
array([[1, 3],
[2, 7],
[0, 0]])
In [99]: arr[-1,:] = 10,11
In [100]: arr
Out[100]:
array([[ 1, 3],
[ 2, 7],
[10, 11]])
Но обратите внимание, что происходит со значениями, когда мы изменяем размер внутренней оси:
In [101]: arr = np.array([[1,3],[2,7]])
In [102]: arr.resize(2,3)
In [103]: arr
Out[103]:
array([[1, 3, 2],
[7, 0, 0]])
Так что этот тип добавления довольно ограничен по сравнению с concatenate
(и всеми его производными «стека»).
Вы смотрели код np.append
?Убедившись, что аргументы являются массивами, и настроив их формы, он делает:
concatenate((arr, values), axis=axis)
Другими словами, это просто альтернативный способ вызова concatenate
.Вероятно, лучше всего добавить одно значение в массив 1d.Он не должен использоваться повторно в цикле, именно потому, что он возвращает новый массив, и, следовательно, является относительно дорогим.В противном случае его использование портит многих пользователей.Некоторые игнорируют параметр оси.У других возникают проблемы с созданием правильного «пустого» массива для начала.Конкатенация также имеет эти проблемы, но, по крайней мере, пользователям приходится сознательно решать вопрос соответствия форм.
np.insert
гораздо сложнее.Он делает разные вещи в зависимости от того, является ли индекс (obj
) числом, срезом или списком чисел.Один из подходов заключается в создании целевого массива правильного размера, копировании фрагментов из оригинала и вставке значений в правильные слоты.Другой способ - использовать логическую маску для копирования значений в правильные места.Оба должны учитывать многомерность - они вставляются вдоль одной оси, но должны использовать соответствующий slice(None)
для других измерений.Это намного сложнее, чем вставка списка, которая вставляет один объект (указатель) в одном месте в 1d.