有没有一种方法可以创建具有线性细分的对数刻度,并且列表和 numpy 之间的转换较少?将列表视为数组时,多次更改会导致错误,反之亦然。
def log_linsub(start, end):
'Creates a log scale from 10**start to 10**end with linear subdivisions.'
base = np.array(range(1, 10))
seq = [base*10**val for val in range(start, end)]
seq = list(np.array(seq).flatten())
seq.append(10**end)
return np.array(seq)
def log_linsub(start, end):
"Creates a log scale from 10**start to 10**end with linear subdivisions."
return np.unique(
[
base * 10**val
for val in range(start, end)
for base in range(1, 11)
]
)
解释一些重构:
range(1, 10)
和 range(start, end)
进行了迭代,因此可以将其更改为列表理解,使其更加清晰和Pythonic;start=1, end=3
处有 100 和 1000 个值,但您可以使用 np.unique (如果需要 np.array)或 set(...)
使用 numpy 可以非常轻松(快速)地完成此操作。
def log_linsub(start, end):
a = np.arange(start, end)[:,None]
b = np.arange(1, 10)
c = 10**a*b
return c.ravel()
为了清楚起见,以下是调用
log_linsub(1, 5)
时的中间体:
a
[[1]
[2]
[3]
[4]]
b
[1 2 3 4 5 6 7 8 9]
c
[[ 10 20 30 40 50 60 70 80 90]
[ 100 200 300 400 500 600 700 800 900]
[ 1000 2000 3000 4000 5000 6000 7000 8000 9000]
[10000 20000 30000 40000 50000 60000 70000 80000 90000]]
速度测试:
>>> %timeit log_linsub_original(1, 5)
10.3 µs ± 621 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
>>> %timeit log_linsub_original(1, 1000)
3.89 ms ± 8.54 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> %timeit log_linsub_tiov4d3r(1, 5)
13.1 µs ± 288 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
>>> %timeit log_linsub_tiov4d3r(1, 1000)
11.7 ms ± 33.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> %timeit log_linsub_mine(1, 5)
3.23 µs ± 11 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
>>> %timeit log_linsub_mine(1, 1000)
18.2 µs ± 137 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
因此,小输入的速度大约快 3 倍,大输入的速度大约快 200 倍。