热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

熊猫:计算第一个连续的真值

如何解决《熊猫:计算第一个连续的真值》经验,为你挑选了2个好方法。

我正在尝试实现一个标识Pandas中第一次连续出现的函数,该函数Series已经被我想要的条件掩盖了:(例如)

[True, True, True, False, True, False, True, True, True, True]

我希望上面的输入给出结果3,即True从系列的开头连续出现3 次.

我知道一个大for循环可以完成这项工作,但有没有任何矢量化/以熊猫为中心的方式来解决它?

非常感谢你.



1> piRSquared..:
题:

找到第一个连续True的计数
考虑a

a = np.array([True, True, True, False, True, False, True, True, True, True])  

答案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

答案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

回答3
numpy更聪明地使用argminargmax.我周围aFalse再利用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

这些答案有多快?
请参阅@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


您可以大量简化Numba代码.`for bo in bools:count + = x; 如果计数而不是x:return count`.它也快一点.

2> Divakar..:

使用NumPy函数,一个解决方案是 -

np.diff(np.flatnonzero(np.diff(np.r_[0,s,0])))[0]

样品运行 -

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

为了性能,我们需要使用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

受到@ piRSquared argmaxargmin诡计的启发,这里还有一个有一堆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


推荐阅读
author-avatar
手机用户2502939333
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有