64

What is a pythonic way of making list of arbitrary length containing evenly spaced numbers (not just whole integers) between given bounds? For instance:

my_func(0,5,10) # ( lower_bound , upper_bound , length )
# [ 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5 ] 

Note the Range() function only deals with integers. And this:

def my_func(low,up,leng):
    list = []
    step = (up - low) / float(leng)
    for i in range(leng):
        list.append(low)
        low = low + step
    return list

seems too complicated. Any ideas?

Double AA
  • 5,759
  • 16
  • 44
  • 56
  • There was some nice solutions: http://stackoverflow.com/questions/477486/python-decimal-range-step-value – Pill Jul 13 '11 at 18:29
  • 1
    Note that this only works accurately for some sequences due to the (necessary) inaccuracy of floating point numbers. –  Jul 13 '11 at 18:30

7 Answers7

91

Given numpy, you could use linspace:

Including the right endpoint (5):

In [46]: import numpy as np
In [47]: np.linspace(0,5,10)
Out[47]: 
array([ 0.        ,  0.55555556,  1.11111111,  1.66666667,  2.22222222,
        2.77777778,  3.33333333,  3.88888889,  4.44444444,  5.        ])

Excluding the right endpoint:

In [48]: np.linspace(0,5,10,endpoint=False)
Out[48]: array([ 0. ,  0.5,  1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5])
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
51

You can use the following approach:

[lower + x*(upper-lower)/length for x in range(length)]

lower and/or upper must be assigned as floats for this approach to work.

milancurcic
  • 6,202
  • 2
  • 34
  • 47
Howard
  • 38,639
  • 9
  • 64
  • 83
  • 8
    Nice to have a concise stock python alternative in case numpy is not available. – feedMe Feb 09 '16 at 14:25
  • 6
    this updated version produces the _exact_ same output as numpy linspace: `[lower + x*(upper-lower)/(length-1) for x in range(length)` – Trav May 10 '18 at 14:40
  • @Trav it does not provide the exact same. The results are not numerically identical for when ascending linspace, and for descending (example: np.linspace(1,0.2,4)) it is very off. Still, its a good effort to get same ballpark numbers for ascending case – Stefan Karlsson Feb 08 '23 at 14:39
14

Similar to unutbu's answer, you can use numpy's arange function, which is analog to Python's intrinsic function range. Notice that the end point is not included, as in range:

>>> import numpy as np
>>> a = np.arange(0,5, 0.5)
>>> a
array([ 0. ,  0.5,  1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5])
>>> a = np.arange(0,5, 0.5) # returns a numpy array
>>> a
array([ 0. ,  0.5,  1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5])
>>> a.tolist() # if you prefer it as a list
[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5]
milancurcic
  • 6,202
  • 2
  • 34
  • 47
4
f = 0.5
a = 0
b = 9
d = [x * f for x in range(a, b)]

would be a way to do it.

marc
  • 6,103
  • 1
  • 28
  • 33
2

Numpy's r_ convenience function can also create evenly spaced lists with syntax np.r_[start:stop:steps]. If steps is a real number (ending on j), then the end point is included, equivalent to np.linspace(start, stop, step, endpoint=1), otherwise not.

>>> np.r_[-1:1:6j, [0]*3, 5, 6]
array([-1. , -0.6, -0.2,  0.2,  0.6,  1.])

You can also directly concatente other arrays and also scalars:

>>> np.r_[-1:1:6j, [0]*3, 5, 6]
array([-1. , -0.6, -0.2,  0.2,  0.6,  1. ,  0. ,  0. ,  0. ,  5. ,  6. ])
Robin Dinse
  • 1,491
  • 14
  • 20
1

You can use the folowing code:

def float_range(initVal, itemCount, step):
    for x in xrange(itemCount):
        yield initVal
        initVal += step

[x for x in float_range(1, 3, 0.1)]
Artsiom Rudzenka
  • 27,895
  • 4
  • 34
  • 52
0

Similar to Howard's answer but a bit more efficient:

def my_func(low, up, leng):
    step = ((up-low) * 1.0 / leng)
    return [low+i*step for i in xrange(leng)]
Peter Collingridge
  • 10,849
  • 3
  • 44
  • 61