Shuffling an array except the first and the last element in Python

Question:

I am generating a normal distribution but keeping the mean and std exactly the same by using np.random.seed(0). I am trying to shuffle r except the first and the last elements of the array but it keeps the remaining elements at the same location in the array as shown in the current output. I also present the expected output.

import numpy as np

np.random.seed(0)

mu, sigma = 50, 2.0 # mean and standard deviation
Nodes=10
r = np.random.normal(mu, sigma, Nodes)

sort_r = np.sort(r); 
r1=sort_r[::-1]

r1=r1.reshape(1,Nodes)


r2 = r.copy()

np.random.shuffle(r2.ravel()[1:]) 

r2=r2.reshape(1,Nodes)                         #actual radius values in mu(m)

maximum = r2.max()
indice1 = np.where(r2 == maximum)
r2[indice1] = r2[0][0]
r2[0][0] = maximum

r2[0][Nodes-1] = maximum  #+0.01*maximum

print("r2 with max at (0,0)=",[r2])

The current output for many runs is

r2 with max at (0,0)= [array([[54.4817864 , 51.90017684, 53.52810469, 53.73511598, 48.04544424,
        51.95747597, 50.80031442, 50.821197  , 49.7935623 , 54.4817864 ]])]

The expected output is (shuffling all elements randomly except the first and the last element)

Run 1: r2 with max at (0,0)= [array([[54.4817864 , 53.52810469, 51.90017684, ,53.73511598, 48.04544424,49.7935623 ,50.80031442, 50.821197  , 51.95747597,  54.4817864 ]])]

Run 2: r2 with max at (0,0)= [array([[54.4817864 , 51.90017684,53.52810469, 48.04544424, 53.73511598, 51.95747597,  49.7935623 ,50.80031442, 50.821197  , 54.4817864 ]])]
Asked By: user20032724

||

Answers:

It’s not that clear from your question what do you include in a run.

If, like it seems, you’re initializing distribution and seed every time, shuffling it once will always give you the same result. It must be like that because random state is fixed, just like you want your random numbers to be predictable also the shuffle operation will return always the same result.

Let me show you what I mean with some simpler code than yours:

# reinit distribution and seed at each run
for run in range(5):
    np.random.seed(0)
    a = np.random.randint(10, size=10)

    np.random.shuffle(a)
    print(f'{run}:{a}')

Which will print

0:[2 3 9 0 3 7 4 5 3 5]
1:[2 3 9 0 3 7 4 5 3 5]
2:[2 3 9 0 3 7 4 5 3 5]
3:[2 3 9 0 3 7 4 5 3 5]
4:[2 3 9 0 3 7 4 5 3 5]

What you want is to initialize your distribution once and shuffle it at each run:

# init distribution and just shuffle it at each run
np.random.seed(0)
a = np.random.randint(10, size=10)

for run in range(5):
    np.random.shuffle(a)
    print(f'{run}:{a}')

Which will print:

0:[2 3 9 0 3 7 4 5 3 5]
1:[9 0 3 4 2 5 7 3 3 5]
2:[2 0 3 3 3 5 7 5 4 9]
3:[5 3 5 3 0 2 7 4 9 3]
4:[3 9 3 2 5 7 3 4 0 5]
Answered By: filippo
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.