Python,高效创建numpy recarray
Python, create numpy recarray efficiently
今天我正在使用这段代码创建一个 numpy recarray。我很确定它可以提高代码效率。但不确定如何。
输入是 t 和 p。每一步都表示多少秒和多少功率。输出是以秒为单位的重新排列。
## New cycle
import numpy as np
t = np.array([30, 60, 60, 60, 120, 120, 150, 600])
p = np.array([0, 200, 300, 400, 350, 50, 400, 0])
time = np.arange(t.sum())
power = np.ones(len(time))
for i in range(len(t)):
if i ==0:
power[0:t[i]] = p[i]
else:
power[t.cumsum()[i-1] : t.cumsum()[i]] = p[i]
listTuples = [(time[i], power[i]) for i in range(len(time))]
inputArray = np.array(listTuples, dtype=[('time', '<f8'), ('PlossTotal', '<f8')])
我认为最简单的方法是:
zip
列出 t
和 p
- 使用 python 的列表乘法为每个幂值创建所需长度的列表(例如 [1] * 5 是 [1, 1, 1, 1, 1])
- 将每个列表转换为 numpy 数组
- 连接(堆叠)所有数组
- 如果您需要元组数组,可以使用
enumerate
获取它
代码:
import numpy as np
t = np.array([30, 60, 60, 60, 120, 120, 150, 600])
p = np.array([0, 200, 300, 400, 350, 50, 400, 0])
res = np.hstack([np.array([ep] * et) for ep, et in zip(p, t)])
res_tuples = = np.array(list(enumerate(res)), dtype=[('time', '<f8'), ('PlossTotal', '<f8')])
您的 time
和 power
数组是:
In [25]: time
Out[25]: array([ 0, 1, 2, ..., 1197, 1198, 1199])
In [26]: power
Out[26]: array([0., 0., 0., ..., 0., 0., 0.])
创建它们的时间:
In [28]: %%timeit
...: for i in range(len(t)):
...: if i ==0:
...: power[0:t[i]] = p[i]
...: else:
...: power[t.cumsum()[i-1] : t.cumsum()[i]] = p[i]
69.2 µs ± 85 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
这是迭代的,所以我怀疑它可以加速,但我现在不会深入细节。 power
全为零这一事实也很可疑。从元组列表创建数组的时间要多得多。
In [29]: %%timeit
...: listTuples = [(time[i], power[i]) for i in range(len(time))]
...: inputArray = np.array(listTuples, dtype=[('time', '<f8'), ('PlossTotal'
...: , '<f8')])
668 µs ± 533 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
另一种填充结构化数组的方法是按字段赋值。由于字段数较少(与记录数相比),这通常更快。
In [32]: arr = np.zeros(time.shape, dtype=[('time', '<f8'), ('PlossTotal'
...: ...: , '<f8')])
In [33]: arr['time'] = time
In [34]: arr['PlossTotal'] = power
In [35]: inputArray==arr
Out[35]: array([ True, True, True, ..., True, True, True])
时间:
In [36]: %%timeit
...: arr = np.zeros(time.shape, dtype=[('time', '<f8'), ('PlossTotal'
...: ...: , '<f8')])
...: arr['time'] = time
...: arr['PlossTotal'] = power
7.53 µs ± 8.59 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
这次,尝试加快速度是值得的 power
。但是由于这些值都是 0,我无法有意义地测试替代方案。
===
In [38]: %%timeit
...: res = np.hstack([np.array([ep] * et) for ep, et in zip(p, t)])
...: res_tuples =np.array(list(enumerate(res)), dtype=[('time', '<f8'), ('Pl
...: ossTotal', '<f8')])
...:
...:
576 µs ± 474 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
今天我正在使用这段代码创建一个 numpy recarray。我很确定它可以提高代码效率。但不确定如何。 输入是 t 和 p。每一步都表示多少秒和多少功率。输出是以秒为单位的重新排列。
## New cycle
import numpy as np
t = np.array([30, 60, 60, 60, 120, 120, 150, 600])
p = np.array([0, 200, 300, 400, 350, 50, 400, 0])
time = np.arange(t.sum())
power = np.ones(len(time))
for i in range(len(t)):
if i ==0:
power[0:t[i]] = p[i]
else:
power[t.cumsum()[i-1] : t.cumsum()[i]] = p[i]
listTuples = [(time[i], power[i]) for i in range(len(time))]
inputArray = np.array(listTuples, dtype=[('time', '<f8'), ('PlossTotal', '<f8')])
我认为最简单的方法是:
zip
列出t
和p
- 使用 python 的列表乘法为每个幂值创建所需长度的列表(例如 [1] * 5 是 [1, 1, 1, 1, 1])
- 将每个列表转换为 numpy 数组
- 连接(堆叠)所有数组
- 如果您需要元组数组,可以使用
enumerate
获取它
代码:
import numpy as np
t = np.array([30, 60, 60, 60, 120, 120, 150, 600])
p = np.array([0, 200, 300, 400, 350, 50, 400, 0])
res = np.hstack([np.array([ep] * et) for ep, et in zip(p, t)])
res_tuples = = np.array(list(enumerate(res)), dtype=[('time', '<f8'), ('PlossTotal', '<f8')])
您的 time
和 power
数组是:
In [25]: time
Out[25]: array([ 0, 1, 2, ..., 1197, 1198, 1199])
In [26]: power
Out[26]: array([0., 0., 0., ..., 0., 0., 0.])
创建它们的时间:
In [28]: %%timeit
...: for i in range(len(t)):
...: if i ==0:
...: power[0:t[i]] = p[i]
...: else:
...: power[t.cumsum()[i-1] : t.cumsum()[i]] = p[i]
69.2 µs ± 85 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
这是迭代的,所以我怀疑它可以加速,但我现在不会深入细节。 power
全为零这一事实也很可疑。从元组列表创建数组的时间要多得多。
In [29]: %%timeit
...: listTuples = [(time[i], power[i]) for i in range(len(time))]
...: inputArray = np.array(listTuples, dtype=[('time', '<f8'), ('PlossTotal'
...: , '<f8')])
668 µs ± 533 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
另一种填充结构化数组的方法是按字段赋值。由于字段数较少(与记录数相比),这通常更快。
In [32]: arr = np.zeros(time.shape, dtype=[('time', '<f8'), ('PlossTotal'
...: ...: , '<f8')])
In [33]: arr['time'] = time
In [34]: arr['PlossTotal'] = power
In [35]: inputArray==arr
Out[35]: array([ True, True, True, ..., True, True, True])
时间:
In [36]: %%timeit
...: arr = np.zeros(time.shape, dtype=[('time', '<f8'), ('PlossTotal'
...: ...: , '<f8')])
...: arr['time'] = time
...: arr['PlossTotal'] = power
7.53 µs ± 8.59 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
这次,尝试加快速度是值得的 power
。但是由于这些值都是 0,我无法有意义地测试替代方案。
===
In [38]: %%timeit
...: res = np.hstack([np.array([ep] * et) for ep, et in zip(p, t)])
...: res_tuples =np.array(list(enumerate(res)), dtype=[('time', '<f8'), ('Pl
...: ossTotal', '<f8')])
...:
...:
576 µs ± 474 ns per loop (mean ± std. dev. of 7 runs, 1,000 loops each)