Skip to content
Advertisement

Improvement on copy array elements numpy

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!

Advertisement

Answer

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()
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement