0

I need to create a list in Python from a minimum and a maximum value. Half of the list needs to go up, and the other half needs to go down. Here's what I'm doing for now:

    random_data = np.random.uniform(min_value, max_value, 6))
    up_data = np.sort(random_data)
    down_data = -np.sort(-random_data)
    df = np.concatenate((up_data, down_data))
  1. I create a list of 6 random numbers between a minimum and a maximum.
  2. I sort them from down to up in a list.
  3. I sort them from up to down in another list.
  4. I put the two lists together.

It's working, but I don't like how it looks. I'm sure there must be a better way to do this but I just can't find anything. Thank you for your help!

Simon F.-Smith
  • 781
  • 3
  • 8

2 Answers2

1

Is it intentional that both sides have the same numbers ? If not, you should generate random numbers for the full size and concatenate ascending and descending sorts of half the values on each side:

import numpy as np
min_value = 75
max_value = 100
size      = 12

random_data = np.random.uniform(min_value, max_value, size)
left_side   = np.sort(random_data[::2])
right_side  = np.sort(random_data[1::2])[::-1]
df          = np.concatenate((left_side,right_side))

output:

print(df)
[84.35962408 84.86455724 84.86643652 85.95444697 86.97411648 95.55028286
 97.6394171  94.16644573 94.05654689 92.12869314 88.52363283 80.19109841]

You could also do it "in-place" directly in the resulting array:

df = np.random.uniform(min_value, max_value, size)
df[:size//2].sort()
df[size//2:][::-1].sort()

In normal Python (i.e. not using the numpy module), you can take a similar approach:

import random
values = [random.randrange(min_value,max_value) for _ in range(size)]
values[:size//2] = sorted(values[:size//2])
values[size//2:] = sorted(values[size//2:],reverse=True)

print(values)
# [78, 79, 80, 80, 87, 93, 98, 92, 90, 86, 85, 81]
Alain T.
  • 40,517
  • 4
  • 31
  • 51
  • Thank you! It's way better like this and you are right, I didn't want the same numbers on both side so that's a very good example you gave to me. – Simon F.-Smith Jan 19 '21 at 15:34
0

Not sure if you need this, but, here is the idea I suggested in comments:

import math
import random

size = 20
dec = 3

mx = 113
mn = 67

domain = sorted([random.uniform(0, math.pi) for _ in range(size)])
use_this = [round(fctr * math.sin(x), dec) for x in domain]

mx_l = max(use_this)
mn_l = min(use_this)

fctr = (mx - mn)/(mx_l - mn_l)

use_this = [round((fctr * (x - mn_l)) + mn, 0) for x in use_this]

print(use_this)

Note:

  1. sin() is monotonically increasing between 0 and pi/2 and decreasing between pi/2 and pi
  2. Used the logic at this SO answer
anurag
  • 1,715
  • 1
  • 8
  • 28
  • 1
    Nice trick. But, although it does give an ascending/descending order, the uniformity of the random distribution is broken by the sin function. Also, it doesn't give results in the min_value...max_value range (although that would be easy to fix) – Alain T. Jan 19 '21 at 15:50
  • was uniformity a requirement? the other I agree (min-max) – anurag Jan 19 '21 at 15:52
  • well the use of `random.uniform` in this case was to generate values between `0 and pi` – anurag Jan 19 '21 at 15:55
  • @AlainT., fixed the min-max problem – anurag Jan 19 '21 at 16:12