有没有类似于R的seq函数生成序列的numpy函数?

30

在R中,您可以通过指定起始点、结束点和所需输出的长度来创建一个序列

seq(1, 1.5, length.out=10)
# [1] 1.000000 1.055556 1.111111 1.166667 1.222222 1.277778 1.333333 1.388889 1.444444 1.500000

在Python中,您可以以类似的方式使用numpy arange函数,但没有简单的方法来指定输出长度。我能想到的最好的办法是:

np.append(np.arange(1, 1.5, step = (1.5-1)/9), 1.5)
# array([ 1.        ,  1.05555556,  1.11111111,  1.16666667,  1.22222222, 1.27777778,  1.33333333,  1.38888889,  1.44444444,  1.5       ])

有没有更简洁的方法来执行这个操作?


7
你尝试过使用numpy.linspace吗? - cel
2
numpy.arange文档在“参见”部分中提到了numpy.linspace,这非常有帮助。每当您正在寻找执行类似或相关于您已知函数的功能的函数时,请查看该部分。 - user2357112
@cel 没有,看起来这回答了我的问题! - C_Z_
1
你也可以使用 np.r_ 的切片索引语法,将虚数作为“步长”参数,例如 np.r_[1:1.5:10j] - ali_m
4个回答

19

是的!实现这个的简单方法是使用 numpy.linspace

Numpy文档

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

在指定间隔内返回均匀间隔的数字。
返回从[start,stop]范围内均匀采样的num个值。
可选择排除区间的端点。

示例:

[In 1] np.linspace(start=0, stop=50, num=5)

[Out 1] array([  0. ,  12.5,  25. ,  37.5,  50. ])

请注意起始值和结束值之间的距离是均匀间隔的,即被num=5等分。

对于那些在安装numpy时遇到问题的人(这种情况现在越来越少),您可以考虑使用anaconda(或miniconda)或类似的发行版。


1
仅限整数怎么样? - Paul Rougieux
2
取决于你要如何切片。一种方法(如果您愿意简单地截断输出)是将其转换为整数,例如:np.linspace(start=0, stop=50, num=5).astype(np.int32)否则,您可以指定一个范围来输出整数,然后将它们转换为整数。 - PaulG
1
谢谢,似乎不需要转换类型。np.array(range(0,5)).dtype 返回 dtype('int64') - Paul Rougieux

5

作为一个替代选择(对于那些感兴趣的人),如果想要 R 中 seq(start, end, by, length.out) 函数的功能,下面的函数提供了完整的功能。

def seq(start, end, by = None, length_out = None):
    len_provided = True if (length_out is not None) else False
    by_provided = True if (by is not None) else False
    if (not by_provided) & (not len_provided):
        raise ValueError('At least by or length_out must be provided')
    width = end - start
    eps = pow(10.0, -14)
    if by_provided:
        if (abs(by) < eps):
            raise ValueError('by must be non-zero.')
    #Switch direction in case in start and end seems to have been switched (use sign of by to decide this behaviour)
        if start > end and by > 0:
            e = start
            start = end
            end = e
        elif start < end and by < 0:
            e = end
            end = start
            start = e
        absby = abs(by)
        if absby - width < eps: 
            length_out = int(width / absby)
        else: 
            #by is too great, we assume by is actually length_out
            length_out = int(by)
            by = width / (by - 1)
    else:
        length_out = int(length_out)
        by = width / (length_out - 1) 
    out = [float(start)]*length_out
    for i in range(1, length_out):
        out[i] += by * i
    if abs(start + by * length_out - end) < eps:
        out.append(end)
    return out

这个函数比 numpy.linspace 慢一点(大约慢4倍-5倍),但是使用 numba,我们可以获得一个速度大约快2倍的函数,并保持与 R 相同的语法。

from numba import jit
@jit(nopython = True, fastmath = True)
def seq(start, end, by = None, length_out = None):
    [function body]

我们可以像在 R 中执行一样来执行这个操作。

seq(0, 5, 0.3)
#out: [3.0, 3.3, 3.6, 3.9, 4.2, 4.5, 4.8]

在上述实现中,它也允许在“by”和“length_out”之间进行一定程度的交换。
seq(0, 5, 10)
#out: [0.0,
 0.5555555555555556,
 1.1111111111111112,
 1.6666666666666667,
 2.2222222222222223,
 2.7777777777777777,
 3.3333333333333335,
 3.8888888888888893,
 4.444444444444445,
 5.0]

基准测试:

%timeit -r 100 py_seq(0.5, 1, 1000) #Python no jit
133 µs ± 20.9 µs per loop (mean ± std. dev. of 100 runs, 1000 loops each)

%timeit -r 100 seq(0.5, 1, 1000) #adding @jit(nopython = True, fastmath = True) prior to function definition
20.1 µs ± 2 µs per loop (mean ± std. dev. of 100 runs, 10000 loops each)

%timeit -r 100 linspace(0.5, 1, 1000)
46.2 µs ± 6.11 µs per loop (mean ± std. dev. of 100 runs, 10000 loops each)

5

您可以在这里找到更多示例,其中包含许多使用numpy软件包的R函数。

输入图像描述

4

@PaulG的回答非常好,可以生成一系列浮点数。如果您正在寻找用于创建包含5个整数元素的numpy向量的R等效项1:5,请使用:

a = np.array(range(0,5))
a
# array([0, 1, 2, 3, 4])

a.dtype
# dtype('int64')

与 R 向量不同的是,Python 列表和 numpy 数组是从零开始索引的。一般情况下,您将使用 np.array(range(n)),它返回从 0n-1 的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接