【问题标题】:Panda rolling window percentile rank熊猫滚动窗口百分位排名
【发布时间】:2016-08-09 16:57:56
【问题描述】:

我正在尝试在滚动窗口内按列计算数据的百分位排名。

test=pd.DataFrame(np.random.randn(20,3),pd.date_range('1/1/2000',periods=20),['A','B','C'])

test
Out[111]: 
                   A         B         C
2000-01-01 -0.566992 -1.494799  0.462330
2000-01-02 -0.550769 -0.699104  0.767778
2000-01-03 -0.270597  0.060836  0.057195
2000-01-04 -0.583784 -0.546418 -0.557850
2000-01-05  0.294073 -2.326211  0.262098
2000-01-06 -1.122543 -0.116279 -0.003088
2000-01-07  0.121387  0.763100  3.503757
2000-01-08  0.335564  0.076304  2.021757
2000-01-09  0.403170  0.108256  0.680739
2000-01-10 -0.254558 -0.497909 -0.454181
2000-01-11  0.167347  0.459264 -1.247459
2000-01-12 -1.243778  0.858444  0.338056
2000-01-13 -1.070655  0.924808  0.080867
2000-01-14 -1.175651 -0.559712 -0.372584
2000-01-15 -0.216708 -0.116188  0.511223
2000-01-16  0.597171  0.205529 -0.728783
2000-01-17 -0.624469  0.592436  0.832100
2000-01-18  0.259269  0.665585  0.126534
2000-01-19  1.150804  0.575759 -1.335835
2000-01-20 -0.909525  0.500366  2.120933

我尝试将 .rolling 与 .apply 一起使用,但我遗漏了一些东西。

pctrank = lambda x: x.rank(pct=True)
rollingrank=test.rolling(window=10,centre=False).apply(pctrank)

对于 A 列,最终值将是从 2000-01-11 到 2000-01-20 的长度 = 10 窗口内的百分位数 -0.909525。有什么想法吗?

【问题讨论】:

    标签: python pandas apply rank percentile


    【解决方案1】:

    你的 lambda 接收一个 numpy 数组,它没有 .rank 方法——它是 pandas 的 SeriesDataFrame 拥有它。因此,您可以将其更改为

    pctrank = lambda x: pd.Series(x).rank(pct=True).iloc[-1]
    

    或者您可以按照this SO answer 的方式使用纯 numpy:

    def pctrank(x):
        n = len(x)
        temp = x.argsort()
        ranks = np.empty(n)
        ranks[temp] = (np.arange(n) + 1) / n
        return ranks[-1]
    

    【讨论】:

    • 太完美了,正是我想要的。谢谢你。所以我错过了在应用 rank() 之前将 x 定义为熊猫系列。你能解释一下为什么我的 lambda 会收到一个 numpy 数组吗? .rolling() 和 .apply() 都是作用于熊猫数据框“测试”的熊猫函数?
    • 为什么我的 lambda 会收到一个 numpy 数组? 我不知道为什么;我只知道错误说类似“numpy.ndarray has no method rank”。 rolling 是 pandas SeriesDataFrame 的方法。 apply 有几个不同的化身。查看split-apply-combine 文档。
    【解决方案2】:

    最简单的选择是这样做:

    from scipy import stats
    # 200 is the window size
    
    dataset[name] =  dataset[name].rolling(200).apply(lambda x: stats.percentileofscore(x, x[-1]))
    

    【讨论】:

      【解决方案3】:

      如果您只需要最后一次观察的排名,就像滚动应用的情况一样,您可以使用:

       def pctrank(x):
          i = x.argsort().argmax() + 1
          n = len(x)
          return i/n
      

      时间大约快两倍

      【讨论】:

        猜你喜欢
        • 2018-09-02
        • 2022-01-16
        • 2021-01-18
        • 2014-04-15
        • 2017-03-30
        • 2019-12-29
        • 2020-04-21
        • 2021-03-30
        • 1970-01-01
        相关资源
        最近更新 更多