我有一系列指标a
,如果应复制最后一个1
的索引,则包含0
。否则,当前运行的索引将通过:
即,
a = np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1])
i = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
预期输出
x = np.array([0, 0, 0, 0, 4, 5, 6, 6, 6, 9, 9])
再次:逻辑:
y
a[y] == 0
:返回i[y]
a[y] == 1
:返回i[yy]
,其中yy
为max yy < y: a[yy] == 0
- a
为0
的“上一个上一个索引”。< / LI>
a[0] == 0
。
我设法完成的任何方法都使用递归方法/循环,并且根本没有效率。什么是快速计算方法x
?
答案 0 :(得分:3)
这是一种利用masking
和maximum-accumulation
和np.maximum.accumulate
的矢量化方式 -
i[np.maximum.accumulate(np.where(a==0, np.arange(len(a)), 0))]
另一种说法是 -
i[np.maximum.accumulate(np.arange(len(a)) * (a==0))]
<强>解释强>
为了深入了解这里故事的细节,让我们分解一下步骤 -
1]输入:
In [83]: a = np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1])
...: i = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
...:
2]因此,输入a
为:
In [84]: a
Out[84]: array([0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1])
3]获取覆盖a
:
In [85]: np.arange(len(a))
Out[85]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
4]现在在a为1的位置屏蔽范围数组,为我们留下对应于0的元素:
In [86]: np.arange(len(a)) * (a==0)
Out[86]: array([0, 0, 0, 0, 4, 5, 6, 0, 0, 9, 0])
5]根据需要使用最大累积来创建渐变结构:
In [87]: np.maximum.accumulate(np.arange(len(a)) * (a==0))
Out[87]: array([0, 0, 0, 0, 4, 5, 6, 6, 6, 9, 9])
6]最后使用所需数字的数字索引到i:
In [88]: i[np.maximum.accumulate(np.arange(len(a)) * (a==0))]
Out[88]: array([0, 0, 0, 0, 4, 5, 6, 6, 6, 9, 9])
运行时测试
方法 -
def FranciscoRodriguez(a,i): # @Francisco Rodríguez's soln
x = []
for idx,val in enumerate(a):
if val==0: x.append(i[idx])
elif val==1: x.append(x[-1])
return x
def ThomasGuenet(a,i): # @ThomasGuenet 's soln
x = np.zeros(len(a))
for j, aa in enumerate(a):
if j == 0:
x[j] == aa
elif aa == 1:
x[j] = x[j-1]
else:
x[j] = i[j]
return x
def vectorizedApp1(a,i):
return i[np.maximum.accumulate(np.where(a==0, np.arange(len(a)), 0))]
def vectorizedApp2(a,i):
return i[np.maximum.accumulate(np.arange(len(a)) * (a==0))]
计时 -
让我们平铺给定的样本以创建更大的数据集并测试所有解决方案:
In [78]: a = np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1])
...: i = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
...:
...: a = np.tile(a,100000)
...: i = np.tile(i,100000)
...:
In [79]: %timeit FranciscoRodriguez(a,i)
...: %timeit ThomasGuenet(a,i)
...: %timeit vectorizedApp1(a,i)
...: %timeit vectorizedApp2(a,i)
...:
1 loop, best of 3: 328 ms per loop
1 loop, best of 3: 331 ms per loop
100 loops, best of 3: 6.07 ms per loop
100 loops, best of 3: 6.77 ms per loop
答案 1 :(得分:2)
我采用了这种方法:
a = [0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1]
i = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x = []
for idx,val in enumerate(a):
if val==0: x.append(i[idx])
elif val==1: x.append(x[-1])
这是一个只遍历列表一次的循环,因此没有嵌套循环或递归。这样,时间成本将是O(N),N是a
答案 2 :(得分:0)
为了快速编写代码,我知道你应该使用尽可能少的if
,没有for
(包含while和try / except),预先指定变量,并使用numpy数组。
a = np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1])
i = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
x = np.zeros(len(a))
for j, aa in enumerate(a):
if j == 0:
x[j] == aa
elif aa == 1:
x[j] = x[j-1]
else:
x[j] = i[j]