'Python: appending numpy.array to list python overwrites the previous elements

I'm trying to plot a stellar orbit in a given potential. First, I initialize the position and velocity, and derive the acceleration from the position according to the given potential.

I then advance the time with a defined timestep and calculate the orbit. The problem arises when I try to store the calculated positions in an empty list. Here is my code:

## Initial position, velocity, and acceleration
r = np.array([20., 20., 0.])
v = np.array([0., 1., 0.])
g = acc(*r) #calculates acceleration from a function

## empty list to store position data
posdata = []

## Orbit integration
dt = 0.1
for t in np.arange(0, 1000, dt):
    v += 0.5 * g * dt
    r += v * dt
    if t%100 == 0:
        print(r) #check if r actually changes
    g = acc(*r)
    v += 0.5 * g * dt
    posdata.append(r)

This is what I'm expecting to get:

posdata
>>> [array([19.999875, 20.099875,  0.]), array([19.99950125, 20.19950001,  0.]), array([19.99887999, 20.29887502,  0.]), ...]

But I actually get this:

>>> [array([-17.57080611, -34.03696644,   0.]), array([-17.57080611, -34.03696644,   0.]), array([-17.57080611, -34.03696644,   0.])]

All the elements are identical to the last element calculated. As you can see, I checked if r actually changes, and it does. I think it has to do with the fact that r is an array, but I don't know how to correct this.



Solution 1:[1]

You are appending the same object each time you are creating a list of many references to the same object.

[r, r, r, r, r, r, r]

Since the object is mutable, when you update the object the change affects your entire list of references.

You need to create a copy of the object when you append it to your list.

Try this instead

posdata.append(r.copy())

Now you will have a different object in each list location.

[r1, r2, r3, r4, r5, r6, r7]

Solution 2:[2]

When you append array r to the list, only the reference of the array object is appended. And since numpy.array objects are mutable so all the references get updated in-place. For this, you can either

  • append the array as list to posdata as list

posdata.append(r.tolist())

Or

  • append the array as a new numpy.array object to posdata

    posdata.append(np.array(r))

Solution 3:[3]

I encountered the same problem. My solution is to change the += in the equation r += v * dt to r = r + v * dt, and then append it to the list.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 windstorm
Solution 3 Michelle Liew