滚动百分位函数在列中输出 0?
Rolling Percentile Function outputting 0's in column?
在创建函数并使用 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)
或许可以尝试在 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
如果您正在尝试计算百分位数排名,那么您可以尝试类似
的方法
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
您尝试的另一种选择是在您的函数中直接应用 pandas' rank
方法和 pct=True
。这将 运行 百分位数方法直接在滚动 window 定义的子集上。可以这样做:
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
一个 window 传递了 n 个以前的值。例如,如果 window 是三个,则将传递一个 numpy 数组,看起来有点像这样:[1, 15, 27]
。
因此,我们感兴趣的滚动百分比是 x
的最后一个值相对于 window 中包含的值之一。因此,我们在位置 [-1, 1] 处获得该值,该值对应于最后一个值的 rolling
列。
您可以使用 pandas rolling
函数结合 quantile
如下。输入 0 到 1 之间的任何分位数(即您的 percentile/100)。如果你不想开头的是Nans,就把min_periods
设为1。
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)
rolling_percentile=dfgrass.rolling(window=3,min_periods=1,center=False,axis=0).quantile(0.4)
print(rolling_percentile)
给出以下输出:
a b c d
0 1.0 2.0 100.0 4.0
1 6.6 13.2 140.0 122.4
2 12.2 12.4 80.6 240.8
3 24.6 27.0 63.0 380.0
4 25.0 15.0 20.6 324.6
5 322.6 51.0 67.4 39.0
6 163.4 45.4 75.4 20.2
7 161.8 50.6 90.4 36.2
在创建函数并使用 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)
或许可以尝试在 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
如果您正在尝试计算百分位数排名,那么您可以尝试类似
的方法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
您尝试的另一种选择是在您的函数中直接应用 pandas' rank
方法和 pct=True
。这将 运行 百分位数方法直接在滚动 window 定义的子集上。可以这样做:
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
一个 window 传递了 n 个以前的值。例如,如果 window 是三个,则将传递一个 numpy 数组,看起来有点像这样:[1, 15, 27]
。
因此,我们感兴趣的滚动百分比是 x
的最后一个值相对于 window 中包含的值之一。因此,我们在位置 [-1, 1] 处获得该值,该值对应于最后一个值的 rolling
列。
您可以使用 pandas rolling
函数结合 quantile
如下。输入 0 到 1 之间的任何分位数(即您的 percentile/100)。如果你不想开头的是Nans,就把min_periods
设为1。
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)
rolling_percentile=dfgrass.rolling(window=3,min_periods=1,center=False,axis=0).quantile(0.4)
print(rolling_percentile)
给出以下输出:
a b c d
0 1.0 2.0 100.0 4.0
1 6.6 13.2 140.0 122.4
2 12.2 12.4 80.6 240.8
3 24.6 27.0 63.0 380.0
4 25.0 15.0 20.6 324.6
5 322.6 51.0 67.4 39.0
6 163.4 45.4 75.4 20.2
7 161.8 50.6 90.4 36.2