【问题标题】:Rolling Percentile Function outputting 0's in column?滚动百分位函数在列中输出 0?
【发布时间】:2022-01-18 07:42:48
【问题描述】:

当创建一个函数并使用rolling( ) 和apply( ) 来计算滚动的3 天百分位数分布时,它会在前3 天之后显示0,用于列的其余部分。

我假设具有 NaN 值的前 2 天没有用于计算百分位函数,因此可能将其余列默认为零,并错误地在第三天给出 33 值.但我不确定。

我一直在尝试解决这个问题,但没有任何解决方案。有谁知道为什么以及如何解决下面的正确代码?将不胜感激。

import pandas as pd
import numpy as np
from scipy import stats
data = { 'a': [1, 15, 27, 399, 17, 568, 200, 9], 
         'b': [2, 30, 15, 60, 15, 80, 53, 41],
         'c': [100,200, 3, 78, 25, 88, 300, 91],
         'd': [4, 300, 400, 500, 23, 43, 9, 71]
         }

dfgrass = pd.DataFrame(data)
def percnum(x):
    for t in dfgrass.index:
        aaa = (x<=dfgrass.loc[t,'b']).value_counts()
        ccc = (x<=dfgrass.loc[t, 'b']).values.sum()
        vvv = len(x)
        nnn = ccc/ vvv
        return nnn * 100

dfgrass['e'] = dfgrass['b'].rolling(window=3).apply(percnum)
print(dfgrass)

【问题讨论】:

    标签: python-3.x pandas dataframe rolling-computation percentile


    【解决方案1】:

    您尝试的另一种选择是在您的函数中直接应用带有pct=True 的pandas 的rank 方法。这将直接在滚动窗口定义的子集上运行 percentile 方法。可以这样做:

    def rolling_percentile(x):
        d = pd.DataFrame(x)
        d['rolling'] = d.rank(pct=True)
        return d.iloc[-1, 1]
    

    然后您可以将其插入到您的应用中:

    df['rolling_apply'] = df[column].rolling(window).apply(rolling_percentile)
    

    关于函数的附加说明:还有其他方法可以做到这一点,但在函数中,我在初始数据帧的子集 x 上创建了一个 rolling 列。因为对于每个x,都会传递一个带有 n 个先前值的窗口。例如,如果您的窗口是三个,则将传递一个 numpy 数组,看起来有点像这样:[1, 15, 27]。 因此,我们感兴趣的滚动百分比是x 相对于窗口中包含的值的最后一个值。因此,我们在位置 [-1, 1] 处获得该值,该位置对应于最后一个值的 rolling 列。

    【讨论】:

    • 非常感谢!!! .我有两个问题,(1)在“ d['rolling'] ”的函数中,您是不是要放置新创建的列 df['rolling_apply'] ? (2) 对于“return d.iloc[-1, 1]”,这里的语法是输出 B 列中的最后一个值。但我并不完全清楚它的用途以及它在函数中的工作方式,是将其用作计算列中行的停止点的目的?还是提供其他服务?
    • 是的,对不起,让我在帖子中说清楚:)
    • 让我知道编辑是否有意义
    • 谢谢,这是非常有帮助的澄清。但是我想用这个函数进一步澄清一下。但在我对此发表评论之前,我需要知道您在数据框的函数中放入的数据框“d”的变量是否为 d=pd.DataFrame(x) , d['rolling'], d.rank (pct = true),他们是否假设使用“df”作为数据帧的注意变量?所以它将是 df=pd.DataFrame(x), df=['rolling'], df.rank(pct=True)。如果是这样,您可以编辑答案吗?
    • Fredaroo,您在此处放置的滚动百分比分布函数,在我看来,查看堆栈交换中的所有其他解决方案,您的解决方案在代码行数方面是最有效的,并且最最简单的!,以及仍然使用 rank(pct=True) 方法的好处。这里的几行代码很漂亮,这里的代码杰作!感谢您的明确澄清和帮助!干杯!
    【解决方案2】:

    也许尝试在您的def percnum(x) 实现中将for t in dfgrass.index 更改为for t in x.index,如下所示:

    def percnum(x):
        for t in x.index:
            aaa = (x<=dfgrass.loc[t,'b']).value_counts()
            ccc = (x<=dfgrass.loc[t, 'b']).values.sum()
            vvv = len(x)
            nnn = ccc/ vvv
            return nnn * 100
    

    【讨论】:

    • 谢谢!!,列中的零现在用值填充。但是第一个值 33 % 是一个不正确的值,它仍然存在,并且填充在列中的其余百分比值似乎向后滞后 1 个值,最后 2 行似乎向后滞后 2 个值.当我向后说时,我的意思是例如列中的最后一个值显示百分比 100%,但这是不正确的,因为它是从列中它之前的 2 行中获取值。
    • 您能澄清一下您正在尝试做什么,以及您想要的预期输出是什么?谢谢。
    • 这是一个滚动百分位分布。问题是它给了我错误的价值。上面的代码输出 33 % 作为第一个值,而它应该是 66 %。
    【解决方案3】:

    如果您尝试计算百分位排名,那么您可以尝试类似

    def percnum(x):
        n = len(x)
        temp = x.argsort()
        ranks = np.empty(n)
        ranks[temp] = (np.arange(n) + 1) / n
        return ranks[-1]
    
    dfgrass.rolling(3).apply(percnum)
    

    给出以下输出

              a         b         c         d
    0       NaN       NaN       NaN       NaN
    1       NaN       NaN       NaN       NaN
    2  1.000000  0.666667  0.333333  1.000000
    3  1.000000  1.000000  0.666667  1.000000
    4  0.333333  0.666667  0.666667  0.333333
    5  1.000000  1.000000  1.000000  0.666667
    6  0.666667  0.666667  1.000000  0.333333
    7  0.333333  0.333333  0.666667  1.000000
    

    【讨论】:

    • 但是这里的“返回排名[-1]”的目的是什么?我知道它返回最后一个值,但是在论坛和代码中的目的是什么?
    猜你喜欢
    • 2012-07-19
    • 2022-01-16
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    • 2014-09-06
    • 1970-01-01
    相关资源
    最近更新 更多