str*_*r18 10 python numpy pandas
我正在尝试实现一个标识Pandas中第一次连续出现的函数,该函数Series已经被我想要的条件掩盖了:(例如)
[True, True, True, False, True, False, True, True, True, True]
我希望上面的输入给出结果3,即True从系列的开头连续出现3 次.
我知道一个大for循环可以完成这项工作,但有没有任何矢量化/以熊猫为中心的方式来解决它?
非常感谢你.
piR*_*red 10
找到第一个连续True的计数
考虑a
a = np.array([True, True, True, False, True, False, True, True, True, True])
Run Code Online (Sandbox Code Playgroud)
答案1
numpy:使用np.logical_and.accumulate否定a并否定它来制作一个掩码,False如果它们存在则消除第一系列的s.然后False在末尾添加一个以确保我们有一个非True最小值.最后,用于np.argmin定位第一个最小值.如果找到了一个位置3,那么它将指示3 True它之前的值.
np.argmin(np.append(a[~np.logical_and.accumulate(~a)], False))
3
Run Code Online (Sandbox Code Playgroud)
答案2
numba.njit
我想使用,numba所以我可以循环并确保在需要时需要进行短路.这是一个肯定会在阵列的早期回答的问题.没有必要无缘无故地评估整个阵列中的事物.
from numba import njit
@njit
def first_true(a):
true_started = False
c = 0
for i, j in enumerate(a):
if true_started and not j:
return c
else:
c += j
true_started = true_started or j
return c
first_true(a)
3
Run Code Online (Sandbox Code Playgroud)
回答3
numpy更聪明地使用argmin和argmax.我周围a有False再利用argmax找到的第True然后从这一点上来说,使用argmin找到第一个False之后.
注意: @Divakar对此答案进行了改进,取消了使用np.concatenate和使用if/then/else.这削减了这个已经非常快速的解决方案3!
def first_true2(a):
a = np.concatenate([[False], a, [False]])
return np.argmin(a[np.argmax(a):])
first_true2(a)
3
Run Code Online (Sandbox Code Playgroud)
这些答案有多快?
请参阅@Divakar的答案,了解正在计时的其他功能的源代码
%timeit first_true(a)
%timeit np.argmin(np.append(a[~np.logical_and.accumulate(~a)], False))
%timeit np.diff(np.flatnonzero(np.diff(np.r_[0,a,0])))[0]
%timeit first_True_island_len(a)
%timeit first_true2(a)
%timeit first_True_island_len_IFELSE(a)
a = np.array([True, True, True, False, True, False, True, True, True, True])
1000000 loops, best of 3: 353 ns per loop
100000 loops, best of 3: 8.32 µs per loop
10000 loops, best of 3: 27.4 µs per loop
100000 loops, best of 3: 5.48 µs per loop
100000 loops, best of 3: 5.38 µs per loop
1000000 loops, best of 3: 1.35 µs per loop
a = np.array([False] * 100000 + [True] * 10000)
10000 loops, best of 3: 112 µs per loop
10000 loops, best of 3: 127 µs per loop
1000 loops, best of 3: 513 µs per loop
10000 loops, best of 3: 110 µs per loop
100000 loops, best of 3: 13.9 µs per loop
100000 loops, best of 3: 4.55 µs per loop
a = np.array([False] * 100000 + [True])
10000 loops, best of 3: 102 µs per loop
10000 loops, best of 3: 115 µs per loop
1000 loops, best of 3: 472 µs per loop
10000 loops, best of 3: 108 µs per loop
100000 loops, best of 3: 14 µs per loop
100000 loops, best of 3: 4.45 µs per loop
Run Code Online (Sandbox Code Playgroud)
使用NumPy函数,一个解决方案是 -
np.diff(np.flatnonzero(np.diff(np.r_[0,s,0])))[0]
Run Code Online (Sandbox Code Playgroud)
样品运行 -
In [16]: s
Out[16]:
0 True
1 True
2 True
3 False
4 True
5 False
6 True
7 True
8 True
9 True
dtype: bool
In [17]: np.diff(np.flatnonzero(np.diff(np.r_[0,s,0])))[0]
Out[17]: 3
Run Code Online (Sandbox Code Playgroud)
为了性能,我们需要使用np.concatenate就地np.r_然后切片来取代最后的差异化 -
def first_True_island_len(a): # a is NumPy array
v = np.concatenate(([False],a,[False]))
idx = np.flatnonzero(v[1:] != v[:-1])
if len(idx)>0:
return idx[1] - idx[0]
else:
return 0
Run Code Online (Sandbox Code Playgroud)
受到@ piRSquared argmax和argmin诡计的启发,这里还有一个有一堆IF-ELSE的 -
def first_True_island_len_IFELSE(a): # a is NumPy array
maxidx = a.argmax()
pos = a[maxidx:].argmin()
if a[maxidx]:
if pos==0:
return a.size - maxidx
else:
return pos
else:
return 0
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1638 次 |
| 最近记录: |