ініціалізувати масивний масив


129

Чи є спосіб ініціалізувати масивний фігуру фігури та додати до неї? Я поясню, що мені потрібно на прикладі списку. Якщо я хочу створити список об’єктів, згенерованих у циклі, я можу зробити:

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

Я хочу зробити щось подібне з нумерованим масивом. Я знаю про vstack, concatenate і т. Д. Однак, здається, для цього потрібні два нумеровані масиви як вхідні дані. Що мені потрібно:

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, нам не потрібно заздалегідь знати його остаточний розмір. Мені цікаво, чи існує щось подібне для створення більшого масиву з менших масивів, починаючи з порожнього масиву.


Між іншим, ваш перший зразок коду може бути написаний акуратно і стисло, як список [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Однак ви можете використовувати, якщо потрібно.


2
Я знаю, що можу встановити big_array = numpy.zeros, а потім заповнити його створеними невеликими масивами. Це, однак, вимагає від мене заздалегідь вказати розмір big_array. Чи немає нічого подібного .append до списку функції, де я не вказую розмір заздалегідь. Дякую!
Curious2learn

2
@ Curious2learn. Ні, в Numpy немає нічого подібного додати. Є функції, які об'єднують масиви або стекують їх, створюючи нові масиви, але вони не роблять цього шляхом додавання. Це пояснюється тим, як налаштовано структури даних. Numpy масиви робляться швидкими завдяки можливості компактніше зберігати значення, але для отримання цієї швидкості вони повинні мати фіксований розмір. Списки Python розроблені таким чином, щоб бути більш гнучкими за рахунок швидкості та розміру.
Джастін Піл

3
@Curious: ну, є appendнуме. Це просто менш ефективно не переділити місце (у цьому випадку набагато менш ефективно, оскільки appendкопіюється весь масив кожен раз), тому це не стандартна методика.
Катріель

1
Що робити, якщо лише частина np.emptyмасиву заповнена значеннями? А що з рештою "порожніх" предметів?
Лі

1
Якщо ви знаєте тільки знати ширину (наприклад , необхідне для np.concatenate()), ви можете форматувати: np.empty((0, some_width)). 0, тож ваш перший масив не буде сміттям.
NumesSanguis

40

Я зазвичай це роблю, створюючи звичайний список, потім додаю до нього свої речі і, нарешті, перетворюю список у масивний масив таким чином:

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 () також.


11
Це не шлях, якщо ви знаєте розмір масиву достроково , однак ... Я в кінцевому підсумку використовую цей метод часто, коли я не знаю, наскільки великий масив у підсумку. Наприклад, під час читання даних з файлу чи іншого процесу. Це насправді не так жахливо, як може здатися спочатку, оскільки python і numpy досить розумні.
травч

18

Введено в числом 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))ініціалізує масив нумерів.
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 для i в xrange (100))", setup = "імпорт numpy як np", число = 10000) -> 0,02539992332458496, порівняно з timeit ("np.fromiter ((i для i в xrange ( 100)), dtype = int) ", setup =" імпорт numpy як np ", число = 10000) -> 0,13351011276245117
hlin117

6

Ви хочете максимально уникати явних циклів, роблячи обчислення масиву, оскільки це зменшує приріст швидкості від такої форми обчислень. Існує кілька способів ініціалізації масиву нумерів. Якщо ви хочете, щоб він був заповнений нулями, зробіть так, як сказав katrielalex:

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

EDIT: Яку послідовність ви робите? Вам слід перевірити різні функції нумерації, які створюють масиви, наприклад 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]]

5

Для першого прикладу використання масиву,

a = numpy.arange(5)

Для ініціалізації big_array використовуйте

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

Це передбачає, що ви хочете ініціалізувати нулі, що досить типово, але існує багато інших способів ініціалізації масиву в numpy .

Редагувати: Якщо ви не знаєте розмір big_array заздалегідь, зазвичай, найкраще спершу створити список Python за допомогою додавання, а коли у вас все зібрано в списку, перетворіть цей список у масив numpy за допомогою numpy.array(mylist). Причиною цього є те, що списки повинні рости дуже ефективно та швидко, тоді як numpy.concatenate буде дуже неефективним, оскільки numpy-масиви не змінюють розмір легко. Але як тільки все зібрано у списку, і ви знаєте остаточний розмір масиву, нумерований масив може бути ефективно побудований.


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.]])

3

Щоразу, коли ви знаходитесь у такій ситуації:

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

і ви хочете чогось подібного в нумері, кілька попередніх відповідей вказували способи зробити це, але як зазначав @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

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.]]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.