【问题标题】:calculating cumulative geometric mean计算累积几何平均值
【发布时间】:2017-09-28 12:24:07
【问题描述】:

试图创建一个函数来求解向量或数组列的累积几何平均值。

我可以求解整个向量/列的几何平均值。只需执行以下操作:

from scipy import stats
GM=stats.gmean(X)
print(GM)

求解累积算术平均值时,我可以简单地运行 pd.expanding_mean(x) 来获得累积平均值。

有没有我可以运行的函数可以得到与几何平均值相同的结果?

【问题讨论】:

    标签: python pandas numpy scipy mean


    【解决方案1】:

    如果您的系列很小,您可以将expanding().apply 与您已经在使用的 scipy.stats.gmean 一起使用:

    In [26]: s = pd.Series(range(1,10))
    
    In [27]: s.expanding().apply(stats.gmean)
    Out[27]: 
    0    1.000000
    1    1.414214
    2    1.817121
    3    2.213364
    4    2.605171
    5    2.993795
    6    3.380015
    7    3.764351
    8    4.147166
    dtype: float64
    

    但这对于较长的系列来说效率很低:

    In [30]: %time egm = pd.concat([s]*1000).expanding().apply(stats.gmean)
    CPU times: user 6.5 s, sys: 4 ms, total: 6.5 s
    Wall time: 6.53 s
    

    所以你可能想制作一个自定义函数,比如

    def expanding_gmean_log(s):
        return np.exp(np.log(s).cumsum() / (np.arange(len(s))+1))
    

    我们在日志空间中优先于 s.cumprod() ** (1/(np.arange(len(s))+1)) 之类的东西工作,以帮助避免中间产品溢出。

    In [52]: %timeit egm = expanding_gmean_log(pd.concat([s]*1000))
    10 loops, best of 3: 71 ms per loop
    
    In [53]: np.allclose(expanding_gmean_log(pd.concat([s]*1000)),
                         pd.concat([s]*1000).expanding().apply(stats.gmean))
    Out[53]: True
    

    【讨论】:

      【解决方案2】:

      您可以使用 gmean 公式的矢量化实现。例如,

      In [159]: x
      Out[159]: array([10,  5, 12, 12,  2, 10])
      
      In [160]: x.cumprod()**(1/np.arange(1., len(x)+1))
      Out[160]: 
      array([ 10.        ,   7.07106781,   8.43432665,   9.2115587 ,
               6.78691638,   7.23980855])
      

      这是相同的结果,使用 gmean() 和列表推导:

      In [161]: np.array([gmean(x[:k]) for k in range(1, len(x)+1)])
      Out[161]: 
      array([ 10.        ,   7.07106781,   8.43432665,   9.2115587 ,
               6.78691638,   7.23980855])
      

      如果x.cumprod() 可能会溢出,您可以使用 gmean 的对数;请参阅@DSM 的回答。

      【讨论】:

        猜你喜欢
        • 2012-06-19
        • 2016-09-26
        • 1970-01-01
        • 2016-07-11
        • 2021-04-01
        • 2017-11-29
        • 1970-01-01
        相关资源
        最近更新 更多