инициализировать массив numpy

129

Есть ли способ инициализировать массив numpy формы и добавить к нему? Я объясню, что мне нужно, на примере списка. Если я хочу создать список объектов, сгенерированных в цикле, я могу:

a = []
for i in range(5):
    a.append(i)

Я хочу сделать что-то подобное с массивом numpy. Я знаю о vstack, concatenate и т. Д. Однако, похоже, для этого требуются два массива numpy в качестве входных данных. Что мне нужно:

big_array # Initially empty. This is where I don't know what to specify
for i in range(5):
    array i of shape = (2,4) created.
    add to big_array

Он big_arrayдолжен иметь форму (10,4). Как это сделать?


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

Хочу добавить следующее уточнение. Я знаю, что могу определить, big_array = numpy.zeros((10,4))а затем заполнить его. Однако для этого необходимо заранее указать размер big_array. Я знаю размер в этом случае, но что, если я не знаю? Когда мы используем .appendфункцию для расширения списка в Python, нам не нужно заранее знать его окончательный размер. Мне интересно, существует ли что-то подобное для создания большего массива из меньших массивов, начиная с пустого массива.

Curious2learn
источник
Кстати ваш первый пример кода может быть написана аккуратно и лаконично , как список понимания: [i for i in range(5)]. (Эквивалентно: list(range(5))хотя это надуманный пример.)
Катриэль
какое решение сработало для вас? я пытаюсь сделать что-то подобное, как x = numpy.array()мы бы сделали со списком вроде y = []; но это не сработало
kRazzy R

Ответы:

160

numpy.zeros

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

или

numpy.ones

Вернуть новый массив заданной формы и типа, заполненный единицами.

или

numpy.empty

Вернуть новый массив заданной формы и типа без инициализации записей.


Однако менталитет, в котором мы создаем массив, добавляя элементы в список, мало используется в numpy, потому что он менее эффективен (типы данных numpy намного ближе к базовым массивам C). Вместо этого вы должны предварительно выделить массив до нужного вам размера, а затем заполнить строки. Но вы можете использовать, numpy.appendесли хотите.

Katriel
источник
2
Я знаю, что могу установить big_array = numpy.zeros, а затем заполнить его созданными небольшими массивами. Однако это требует от меня заранее указать размер big_array. Нет ничего похожего на .append функции списка, где у меня нет заранее указать размер. Спасибо!
Curious2learn
2
@ Curious2learn. Нет, в Numpy нет ничего лучше, чем append. Существуют функции, которые объединяют массивы или складывают их, создавая новые массивы, но они не делают этого путем добавления. Это из-за способа настройки структур данных. Массивы Numpy сделаны быстрыми благодаря возможности более компактного хранения значений, но для достижения этой скорости они должны иметь фиксированный размер. Списки Python предназначены для большей гибкости за счет скорости и размера.
Джастин Пил,
3
@Curious: ну, там есть appendnumpy. Просто не выполнять предварительное выделение менее эффективно (в данном случае гораздо менее эффективно, поскольку appending каждый раз копирует весь массив), поэтому это не стандартный метод.
Katriel
1
Что если только часть np.emptyмассива заполнена значениями? А как насчет оставшихся «пустых» предметов?
Ли
1
Если вы знаете только знать ширину (например , необходимое для np.concatenate()), вы можете инициализировать: np.empty((0, some_width)). 0, поэтому ваш первый массив не будет мусором.
NumesSanguis 01
40

Обычно я это делаю, создавая обычный список, затем добавляю в него свои данные и, наконец, преобразовываю список в массив numpy следующим образом:

import numpy as np
big_array = [] #  empty regular list
for i in range(5):
    arr = i*np.ones((2,4)) # for instance
    big_array.append(arr)
big_np_array = np.array(big_array)  # transformed to a numpy array

конечно, ваш последний объект занимает в два раза больше места в памяти на этапе создания, но добавление в список python происходит очень быстро, как и создание с использованием np.array ().

mad7777
источник
11
Однако это не выход, если вы заранее знаете размер массива ... Я часто использую этот метод, когда не знаю, насколько большим будет массив в конечном итоге. Например, при чтении данных из файла или другого процесса. На самом деле это не так ужасно, как может показаться сначала, поскольку python и numpy довольно умны.
travc
18

Введено в numpy 1.8:

numpy.full

Вернуть новый массив заданной формы и типа, заполненный fill_value.

Примеры:

>>> import numpy as np
>>> np.full((2, 2), np.inf)
array([[ inf,  inf],
       [ inf,  inf]])
>>> np.full((2, 2), 10)
array([[10, 10],
       [10, 10]])
Франк Дернонкур
источник
13

Аналог массива для питона

a = []
for i in range(5):
    a.append(i)

является:

import numpy as np

a = np.empty((0))
for i in range(5):
    a = np.append(a, i)
саман
источник
5
@NicholasTJ: empty((0))инициализирует массив numpy.
Adobe,
2
скобки в np.empty ((0)) избыточны.
Szymon Roziewski
7

numpy.fromiter() это то, что вы ищете:

big_array = numpy.fromiter(xrange(5), dtype="int")

Он также работает с выражениями генератора, например:

big_array = numpy.fromiter( (i*(i+1)/2 for i in xrange(5)), dtype="int" )

Если вы заранее знаете длину массива, вы можете указать ее с помощью необязательного аргумента count.

Квант Метрополис
источник
2
Я действительно запускал timeit и думаю, что np.fromiter () может быть медленнее, чем np.array (). timeit ("np.array (i for i in xrange (100))", setup = "import numpy as np", number = 10000) -> 0,02539992332458496, по сравнению с timeit ("np.fromiter ((i for i in xrange ( 100)), dtype = int) ", setup =" import numpy as np ", number = 10000) -> 0.13351011276245117
hlin117
6

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

big_array = numpy.zeros((10,4))

РЕДАКТИРОВАТЬ: Какую последовательность вы делаете? Вы должны проверить различные функции numpy, которые создают массивы, например numpy.linspace(start, stop, size)(число с равным интервалом) или numpy.arange(start, stop, inc). По возможности, эти функции сделают массивы значительно быстрее, чем выполнение той же работы в явных циклах.

Андреас Лёв Селвик
источник
6

Чтобы инициализировать массив numpy с определенной матрицей:

import numpy as np

mat = np.array([[1, 1, 0, 0, 0],
                [0, 1, 0, 0, 1],
                [1, 0, 0, 1, 1],
                [0, 0, 0, 0, 0],
                [1, 0, 1, 0, 1]])

print mat.shape
print mat

вывод:

(5, 5)
[[1 1 0 0 0]
 [0 1 0 0 1]
 [1 0 0 1 1]
 [0 0 0 0 0]
 [1 0 1 0 1]]
EdW
источник
5

Для вашего первого примера использования массива

a = numpy.arange(5)

Чтобы инициализировать big_array, используйте

big_array = numpy.zeros((10,4))

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

Изменить: если вы заранее не знаете размер big_array, обычно лучше сначала создать список Python с помощью append, а когда у вас есть все, что собрано в списке, преобразовать этот список в массив numpy, используя numpy.array(mylist). Причина этого в том, что списки предназначены для очень эффективного и быстрого роста, тогда как numpy.concatenate будет очень неэффективным, поскольку массивы numpy не меняют размер легко. Но как только все будет собрано в список и вы узнаете окончательный размер массива, можно будет эффективно построить массив numpy.

tom10
источник
3

Я бы предложил сначала определить форму. Затем переберите его, чтобы вставить значения.

big_array= np.zeros(shape = ( 6, 2 ))
for it in range(6):
    big_array[it] = (it,it) # For example

>>>big_array

array([[ 0.,  0.],
       [ 1.,  1.],
       [ 2.,  2.],
       [ 3.,  3.],
       [ 4.,  4.],
       [ 5.,  5.]])
GT GT
источник
3

Когда бы вы ни оказались в следующей ситуации:

a = []
for i in range(5):
    a.append(i)

и вы хотите что-то подобное в numpy, в нескольких предыдущих ответах были указаны способы сделать это, но, как указал @katrielalex, эти методы неэффективны. Эффективный способ сделать это - создать длинный список, а затем изменить его так, как вы хотите, после того, как у вас будет длинный список. Например, предположим, что я читаю несколько строк из файла, и в каждой строке есть список чисел, и я хочу построить массив формы (количество прочитанных строк, длина вектора в каждой строке). Вот как я бы сделал это более эффективно:

long_list = []
counter = 0
with open('filename', 'r') as f:
    for row in f:
        row_list = row.split()
        long_list.extend(row_list)
        counter++
#  now we have a long list and we are ready to reshape
result = np.array(long_list).reshape(counter, len(row_list)) #  desired numpy array
Heapify
источник
2

Я понимаю, что это немного поздно, но я не заметил никаких других ответов, в которых упоминается индексация в пустой массив:

big_array = numpy.empty(10, 4)
for i in range(5):
    array_i = numpy.random.random(2, 4)
    big_array[2 * i:2 * (i + 1), :] = array_i

Таким образом, вы заранее выделяете весь массив результатов numpy.emptyи заполняете строки по мере продвижения, используя индексированное присвоение.

Совершенно безопасно выполнить предварительное emptyвыделение, а не zerosв приведенном вами примере, поскольку вы гарантируете, что весь массив будет заполнен генерируемыми фрагментами.

Безумный физик
источник
1

Может быть, что-то подобное подойдет вам ...

import numpy as np

N = 5
res = []

for i in range(N):
    res.append(np.cumsum(np.ones(shape=(2,4))))

res = np.array(res).reshape((10, 4))
print(res)

Что дает следующий результат

[[ 1.  2.  3.  4.]
 [ 5.  6.  7.  8.]
 [ 1.  2.  3.  4.]
 [ 5.  6.  7.  8.]
 [ 1.  2.  3.  4.]
 [ 5.  6.  7.  8.]
 [ 1.  2.  3.  4.]
 [ 5.  6.  7.  8.]
 [ 1.  2.  3.  4.]
 [ 5.  6.  7.  8.]]

источник