【问题标题】:what's the inverse of the quantile function on a pandas Series?熊猫系列的分位数函数的倒数是什么?
【发布时间】:2014-12-16 19:43:11
【问题描述】:

分位数函数为我们提供给定熊猫系列的分位数s

例如

s.quantile(0.9) 是 4.2

是否有逆函数(即累积分布)找到 x 的值使得

s.quantile(x)=4

谢谢

【问题讨论】:

    标签: python pandas quantile


    【解决方案1】:

    我和你有同样的问题!我找到了一种使用 scipy 获得分位数倒数的简单方法。

    #libs required
    from scipy import stats
    import pandas as pd
    import numpy as np
    
    #generate ramdom data with same seed (to be reproducible)
    np.random.seed(seed=1)
    df = pd.DataFrame(np.random.uniform(0,1,(10)), columns=['a'])
    
    #quantile function
    x = df.quantile(0.5)[0]
    
    #inverse of quantile
    stats.percentileofscore(df['a'],x)
    

    【讨论】:

    • 值得注意的是,如果您的系列中有 NaN 值,则分数函数的分位数和百分位数似乎不会以相同的方式对待它们,即这些函数彼此并不完全相反。
    • 请注意,当分位数与某个值不精确对齐时,pandas 插值会导致结果不一致;例如,尝试quantile(0.51),反之亦然。
    • 只做 y = stats.percentileofscore(df['a'].dropna(), x) 得到与 df['a].quantile(y) == x 匹配的逆
    【解决方案2】:

    排序可能很昂贵,如果您寻找单个值,我猜您最好使用以下方法计算它:

    s = pd.Series(np.random.uniform(size=1000))
    ( s < 0.7 ).astype(int).mean() # =0.7ish
    

    可能有一种方法可以避免 int(bool) 恶作剧。

    【讨论】:

    • 这很聪明。 (s
    • 如何获取多个值,类似于分位数方法?您可以使用 q 参数将 quantile 传递给要计算的分位数列表。
    【解决方案3】:

    从数学上讲,您试图找到CDF 或返回s 小于或等于q 的值或分位数的概率:

    F(q) = Pr[s <= q]
    

    大家可以使用 numpy 试试这个一行代码:

    np.mean(s.to_numpy() <= q)
    

    【讨论】:

    • Imo 使用 mean(x) = sum(x)/len(x) 一个优雅的解决方案需要一点解释:它计算 (sum(x)) 有多少值小于或等于 q并使其成为相对频率 (/len(x))。这是 ECDF 的定义(经验分布函数en.wikipedia.org/wiki/Empirical_distribution_function)。从技术上讲,'s.to_numpy()' 用于将 's' 带入正确的格式(例如,如果 's' 是像 '[1,2,2,3,3]' 这样的列表) - 如果's' 已经是一个熊猫系列 (´s = pd.Series([1,2,2, 3, 3])´),如 OP 中所述。
    • @Qaswed,我认为“mean(x) = sum(x)/len(x) 一个优雅的解决方案需要一点解释是不正确的:它很重要 (sum(x))有多少值小于或等于 q 并使其成为相对频率 (/len(x))。” sum(x) 只是将 x 中的所有元素相加。分布函数将涉及一个指标函数的总和(x 的指标
    【解决方案4】:

    据我所知,没有 1-liner,但您可以使用 scipy 实现这一点:

    import pandas as pd
    import numpy as np
    from scipy.interpolate import interp1d
    
    # set up a sample dataframe
    df = pd.DataFrame(np.random.uniform(0,1,(11)), columns=['a'])
    # sort it by the desired series and caculate the percentile
    sdf = df.sort('a').reset_index()
    sdf['b'] = sdf.index / float(len(sdf) - 1)
    # setup the interpolator using the value as the index
    interp = interp1d(sdf['a'], sdf['b'])
    
    # a is the value, b is the percentile
    >>> sdf
        index         a    b
    0      10  0.030469  0.0
    1       3  0.144445  0.1
    2       4  0.304763  0.2
    3       1  0.359589  0.3
    4       7  0.385524  0.4
    5       5  0.538959  0.5
    6       8  0.642845  0.6
    7       6  0.667710  0.7
    8       9  0.733504  0.8
    9       2  0.905646  0.9
    10      0  0.961936  1.0
    

    现在我们可以看到这两个函数是互逆的。

    >>> df['a'].quantile(0.57)
    0.61167933268395969
    >>> interp(0.61167933268395969)
    array(0.57)
    >>> interp(df['a'].quantile(0.43))
    array(0.43)
    

    interp 还可以接收列表、numpy 数组或 pandas 数据系列,真的是任何迭代器!

    【讨论】:

      【解决方案5】:

      刚刚遇到同样的问题。这是我的两分钱。

      def inverse_percentile(arr, num):
          arr = sorted(arr)
          i_arr = [i for i, x in enumerate(arr) if x > num]
      
          return i_arr[0] / len(arr) if len(i_arr) > 0 else 1
      

      【讨论】:

        【解决方案6】:

        s 中小于 x 的记录的百分比

        # Find the percentile of `x` in `s`
        (s<x).mean()  # i.e., (s<x).sum()/len(s)
        

        或者,当s 被排序时:

        s.searchsorted(x)/len(s)
        

        另请参阅:pandas.Series.searchsorted

        【讨论】:

          【解决方案7】:

          我使用np.searchsorted 函数“查找应插入元素以保持顺序的索引”

          np.random.seed(seed=1)
          
          #we want to find the 5th 10-tile of a series of 20 elements
          S = 20
          N = 10
          n = 5
          
          df = pd.DataFrame(np.random.uniform(0,1,S), columns=['a'])
          
          #quantile N function
          q = df['a'].quantile(np.arange(0,N+1)/(N))
          
          print(q)
          
          #retrieve the ntile
          x = q.iloc[n]
          
          print('-'*30)
          print(f"the {n}th {N}-tile of the series is: {x}")
          
          #inverse
          print('-'*30)
          print(f"{x} is in the {np.searchsorted(q,x)}th {N}-tile of the series")
          
          #and it works also with a value not present in the series
          x=x+random.uniform(-.2,.2)
          print('-'*30)
          print(f"{x} is in the {np.searchsorted(q,x)}th {N}-tile of the series")
          

          输出:

          0.0    0.000114
          0.1    0.085843
          0.2    0.145482
          0.3    0.194549
          0.4    0.263180
          0.5    0.371164
          0.6    0.417135
          0.7    0.455081
          0.8    0.581045
          0.9    0.688730
          1.0    0.878117
          Name: a, dtype: float64
          ------------------------------
          the 5th 10-tile of the series is: 0.37116410063685884
          ------------------------------
          0.37116410063685884 is in the 5th 10-tile of the series
          ------------------------------
          0.27693796519907005 is in the 5th 10-tile of the series
          

          【讨论】:

            【解决方案8】:

            您可以使用 statsmodels 中的 ECDF 函数。 ECDF 代表经验分布函数,“经验的”指的是它创建的函数是基于在您的数据中观察到的事实。

            假设你有一个系列s

            import pandas as pd
            s = pd.Series(np.random.uniform(size=1000))
            

            您可以在 0.282 处评估 CDF:

            (s <= 0.282).mean()
            

            或者您可以使用 statsmodels 函数创建 ECDF:

            from statsmodels.distributions.empirical_distribution import ECDF
            
            ecdf_s = ECDF(s)
            
            ecdf_s
            
            [ecdf_s(k) for k in [0.282, 0.544, 0.775]]
            
            

            并检查它是否是分位数的倒数:

            s.quantile([0.25, 0.50, 0.75])
            

            【讨论】:

              猜你喜欢
              • 2020-08-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-06-03
              • 1970-01-01
              • 2021-04-14
              • 1970-01-01
              • 2015-06-28
              相关资源
              最近更新 更多