Reputation: 446
I have a question regarding variable assignation and memory allocation in a simple case.
Imagine that I am initialising a state vector x
, with initial value x0
. I am then making iterative updates on that state vector with buffer array X
and after each iteration, I store the new state vector in a storage list L
. An outline of my initial implementation can be found in the following snippet:
import numpy as np
np.random.seed(11)
x0 = 1
L = [x0]
x = x0
X = np.zeros((3,1))
for i in range(10):
X[-1, :] = np.random.normal() # To simulate operations on X
x = X[-1, :]
L.append(x)
print(L)
Which would print that L holds
[1 array([-1.06560298]) array([-1.06560298]) array([-1.06560298])
array([-1.06560298]) array([-1.06560298]) array([-1.06560298])
array([-1.06560298]) array([-1.06560298]) array([-1.06560298])
array([-1.06560298])]
Because when x
is appended to L, only the reference to X[-1, :]
is added, not the actual value.
The solution I could find is to use np.copy
to copy the values of the last row of X
into x
and then append it, as can be seen in the following snippet.
import numpy as np
np.random.seed(11)
x0 = 1
L = [x0]
x = x0
X = np.zeros((3,1))
for i in range(10):
X[-1, :] = np.random.normal() # To simulate operations on X
x = np.copy(X[-1, :])
L.append(x)
print(L)
The output shows that indeed the modifications on the state x
are correctly recorded.
[1 array([1.74945474]) array([-0.286073]) array([-0.48456513])
array([-2.65331856]) array([-0.00828463]) array([-0.31963136])
array([-0.53662936]) array([0.31540267]) array([0.42105072])
array([-1.06560298])]
I wonder if there would be a more elegant or efficient way to solve this problem?
Thanks!
Upvotes: 1
Views: 60
Reputation: 114588
Don't mix numpy arrays and python lists if you can avoid it. If you know the number of iterations, pre-allocate a buffer to hold the whole thing (e.g., with np.empty
):
import numpy as np
np.random.seed(11)
N = 10
L = np.empty(N)
L[0] = 1
X = np.zeros(3)
for i in range(N):
L[i] = X[-1] = np.random.normal()
print(L)
On the other hand, if all you need is to get the scalar from a 1-element array, you can use the item
method:
x = X[:, -1].item()
Upvotes: 1
Reputation: 2088
I am not entirely sure I understand what you want to do, but maybe numpy.append()
is what you are looking for:
import numpy as np
np.random.seed(11)
x = np.array([1.])
for i in range(10):
x = np.append(x, np.random.normal())
print(x)
Upvotes: 1