Как добавить новую строку в пустой массив NumPy

158

Используя стандартные массивы Python, я могу сделать следующее:

arr = []
arr.append([1,2,3])
arr.append([4,5,6])
# arr is now [[1,2,3],[4,5,6]]

Тем не менее, я не могу сделать то же самое в NumPy. Например:

arr = np.array([])
arr = np.append(arr, np.array([1,2,3]))
arr = np.append(arr, np.array([4,5,6]))
# arr is now [1,2,3,4,5,6]

Я тоже посмотрел vstack, но когда я используюvstack пустой массив, я получаю:

ValueError: all the input array dimensions except for the concatenation axis must match exactly

Итак, как мне добавить новую строку в пустой массив в NumPy?

Тони Старк
источник
1
Если он пуст, зачем? Просто начните с массива, содержащего только первый ряд.
Jonrsharpe
10
Я просто хочу знать, возможно ли добавить пустой массив NumPy. Иногда написать такой код чище, поскольку операции добавления находятся в цикле.
Тони Старк
5
Учитывая то , как Numpy массивы работы, вы гораздо лучше строить пустой массив затем положить данные, например , см stackoverflow.com/questions/568962/...
jonrsharpe

Ответы:

228

Способ «запустить» нужный вам массив:

arr = np.empty((0,3), int)

Который является пустым массивом, но имеет правильную размерность.

>>> arr
array([], shape=(0, 3), dtype=int64)

Затем обязательно добавьте вдоль оси 0:

arr = np.append(arr, np.array([[1,2,3]]), axis=0)
arr = np.append(arr, np.array([[4,5,6]]), axis=0)

Но @jonrsharpe прав. На самом деле, если вы собираетесь добавлять в цикл, было бы гораздо быстрее добавить список, как в первом примере, а затем преобразовать в массив с пустыми значениями в конце, поскольку вы на самом деле не используете numpy как предназначен во время цикла:

In [210]: %%timeit
   .....: l = []
   .....: for i in xrange(1000):
   .....:     l.append([3*i+1,3*i+2,3*i+3])
   .....: l = np.asarray(l)
   .....: 
1000 loops, best of 3: 1.18 ms per loop

In [211]: %%timeit
   .....: a = np.empty((0,3), int)
   .....: for i in xrange(1000):
   .....:     a = np.append(a, 3*i+np.array([[1,2,3]]), 0)
   .....: 
100 loops, best of 3: 18.5 ms per loop

In [214]: np.allclose(a, l)
Out[214]: True

Numpythonic способ сделать это зависит от вашего приложения, но это будет больше похоже на:

In [220]: timeit n = np.arange(1,3001).reshape(1000,3)
100000 loops, best of 3: 5.93 µs per loop

In [221]: np.allclose(a, n)
Out[221]: True
askewchan
источник
Что делать, если я должен сделать это 10 ^ 5 или 10 ^ 6 раз? Похоже, что ни один из этих методов не пройдет. любое предложение?
Ро Пхи
@Roberto, обычно есть какой-то способ заранее определить размер или форму (по крайней мере, значения будут предпочтительнее) массива. Как вы думаете, вы можете сделать это? Добавление действительно должно быть одной или двумя временными операциями.
Askewchan
иногда вы не можете угадать размеры, это жизнь. Однако вы можете выделить достаточно большой массив и дать значения его представлениям. Мне это не нравится, потому что есть нежелательные значения, которые нужно найти способ «замаскировать». Эта идея маскировки действительно не соответствует моему вкусу.
Ро Пхи
Не нужно маскировать, просто нарезать! a = a[:N] Хотя я твердо верю, что вы должны найти способ векторизовать его (напишите новый вопрос со своей спецификой, если вам нужна помощь) или просто использовать списки, пока цикл не закончится.
Askewchan
29

Вот мое решение:

arr = []
arr.append([1,2,3])
arr.append([4,5,6])
np_arr = np.array(arr)
just4fun
источник
Полученный массив имеет объект типа d, что в некоторых случаях
неприемлемо
26

В этом случае вы можете использовать функции np.hstack и np.vstack

arr = np.array([])
arr = np.hstack((arr, np.array([1,2,3])))
# arr is now [1,2,3]

arr = np.vstack((arr, np.array([4,5,6])))
# arr is now [[1,2,3],[4,5,6]]

Вы также можете использовать функцию np.concatenate.

ура

mrcl
источник
7
Не будет работать, если второй массив имеет размерность, равную> = 2 ((2, 2)). Мне кажется, что нет способа избежать граничных случаев, если вы строите массивы из пустых путем конкатенации.
Таоси
Не хорошее решение, так как нужно каждый раз проверять размер.
СКР
1

используя собственное определение dtype, у меня сработало следующее:

import numpy

# define custom dtype
type1 = numpy.dtype([('freq', numpy.float64, 1), ('amplitude', numpy.float64, 1)])
# declare empty array, zero rows but one column
arr = numpy.empty([0,1],dtype=type1)
# store row data, maybe inside a loop
row = numpy.array([(0.0001, 0.002)], dtype=type1)
# append row to the main array
arr = numpy.row_stack((arr, row))
# print values stored in the row 0
print float(arr[0]['freq'])
print float(arr[0]['amplitude'])
boclodoa
источник
1

В случае добавления новых строк для массива в цикле, присвойте массив непосредственно в первый раз в цикле вместо инициализации пустого массива.

for i in range(0,len(0,100)):
    SOMECALCULATEDARRAY = .......
    if(i==0):
        finalArrayCollection = SOMECALCULATEDARRAY
    else:
        finalArrayCollection = np.vstack(finalArrayCollection,SOMECALCULATEDARRAY)

Это в основном полезно, когда форма массива неизвестна

Rajesh_Saladi
источник
0

Я хочу сделать цикл for, но с методом askewchan он не работает, поэтому я изменил его.

x=np.empty((0,3))
y=np.array([1 2 3])
for i in ...
x = vstack((x,y))
Циндун Ван
источник