Как мне создать пустой массив / матрицу в NumPy?

311

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

На данный момент я могу найти единственный способ сделать это:

mat = None
for col in columns:
    if mat is None:
        mat = col
    else:
        mat = hstack((mat, col))

Тогда как если бы это был список, я бы сделал что-то вроде этого:

list = []
for item in data:
    list.append(item)

Есть ли способ использовать такую ​​запись для массивов или матриц NumPy ?

Бен
источник

Ответы:

441

У вас неправильная ментальная модель для эффективного использования NumPy. Массивы NumPy хранятся в смежных блоках памяти. Если вы хотите добавить строки или столбцы в существующий массив, весь массив необходимо скопировать в новый блок памяти, создавая пробелы для хранения новых элементов. Это очень неэффективно, если сделать это несколько раз для построения массива.

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

>>> import numpy
>>> a = numpy.zeros(shape=(5,2))
>>> a
array([[ 0.,  0.],
   [ 0.,  0.],
   [ 0.,  0.],
   [ 0.,  0.],
   [ 0.,  0.]])
>>> a[0] = [1,2]
>>> a[1] = [2,3]
>>> a
array([[ 1.,  2.],
   [ 2.,  3.],
   [ 0.,  0.],
   [ 0.,  0.],
   [ 0.,  0.]])
Стивен Симмонс
источник
123
Существует также numpy.empty (), если вам не нужно обнулять массив.
Янв
21
В чем преимущество использования empty () над нулями ()?
Зак
45
что если вы собираетесь сразу инициализировать его с вашими данными, вы сэкономите на обнулении.
Маркоросси
16
@maracorossi .empty()означает, что в ячейках можно найти случайные значения, но массив создается быстрее, чем, например, с помощью .zeros()?
user3085931
6
@ user3085931 да!
Натан
98

Массив NumPy - это очень отличающаяся структура данных от списка, и он предназначен для использования по-разному. Ваше использование hstackпотенциально очень неэффективно ... каждый раз, когда вы вызываете его, все данные в существующем массиве копируются в новый. (У этой appendфункции будет та же проблема.) Если вы хотите построить свою матрицу по одному столбцу за раз, лучше всего сохранить ее в списке до ее завершения, и только затем преобразовать в массив.

например


mylist = []
for item in data:
    mylist.append(item)
mat = numpy.array(mylist)

itemможет быть списком, массивом или любым итеративным, если каждый из них itemимеет одинаковое количество элементов.
В этом конкретном случае ( dataэто итеративный столбец матрицы) вы можете просто использовать


mat = numpy.array(data)

(Также обратите внимание, что использование listв качестве имени переменной, вероятно, не очень хорошая практика, поскольку оно маскирует встроенный тип под этим именем, что может привести к ошибкам.)

РЕДАКТИРОВАТЬ:

Если по какой-то причине вы действительно хотите создать пустой массив, вы можете просто использовать numpy.array([]), но это редко полезно!

Грег Болл
источник
1
Существенно ли отличаются числовые массивы / матрицы от Matlab?
Levesque
1
Если по какой - то причине вам необходимо определить пустой массив, но с фиксированной шириной (например np.concatenate()), вы можете использовать: np.empty((0, some_width)). 0, так что ваш первый массив не будет мусором.
NumesSanguis
56

Чтобы создать пустой многомерный массив в NumPy (например, 2D-массив m*nдля хранения вашей матрицы), на случай, если вы не знаете, mсколько строк вы добавите, и не заботитесь о вычислительных затратах, упомянутых Стивеном Симмонсом (а именно, перестройкой массив на каждом Append), вы можете сжать до 0 измерение , к которому вы хотите добавить к: X = np.empty(shape=[0, n]).

Таким образом, вы можете использовать, например (здесь, m = 5который мы предполагаем, что мы не знали при создании пустой матрицы, и n = 2):

import numpy as np

n = 2
X = np.empty(shape=[0, n])

for i in range(5):
    for j  in range(2):
        X = np.append(X, [[i, j]], axis=0)

print X

который даст вам:

[[ 0.  0.]
 [ 0.  1.]
 [ 1.  0.]
 [ 1.  1.]
 [ 2.  0.]
 [ 2.  1.]
 [ 3.  0.]
 [ 3.  1.]
 [ 4.  0.]
 [ 4.  1.]]
Франк Дернонкур
источник
1
Это должен быть ответ на вопрос, заданный OP, для случая использования, когда вы заранее не знаете #rows или хотите обработать случай, когда есть 0 строк
Spcogg второе
26

Я много разбирался в этом, потому что мне нужно было использовать numpy.array в качестве набора в одном из моих школьных проектов, и мне нужно было инициализировать пустой ... Я не нашел здесь никакого релевантного ответа о переполнении стека, поэтому я начал рисовал что-то

# Initialize your variable as an empty list first
In [32]: x=[]
# and now cast it as a numpy ndarray
In [33]: x=np.array(x)

Результат будет:

In [34]: x
Out[34]: array([], dtype=float64)

Поэтому вы можете напрямую инициализировать массив np следующим образом:

In [36]: x= np.array([], dtype=np.float64)

Надеюсь, это поможет.

Андрей Пага
источник
Это не работает для массивов, как в вопросе, но может быть полезно для векторов.
Divenex
a=np.array([])Кажется, по умолчаниюfloat64
P i
7

Вы можете использовать функцию добавления. Для строк:

>>> from numpy import *
>>> a = array([10,20,30])
>>> append(a, [[1,2,3]], axis=0)
array([[10, 20, 30],      
       [1, 2, 3]])

Для столбцов:

>>> append(a, [[15],[15]], axis=1)
array([[10, 20, 30, 15],      
       [1, 2, 3, 15]])

РЕДАКТИРОВАТЬ
Конечно, как упоминалось в других ответах, если вы не выполняете какую-либо обработку (например, инверсию) для матрицы / массива КАЖДЫЙ раз, когда вы добавляете что-то к нему, я просто создаю список, добавляю к нему, а затем преобразую его в массив.

Ил-Бхима
источник
3

Если вы абсолютно не знаете окончательный размер массива, вы можете увеличить размер массива следующим образом:

my_arr = numpy.zeros((0,5))
for i in range(3):
    my_arr=numpy.concatenate( ( my_arr, numpy.ones((1,5)) ) )
print(my_arr)

[[ 1.  1.  1.  1.  1.]  [ 1.  1.  1.  1.  1.]  [ 1.  1.  1.  1.  1.]]
  • Обратите внимание на 0первую строку.
  • numpy.appendэто еще один вариант. Это звонки numpy.concatenate.
киборг
источник
3

Вы можете применить его для построения любого вида массива, например, нулей:

a = range(5)
a = [i*0 for i in a]
print a 
[0, 0, 0, 0, 0]
Али Г
источник
4
Если вы хотите сделать это в чистом Python, a= [0] * 5это простое решение
Makers_F
3

Вот некоторый обходной путь, чтобы numpys больше походили на Списки

np_arr = np.array([])
np_arr = np.append(np_arr , 2)
np_arr = np.append(np_arr , 24)
print(np_arr)

ВЫХОД: массив ([2., 24.])

Darius
источник
2

В зависимости от того, для чего вы это используете, вам может потребоваться указать тип данных (см. «Dtype» ).

Например, чтобы создать двумерный массив 8-битных значений (подходит для использования в качестве монохромного изображения):

myarray = numpy.empty(shape=(H,W),dtype='u1')

Для изображения RGB укажите количество цветовых каналов в форме: shape=(H,W,3)

Вы также можете рассмотреть возможность инициализации нулями numpy.zerosвместо использования numpy.empty. Смотрите примечание здесь .

nobar
источник
1

Я думаю, что вы хотите обрабатывать большую часть работы со списками, а затем использовать результат в качестве матрицы. Может быть, это способ;

ur_list = []
for col in columns:
    ur_list.append(list(col))

mat = np.matrix(ur_list)
руно
источник
1

Я думаю, что вы можете создать пустой массив, как:

>>> import numpy as np
>>> empty_array= np.zeros(0)
>>> empty_array
array([], dtype=float64)
>>> empty_array.shape
(0,)

Этот формат полезен, когда вы хотите добавить массив NumPy в цикл.

веешь д
источник
0

Для создания пустого массива NumPy без определения его формы есть способ:

1.

arr = np.array([]) 

предпочтительным. потому что вы знаете, что вы будете использовать это как NumPy.

2.

arr = []
# and use it as numpy. append to it or etc..

NumPy преобразует это в тип np.ndarray впоследствии, без доп [] dimionsion.

Pedram
источник
0

Возможно, вы ищете что-то вроде этого:

x=np.array(0)

Таким образом, вы можете создать массив без каких-либо элементов. Это похоже чем:

x=[]

Таким образом, вы сможете заранее добавлять новые элементы в ваш массив.

Эдгар Дуарте
источник