np.arange或np.linspace的替代,具有非均匀间隔



我可以在[0,2*pi)上使用numpy函数np.arange()获得一个统一的网格,但是,我想要一个具有相同点数但在一定间隔上具有更多点密度的网格,例如在[pi,1.5*pi]上具有更精细的网格。我如何实现这一点,是否有一个接受密度函数的 numpy 函数,它的输出是具有该密度的网格?

>我很惊讶我在Stack Overflow上找不到类似的问答。有一些关于对离散分布中的随机数做类似的事情,但对连续分布不行,也不是作为修改np.arangenp.linspace

如果需要获取一个 x 范围进行绘图,该范围在预计函数波动较快的区域具有更精细的采样,则可以创建一个非线性函数,该函数接受 0 到 1 范围内的输入,并生成非线性进行相同范围内的输出。例如:

def f(x):
return x**2
angles = 2*np.pi*f(np.linspace(0, 1, num, endpoint=False))

这将在接近零的地方产生精细采样,在 2*pi 附近产生粗采样。 要更精细地控制采样密度,可以使用以下函数。作为奖励,它还允许随机抽样。

import numpy as np
def density_space(xs, ps, n, endpoint=False, order=1, random=False):
"""Draw samples with spacing specified by a density function.
Copyright Han-Kwang Nienhuys (2020).
License: any of: CC-BY, CC-BY-SA, BSD, LGPL, GPL.
Reference: https://stackoverflow.com/a/62740029/6228891

Parameters:

- xs: array, ordered by increasing values.
- ps: array, corresponding densities (not normalized).
- n: number of output values.
- endpoint: whether to include x[-1] in the output.
- order: interpolation order (1 or 2). Order 2 will
require dense sampling and a smoothly varying density 
to work correctly.
- random: whether to return random samples, ignoring endpoint).
in this case, n can be a shape tuple.
Return:

- array, shape (n,), with values from xs[0] to xs[-1]
"""
from scipy.interpolate import interp1d
from scipy.integrate import cumtrapz

cps = cumtrapz(ps, xs, initial=0)
cps *= (1/cps[-1])
intfunc = interp1d(cps, xs, kind=order)
if random:
return intfunc(np.random.uniform(size=n))
else:
return intfunc(np.linspace(0, 1, n, endpoint=endpoint))

测试:

values = density_space(
[0, 100, 101, 200],
[1, 1, 2, 2],
n=12, endpoint=True)
print(np.around(values))
[  0.  27.  54.  82. 105. 118. 132. 146. 159. 173. 186. 200.]

累积密度函数是使用梯形积分创建的,梯形积分基本上基于线性插值。高阶积分是不安全的,因为输入可能有(近(不连续性,例如示例中从 x=100 跳到 x=101。输入中的不连续性会导致累积密度函数中的一阶导数不连续(代码中的cps(,这将导致平滑插值(2阶或以上(的问题。因此,建议仅将 order=2 用于平滑密度函数 - 而不是使用任何更高的阶数。

最新更新