【问题标题】:Apply number ceiling/threshold to pandas dataframe将数字上限/阈值应用于熊猫数据框
【发布时间】:2018-07-23 23:14:14
【问题描述】:

我有一个数据框,其中包含从第 1 天到第 7 天的三个人(John、Terry、Henry)的分数。

        1     2     3     4     5     6      7
John    1.3   2.8   3.0   4.4   2.6   3.1    4.8
Terry   1.1   2.3   4.1   5.5   3.7   2.1    3.8
Henry   0.3   1.0   2.0   3.0   2.7   1.1    2.8

如何设置分数上限,以便一旦分数达到 > 2.5,从那天起的所有分数都设置为 3,无论分数是多少

输出应该是:

        1     2     3     4     5     6      7
John    1.3   3.0   3.0   3.0   3.0   3.0    3.0
Terry   1.1   2.3   3.0   3.0   3.0   3.0    3.0
Henry   0.3   1.0   2.0   3.0   3.0   3.0    3.0

我尝试先应用定义一个函数并使用 np.apply(threshold_1, axis=1) 但它不起作用:

def threshold_1(x):
    if (x > 2.5 & x+1 < 2.5):
        return 3
    if (x > 2.5 & x+1 > 2.5):
        return 3
    else:
        return x

【问题讨论】:

    标签: pandas numpy dataframe lambda apply


    【解决方案1】:

    用途:

    df = df.mask(df.gt(2.5).cumsum(1).gt(0), 3)
    #same as
    #df = df.mask((df > 2.5).cumsum(axis=1) > 0, 3)
    print (df)
             1    2    3    4    5    6    7
    John   1.3  3.0  3.0  3.0  3.0  3.0  3.0
    Terry  1.1  2.3  3.0  3.0  3.0  3.0  3.0
    Henry  0.3  1.0  2.0  3.0  3.0  3.0  3.0
    

    详情

    首先通过2.5比较所有值gt

    print (df.gt(2.5))
               1      2      3     4     5      6     7
    John   False   True   True  True  True   True  True
    Terry  False  False   True  True  True  False  True
    Henry  False  False  False  True  True  False  True
    

    然后通过axis=1按列获取cumsum

    print (df.gt(2.5).cumsum(axis=1))
           1  2  3  4  5  6  7
    John   0  1  2  3  4  5  6
    Terry  0  0  1  2  3  3  4
    Henry  0  0  0  1  2  2  3
    

    并通过eq0进行比较:

    print (df.gt(2.5).cumsum(axis=1).gt(0))
               1      2      3     4     5     6     7
    John   False   True   True  True  True  True  True
    Terry  False  False   True  True  True  True  True
    Henry  False  False  False  True  True  True  True
    

    最后将Trues 替换为3mask

    print (df.mask(df.gt(2.5).cumsum(1).gt(0), 3))
             1    2    3    4    5    6    7
    John   1.3  3.0  3.0  3.0  3.0  3.0  3.0
    Terry  1.1  2.3  3.0  3.0  3.0  3.0  3.0
    Henry  0.3  1.0  2.0  3.0  3.0  3.0  3.0 
    

    为了提高性能,可以使用numpy

    a = df.values
    df1 = pd.DataFrame(np.where(np.cumsum(a > 2.5, axis=1) > 0, 3, a), 
                       index=df.index,
                       columns=df.columns)
    print (df1)
    
             1    2    3    4    5    6    7
    John   1.3  3.0  3.0  3.0  3.0  3.0  3.0
    Terry  1.1  2.3  3.0  3.0  3.0  3.0  3.0
    Henry  0.3  1.0  2.0  3.0  3.0  3.0  3.0
    

    【讨论】:

    • 是否可以不将所有值屏蔽为 3,而只是固定该值?因此,对于第 3 天的“Terry”,从第 3 天开始的值将固定为 4.1。我尝试用“df”替换“3”,但它不起作用:df.mask(df.gt(2.5).cumsum(1).gt(0), df)
    • 我认为最好的方法是创建新问题,我认为可以得到更好的答案。
    • 已经在这里提出了一个新问题:stackoverflow.com/questions/48811596/…
    【解决方案2】:

    我们可以使用idxmax

    s=df.gt(2.5).idxmax(1)
    for x in list(range(len(s))):
        df.loc[s.index[x],s[x]:]=3
    
    df
    Out[585]: 
             1    2    3    4    5    6    7
    John   1.3  3.0  3.0  3.0  3.0  3.0  3.0
    Terry  1.1  2.3  3.0  3.0  3.0  3.0  3.0
    Henry  0.3  1.0  2.0  3.0  3.0  3.0  3.0
    

    【讨论】:

      猜你喜欢
      • 2018-11-13
      • 1970-01-01
      • 2018-11-19
      • 1970-01-01
      • 2019-02-07
      • 2013-08-10
      • 2021-02-12
      • 1970-01-01
      相关资源
      最近更新 更多