【问题标题】:Piece-wise Linear Function from a Pandas SeriesPandas 系列的分段线性函数
【发布时间】:2020-02-05 20:02:30
【问题描述】:

我有许多大熊猫系列的“成本斜率”,它们代表一个线性函数f,以一种痛苦的形式给出。这是一个小得多的例子:

slopes = Series({'-inf': 10, -200: 60, 0: 0, 200: 1, 'inf': 10})

-inf    10
-200    60
0        0
200      1
inf     10

(0, 0) 始终在系列中,并且斜率表示从零开始向任一方向移动时的分段“边际成本”

f(-200) = 12000  # abs(-200) * 60
f(-100) = 6000  # abs(-100) * 60
f(0) = 0
f(100) = 100  # 100 * 1
f(200) = 200  # 200 * 1
f(300) = 1200  # 200 * 1 + (300-200) * 10

由于该系列很大并且被多次调用,我希望将其置于可以使用 Numpy 的 interppiecewise 或 Pandas interpolate 来提高速度而不是构建 for 循环的形式。

我认为piecewise 可能是解决方案,但我不确定如何转换和处理inf?也许有更清洁的方法?

【问题讨论】:

    标签: python pandas numpy linear-interpolation piecewise


    【解决方案1】:

    通过选择使用np.piecewise,您只需将成本斜率区间指定为condlist,并将相应的线性函数表达式指定为funclist,例如:

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.array([-200,-100,0,100,200,300])
    
    condlist = [x<-200,\
                np.logical_and(x>=-200, x<0),\
                x==0,\
                np.logical_and(x>0,x<=200),\
                x>200]
    funclist = [lambda x: 200*60+abs(x+200)*10,\
                lambda x: abs(x)*60,\
                lambda x:0,\
                lambda x: abs(x)*1,\
                lambda x: 200*1+abs(x-200)*10]
    
    f = np.piecewise(x,condlist,funclist)
    

    用给定的点验证实现的正确性,如下:

    np.allclose([12000,6000,0,100,200,1200],f)
    >>> True
    

    绘制更大的范围,比如说x = np.linspace(-500,500,2000),最后给出:

    plt.plot(x, f,'r')
    plt.scatter([-200,-100,0,100,200,300],[12000,6000,0,100,200,1200],s=20,zorder=5)
    

    希望这会有所帮助。

    【讨论】:

    • 有趣,所以 inf/-inf 似乎得到了合理的处理,这对了解很有用,piecewise 可能是这项工作。我不知道如何以编程方式合理地转换那些“condlist”和“funclist”的许多不同系列。
    【解决方案2】:
    import math
    slopes = pd.Series({ -math.inf: 10, -200: 60, 0: 0, 200: 1, 300: 10, math.inf: 10})
    

    根据需要定义成本函数

    def cost_func(x):
        if x[0] < 200:
            return abs(x[0]) * x[1]
        else: 
            return 200 + abs(x[0]-200) * x[1]
    
    slope_df = pd.DataFrame({'value':slopes.index, 'amount':slopes.values}, index = range(slopes.size))
    
    slope_df['cost'] = slope_df[ ['value', 'amount'] ].apply(lambda row: cost_func(row), axis=1)
    print(slope_df)
    

    【讨论】:

      猜你喜欢
      • 2020-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      • 2012-03-14
      相关资源
      最近更新 更多