Создание массива в 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", причем это массив с самого начала?
Ответы
Ответ 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
в С++ сделайте это также).