滚动百分位函数在列中输出 0?

Posted

技术标签:

【中文标题】滚动百分位函数在列中输出 0?【英文标题】:Rolling Percentile Function outputting 0's in column? 【发布时间】: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)

【问题讨论】:

【参考方案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]”的目的是什么?我知道它返回最后一个值,但是在论坛和代码中的目的是什么?

以上是关于滚动百分位函数在列中输出 0?的主要内容,如果未能解决你的问题,请参考以下文章

为什么此代码在列中输出4321?

Sencha EXT JS datagrid滚动条专门在列上?

在列中显示终端输出以有效地查看更多输出

滚动百分位数 - 熊猫

pyspark 在列上应用函数

多个 if 循环条件并在列中打印输出