输入:
arange(0.0,0.6,0.2)
输出:
0.,0.4
我想要。
0.,0.2,0.4,0.6
如何使用range或arange函数?如果不行,有什么替代方法吗?
简单的方法是在上限中添加步长,就可以得到所需的输出。例如:
A simpler approach to get the desired output is to add the step size in the upper limit. For instance,
np.arange(start, end + step, step)
这将允许您同时包含终点。在您的情况下:
np.arange(0.0, 0.6 + 0.2, 0.2)
会导致
array([0. , 0.2, 0.4, 0.6]).
end + step
有时会多输出1个值。 - Winandstep = 7.06957358127605; len(np.arange(0, 22050 + step, step))==3121
. But 22050/step==3119.0
- Winandnp.arange(start, end + step/2, step)
。 - undefinedstop
的代码中存在一个错误 - start
不是整数个 step
=> 已修复
意外行为:
>>> np.arange(1, 1.3, .1) # UNEXPECTED
array([1. , 1.1, 1.2, 1.3])
修复:
>>> from arange_cust import *
>>> np_arange_closed(1, 1.3, .1)
array([1. , 1.1, 1.2, 1.3])
>>> np_arange_open(1, 1.3, .1)
array([1. , 1.1, 1.2])
我也遇到过你的问题几次。通常我会通过添加一个小值来快速修复它。正如评论中Kasrâmvd所提到的,问题有点更加复杂,因为在numpy.arange中可能会出现浮点舍入误差(请参见此处和此处)。
在这个例子中可以发现意外行为:
>>> np.arange(1, 1.3, 0.1)
array([1. , 1.1, 1.2, 1.3])
为了澄清一些事情,我决定对np.arange非常小心。
arange_cust.py
:
import numpy as np
def np_arange_cust(
*args, rtol: float=1e-05, atol: float=1e-08, include_start: bool=True, include_stop: bool = False, **kwargs
):
"""
Combines numpy.arange and numpy.isclose to mimic open, half-open and closed intervals.
Avoids also floating point rounding errors as with
>>> np.arange(1, 1.3, 0.1)
array([1., 1.1, 1.2, 1.3])
Parameters
----------
*args : float
passed to np.arange
rtol : float
if last element of array is within this relative tolerance to stop and include[0]==False, it is skipped
atol : float
if last element of array is within this relative tolerance to stop and include[1]==False, it is skipped
include_start: bool
if first element is included in the returned array
include_stop: bool
if last elements are included in the returned array if stop equals last element
kwargs :
passed to np.arange
Returns
-------
np.ndarray :
as np.arange but eventually with first and last element stripped/added
"""
# process arguments
if len(args) == 1:
start = 0
stop = args[0]
step = 1
elif len(args) == 2:
start, stop = args
step = 1
else:
assert len(args) == 3
start, stop, step = tuple(args)
arr = np.arange(start, stop, step, **kwargs)
if not include_start:
arr = np.delete(arr, 0)
if include_stop:
if np.isclose(arr[-1] + step, stop, rtol=rtol, atol=atol):
arr = np.c_[arr, arr[-1] + step]
else:
if np.isclose(arr[-1], stop, rtol=rtol, atol=atol):
arr = np.delete(arr, -1)
return arr
def np_arange_closed(*args, **kwargs):
return np_arange_cust(*args, **kwargs, include_start=True, include_stop=True)
def np_arange_open(*args, **kwargs):
return np_arange_cust(*args, **kwargs, include_start=True, include_stop=False)
为了避免未来出现错误,这里提供一个测试模块。如果我们再次发现问题,让我们添加一个测试用例。test_arange_cust.py
:
import numpy as np
from arange_cust import np_arange_cust, np_arange_closed, np_arange_open
import pytest
class Test_np_arange_cust:
paras_minimal_working_example = {
"arange simple": {
"start": 0, "stop": 7, "step": 1, "include_start": True, "include_stop": False,
"res_exp": np.array([0, 1, 2, 3, 4, 5, 6])
},
"stop not on grid": {
"start": 0, "stop": 6.5, "step": 1, "include_start": True, "include_stop": False,
"res_exp": np.array([0, 1, 2, 3, 4, 5, 6])
},
"arange failing example: stop excl": {
"start": 1, "stop": 1.3, "step": .1, "include_start": True, "include_stop": False,
"res_exp": np.array([1., 1.1, 1.2])
},
"arange failing example: stop incl": {
"start": 1, "stop": 1.3, "step": .1, "include_start": True, "include_stop": True,
"res_exp": np.array([1., 1.1, 1.2, 1.3])
},
"arange failing example: stop excl + start excl": {
"start": 1, "stop": 1.3, "step": .1, "include_start": False, "include_stop": False,
"res_exp": np.array([1.1, 1.2])
},
"arange failing example: stop incl + start excl": {
"start": 1, "stop": 1.3, "step": .1, "include_start": False, "include_stop": True,
"res_exp": np.array([1.1, 1.2, 1.3])
},
}
@pytest.mark.parametrize(
argnames=next(iter(paras_minimal_working_example.values())).keys(),
argvalues=[tuple(paras.values()) for paras in paras_minimal_working_example.values()],
ids=paras_minimal_working_example.keys(),
)
def test_minimal_working_example(self, start, stop, step, include_start, include_stop, res_exp):
res = np_arange_cust(start, stop, step, include_start=include_start, include_stop=include_stop)
assert np.allclose(res, res_exp), f"Unexpected result: {res=}, {res_exp=}"
很有趣,你得到了那个输出结果。当我运行arange(0.0,0.6,0.2)
时,我得到的是:
array([0. , 0.2, 0.4])
无论如何,从 numpy.arange
文档中可以得知:生成的值在半开区间[start, stop)内(也就是包括start但不包括stop)。
同样来自文档:当使用非整数步长(例如0.1)时,结果通常不一致。对于这些情况最好使用numpy.linspace
。
唯一能建议您做的是修改停止参数并添加一个非常小的量,例如:
np.arange(0.0, 0.6 + 0.001 ,0.2)
返回
array([0. , 0.2, 0.4, 0.6])
你期望的输出是什么。
无论如何,最好使用 numpy.linspace
并设置 endpoint=True
。
虽然这是一个老问题,但可以更加简单地实现。
def arange(start, stop, step=1, endpoint=True):
arr = np.arange(start, stop, step)
if endpoint and arr[-1]+step==stop:
arr = np.concatenate([arr,[end]])
return arr
print(arange(0, 4, 0.5, endpoint=True))
print(arange(0, 4, 0.5, endpoint=False))
这提供了
[0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. ]
[0. 0.5 1. 1.5 2. 2.5 3. 3.5]
arange(1, 1.7, 0.1, endpoint=True)
返回的结果是 array([1. , 1.1, 1.2, 1.3, 1.4, 1.5, 1.6])
。 - kadee一个使用np.linspace
的简单例子(其他答案中提到了很多次,但没有简单的示例):
import numpy as np
start = 0.0
stop = 0.6
step = 0.2
num = round((stop - start) / step) + 1 # i.e. length of resulting array
np.linspace(start, stop, num)
>>> array([0.0, 0.2, 0.4, 0.6])
start
不为零时正确计算num
。感谢你的指出。 - David Parksstop
是step
的倍数。在你的例子中,start=4
和stop=9
之间的差为5,这不是stop
的偶数倍。在这种情况下,问题变得更加复杂。我意识到了这一点,但避免尝试创建一个更复杂的答案,因为它与OP的原始问题偏离太远。我认为你可以找到一个解决方案,但这个答案对于那个问题不起作用。它只适用于具有偶数倍数的整数。 - David Parks好的,我会在这里留下这个解决方案。第一步是计算给定边界[a,b]
和step
数量的项数的小数部分。接下来计算一个适当的添加到末尾的量,不会影响结果numpy数组的大小,然后调用np.arrange()
。
import numpy as np
def np_arange_fix(a, b, step):
nf = (lambda n: n-int(n))((b - a)/step+1)
bb = (lambda x: step*max(0.1, x) if x < 0.5 else 0)(nf)
arr = np.arange(a, b+bb, step)
if int((b-a)/step+1) != len(arr):
print('I failed, expected {} items, got {} items, arr-out{}'.format(int((b-a)/step), len(arr), arr))
raise
return arr
print(np_arange_fix(1.0, 4.4999999999999999, 1.0))
print(np_arange_fix(1.0, 4 + 1/3, 1/3))
print(np_arange_fix(1.0, 4 + 1/3, 1/3 + 0.1))
print(np_arange_fix(1.0, 6.0, 1.0))
print(np_arange_fix(0.1, 6.1, 1.0))
输出:
[1. 2. 3. 4.]
[1. 1.33333333 1.66666667 2. 2.33333333 2.66666667
3. 3.33333333 3.66666667 4. 4.33333333]
[1. 1.43333333 1.86666667 2.3 2.73333333 3.16666667
3.6 4.03333333]
[1. 2. 3. 4. 5. 6.]
[0.1 1.1 2.1 3.1 4.1 5.1 6.1]
def np_arange_fix(a, b, step):
b += (lambda x: step*max(0.1, x) if x < 0.5 else 0)((lambda n: n-int(n))((b - a)/step+1))
return np.arange(a, b, step)
np.arange(0, 100e3+1)/100e3
linspace
可以更好地控制终点。 - hpauljlinspace
中,步长不能直接传递(只能返回)。 - Friedrich -- Слава Україні