滚动百分位函数在列中输出 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?的主要内容,如果未能解决你的问题,请参考以下文章