Подтвердить что ты не робот

Создание массива в numpy/scipy путем итерации в Python?

Часто я создаю массив, повторяя некоторые данные, например:

my_array = []
for n in range(1000):
  # do operation, get value 
  my_array.append(value)
# cast to array
my_array = array(my_array)

Я обнаружил, что мне нужно сначала создать список, а затем применить его (используя "массив" ) к массиву. Есть ли способ обойти эти проблемы? Все эти призывы кастинга загромождают код... как я могу итеративно создавать "my_array", причем это массив с самого начала?

4b9b3361

Ответ 1

Если я правильно понимаю ваш вопрос, это должно делать то, что вы хотите:

# the array passed into your function
ax = NP.random.randint(10, 99, 20).reshape(5, 4)

# just define a function to operate on some data
fnx = lambda x : NP.sum(x)**2

# apply the function directly to the numpy array
new_row = NP.apply_along_axis(func1d=fnx, axis=0, arr=ax)

# 'append' the new values to the original array
new_row = new_row.reshape(1,4)
ax = NP.vstack((ax, new_row))

Ответ 2

NumPy предоставляет метод 'fromiter':

def myfunc(n):
    for i in range(n):
        yield i**2


np.fromiter(myfunc(5), dtype=int)

что дает

array([ 0,  1,  4,  9, 16])

Ответ 3

Рекомендуемый способ сделать это - предварительно распределить перед циклом и использовать нарезку и индексирование для вставки

my_array = numpy.zeros(1,1000)
for i in xrange(1000):
    #for 1D array
    my_array[i] = functionToGetValue(i)
    #OR to fill an entire row
    my_array[i:] = functionToGetValue(i)
    #or to fill an entire column
    my_array[:,i] = functionToGetValue(i)

numpy предоставляет метод array.resize(), но это будет намного медленнее из-за стоимости перераспределения памяти внутри цикла. Если у вас есть гибкость, я боюсь, что единственный способ - создать array из list.

EDIT: Если вы обеспокоены тем, что вы выделяете слишком много памяти для своих данных, я бы использовал вышеописанный метод для перераспределения, а затем, когда цикл был завершен, удалите неиспользуемые биты массива, используя array.resize(). Это будет намного быстрее, чем постоянное перераспределение массива внутри цикла.

EDIT: в ответ на комментарий @user248237, предполагая, что вы знаете какое-либо одно измерение массива (для простоты):

my_array = numpy.array(10000, SOMECONSTANT)

for i in xrange(someVariable):
    if i >= my_array.shape[0]:
        my_array.resize((my_array.shape[0]*2, SOMECONSTANT))

    my_array[i:] = someFunction()

#lop off extra bits with resize() here

Общий принцип: "выделяйте больше, чем вы думаете, что вам нужно, и если что-то изменится, измените размер массива как можно раньше". Удвоение размера можно считать чрезмерным, но на самом деле это метод, используемый несколькими структурами данных в нескольких стандартных библиотеках на других языках (java.util.Vector делает это по умолчанию, например. Я думаю, что несколько реализаций std::vector в С++ сделайте это также).