首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算级数开始/结束时的零点数

计算级数开始/结束时的零点数
EN

Stack Overflow用户
提问于 2019-08-13 05:40:41
回答 2查看 217关注 0票数 3

我有一个类似的系列:

代码语言:javascript
复制
s = pd.Series([0, 0, 0, 1, 2, 3])
s
Out[00]: 
0    0
1    0
2    0
3    1
4    2
5    0
dtype: int64

我想在这个系列中计算开始和尾随零的数目。所以在这种情况下,我应该得到3作为开始,因为在第一个非零数之前有3个零,而对于尾随零有1个,因为在最后一个非零之后,序列的尾部有一个零。

我到目前为止所做的

到目前为止,我的解决方案是使用累积和。

代码语言:javascript
复制
sum(s.cumsum() == 0) # begenning
np.sum(np.cumsum(s.values[::-1]) == 0) # trailing

但是对于非常大的系列来说,这是非常慢的,特别是尾随零点的计算,我需要一个替代方案。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-08-13 05:48:28

使用numpy.nonzero

代码语言:javascript
复制
import numpy as np

n_rows = len(s)
indices = np.nonzero(s)[0]

if indices.size>0:
    head = indices[0]
    trail = n_rows - indices[-1] -1
else:
    head, trail = n_rows, n_rows
print(head, trail)

输出:

代码语言:javascript
复制
3 1

基准(大约快15倍):

代码语言:javascript
复制
s = np.zeros(100000)
s[30000:50000] +=1
s = pd.Series(s)

%%timeit

n_rows = len(s)
indices = np.nonzero(s)[0]

if indices.size>0:
    head = indices[0]
    trail = n_rows - indices[-1] -1
else:
    head, trail = n_rows, n_rows
# 661 µs ± 8.63 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit

sum(s.cumsum() == 0) # begenning
np.sum(np.cumsum(s.values[::-1]) == 0) # trailing
# 9.39 ms ± 163 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

测试和编辑:对所有零和非零的情况都很好。

票数 5
EN

Stack Overflow用户

发布于 2019-08-13 07:06:31

出于好奇,我检查了另一种简单的熊猫方法,并在一个1.000.000行的系列中测试了这三个版本。

原来克里斯的版本比原来的版本快18倍,比我的熊猫版本快2倍。但请注意,我的熊猫版本与假设相同,即指数是从0开始的连续整数索引(因此.iloc[i]将返回与.loc[i]相同的值),而chris的版本则独立于索引。

代码语言:javascript
复制
def test_pandas_version(s):
    truth=(s!=0)
    idxs= truth.index.where(truth, np.NaN)
    #first_one=idxs.min()
    first_one=truth.idxmax()
    last_one= idxs.max()
    whole_len=   truth.shape[0]
    prefix_len=  first_one
    suffix_le=   whole_len - last_one - 1
    if prefix_len == np.NaN:
        prefix_len= whole_len
        suffix_len= 0
    return (prefix_len, suffix_le)

def test_original_version(s):
    suffix_len = np.sum(np.cumsum(s.values[::-1]) == 0) # begenning
    prefix_len= sum(s.cumsum() == 0) 
    return (prefix_len, suffix_le)

def test_np_version(s):
    n_rows = len(s)
    indices = np.nonzero(s)[0]

    if indices.size>0:
        head = indices[0]
        trail = n_rows - indices[-1] -1
    else:
        head, trail = n_rows, n_rows
    return (head, trail)

for func in [test_np_version, test_pandas_version, test_original_version]:
    before= datetime.now()
    for i in range(100):
        result= func(s1)
    after= datetime.now()
    time_diff= (after-before).total_seconds()
    print(f'result for {func.__name__} was {result} in {time_diff} seconds')
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57471710

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档