Numpy - добавить строку в массив

161

Как добавить строки в массив NumPy?

У меня есть массив A:

A = array([[0, 1, 2], [0, 2, 0]])

Я хочу добавить строки в этот массив из другого массива X, если первый элемент каждой строки в X соответствует определенному условию.

В массивах Numpy нет метода «добавления», подобного спискам, или так кажется.

Если бы А и Х были списками, я бы просто сделал:

for i in X:
    if i[0] < 3:
        A.append(i)

Есть ли numpythonic способ сделать эквивалент?

Спасибо, S ;-)

Даррен Дж. Фицпатрик
источник
См. Также stackoverflow.com/questions/8486294/…
Thomas Ahle

Ответы:

120

Что такое X? Если это 2D-массив, как вы можете сравнить его строку с числом i < 3:?

РЕДАКТИРОВАТЬ после комментария OP:

A = array([[0, 1, 2], [0, 2, 0]])
X = array([[0, 1, 2], [1, 2, 0], [2, 1, 2], [3, 2, 0]])

добавить ко Aвсем строкам Xоткуда первый элемент < 3:

import numpy as np
A = np.vstack((A, X[X[:,0] < 3]))

# returns: 
array([[0, 1, 2],
       [0, 2, 0],
       [0, 1, 2],
       [1, 2, 0],
       [2, 1, 2]])
eumiro
источник
1
Извините, хороший момент! Предположим, 2D-массив, первый элемент каждой строки должен соответствовать условию. Я отредактирую это. Спасибо, S ;-)
Даррен Дж. Фицпатрик
2
@ DarrenJ.Fitzpatrick Имейте в виду, что, выполняя подобные манипуляции, вы работаете против хорошей работы, которую Numpy выполняет, предварительно выделяя память для существующего массива A. Очевидно, что для небольшой проблемы, как в этом ответе, это не проблема, но она может быть более сложной для больших данных.
dtlussier
166

ну, вы можете сделать это:

  newrow = [1,2,3]
  A = numpy.vstack([A, newrow])
jknair
источник
2
@ Крис Почему это устарело? Я ничего не вижу в документах
Георгий
1
@ Георгий Честно говоря, я не знаю. Я здесь искал ответы такие же как и вы :-). Я не могу вспомнить, почему я написал выше комментарий. Должно быть, я видел в документах его устарела. Но, глядя на документы сейчас ... это не так. Возможно ли, что они осудили это, затем снова передумали и решили, что слишком много людей будет раздражать, чтобы осудить и удалить это?
Крис
32

Так как этот вопрос был 7 лет назад, в последней версии, которую я использую, это numpy версия 1.13 и python3, я делаю то же самое, добавляя строку в матрицу, не забудьте поставить двойную скобку во второй аргумент, в противном случае это приведет к ошибке измерения.

Здесь я добавляю на матрицу А

1 2 3
4 5 6

с рядом

7 8 9

такое же использование в np.r_

A= [[1, 2, 3], [4, 5, 6]]
np.append(A, [[7, 8, 9]], axis=0)

    >> array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])
#or 
np.r_[A,[[7,8,9]]]

Просто чтобы кто-то заинтересовался, если вы хотите добавить столбец,

array = np.c_[A,np.zeros(#A's row size)]

следуя тому, что мы делали раньше на матрице А, добавив к ней столбец

np.c_[A, [2,8]]

>> array([[1, 2, 3, 2],
          [4, 5, 6, 8]])
Флора Пи Джей Ли
источник
11

Если после каждой строки вычисления не требуются, гораздо быстрее добавить строки в python, а затем преобразовать в numpy. Вот временные тесты, использующие python 3.6 против numpy 1.14, по 100 строк, по одной за раз:

import numpy as np 
from time import perf_counter, sleep

def time_it():
    # Compare performance of two methods for adding rows to numpy array
    py_array = [[0, 1, 2], [0, 2, 0]]
    py_row = [4, 5, 6]
    numpy_array = np.array(py_array)
    numpy_row = np.array([4,5,6])
    n_loops = 100

    start_clock = perf_counter()
    for count in range(0, n_loops):
       numpy_array = np.vstack([numpy_array, numpy_row]) # 5.8 micros
    duration = perf_counter() - start_clock
    print('numpy 1.14 takes {:.3f} micros per row'.format(duration * 1e6 / n_loops))

    start_clock = perf_counter()
    for count in range(0, n_loops):
        py_array.append(py_row) # .15 micros
    numpy_array = np.array(py_array) # 43.9 micros       
    duration = perf_counter() - start_clock
    print('python 3.6 takes {:.3f} micros per row'.format(duration * 1e6 / n_loops))
    sleep(15)

#time_it() prints:

numpy 1.14 takes 5.971 micros per row
python 3.6 takes 0.694 micros per row

Итак, простое решение исходного вопроса, которое было семь лет назад, заключается в использовании vstack () для добавления новой строки после преобразования строки в массив numpy. Но более реалистичное решение должно учитывать низкую производительность vstack в этих условиях. Если вам не нужно выполнять анализ данных в массиве после каждого добавления, лучше буферизовать новые строки в список строк Python (список списков, на самом деле) и добавить их как группу в массив numpy использование vstack () перед выполнением любого анализа данных.

rbasham
источник
10

Вы также можете сделать это:

newrow = [1,2,3]
A = numpy.concatenate((A,newrow))
кулачок
источник
2
хммм. когда я пытался это сделать, он просто добавлялся в конец A, а не добавлял новую строку в соответствии с запросом OP.
Тодд Карри,
13
вероятноnp.concatenate((A,newrow), axis=0)
Константинос Родитакис
3
Начиная с numpy версии 1.12.1(и в Python 3), это похоже на попытку конкатенировать вектор с повышением матрицы ValueError: all the input arrays must have same number of dimensions. Похоже, что он хочет, чтобы вектор был явно преобразован в вектор столбца или строки, прежде чем он захочет объединить его.
MRule
3
@MRule Вы можете исправить это, используя двойные квадратные скобки в соответствии с ответом @Flora PJ Li stackoverflow.com/a/47845065/1410035 . newrow = [[1,2,3]]
Том Салеба
5
import numpy as np
array_ = np.array([[1,2,3]])
add_row = np.array([[4,5,6]])

array_ = np.concatenate((array_, add_row), axis=0)
naman1994
источник
3

Если вы можете сделать конструкцию за одну операцию, то что-то вроде ответа vstack-with-fancy-indexing - хороший подход. Но если ваше состояние более сложное или строки появляются на лету, вы можете увеличить массив. Фактически, numpythonic способ сделать что-то вроде этого - динамически увеличивать массив - это динамически увеличивать список:

A = np.array([[1,2,3],[4,5,6]])
Alist = [r for r in A]
for i in range(100):
    newrow = np.arange(3)+i
    if i%5:
        Alist.append(newrow)
A = np.array(Alist)
del Alist

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

user2475529
источник
3

Я использую 'np.vstack', который быстрее, EX:

import numpy as np

input_array=np.array([1,2,3])
new_row= np.array([4,5,6])

new_array=np.vstack([input_array, new_row])
RANO
источник
2

Вы можете использовать, numpy.append()чтобы добавить строку в массив numpty и изменить форму матрицы позже.

import numpy as np
a = np.array([1,2])
a = np.append(a, [3,4])
print a
# [1,2,3,4]
# in your example
A = [1,2]
for row in X:
    A = np.append(A, row)
Чарльз Чоу
источник