首页 > 解决方案 > Pandas,按行计算,第一个值满足条件

问题描述

我有一个数据框:

df = pd.DataFrame(
    [
        [10,20,40],
        [2,1,26],
        [1, 2, 60],
    ], columns = ['f1', 'f2', 'f3']
)

df['cumsum'] = df.sum(axis=1)
df['cumsum_perc'] = (df['cumsum'] * 0.1).astype(int)


|    |   f1 |   f2 |   f3 |   cumsum |   cumsum_perc |
|---:|-----:|-----:|-----:|---------:|--------------:|
|  0 |   10 |   20 |   40 |       70 |             7 |
|  1 |    2 |    1 |   26 |       29 |             2 |
|  2 |    1 |    2 |   60 |       63 |             6 |

正如你所看到的,对于每一行,我计算了累积总和,而不是累积总和的任意(在本例中为 10%)百分比的累积总和。

每个 f 列都有其思考值(f_pon),f1 = 1,f2 = 2,f3 = 3。

现在,对于每一行,我必须找出具有最高值的 f 列,其值小于或等于 cumsum_perc (f_le) 以确定它的 f_pon。

让我们以第三行为例。

f_le = f2 (2 < 6),这意味着 f_pon = 2。

现在我必须看看 cumsum_perc - f_le 列中是否有任何提醒。rem = cumsum_perc (6) - f_le (2) = 4。

考虑到 f_le (f3) 右侧第一个 f 列的值,我必须计算提醒的百分比,所以这里我们有 rem_perc = rem (4) / f3 (60) = 0.066。

第三行的最终结果是 f_pon (2) + rem_perc = 2.066。

如果我们对第一行应用相同的逻辑,那么 f1 就是 f_le,并且没有提醒,因为 cumsum_perc (7) - f_le (10) = -3。如果 rem 是负数,它应该设置为 0。所以结果是 f1_pon (1) + rem (0) / f2 (20) = 1

对于第二行,结果也是 1,因为没有提醒。

如何以最有效的方式计算每一行的最终结果?

标签: python-3.xpandas

解决方案


老实说,很难遵循你的规则,但既然你现在是你的规则,我建议实现一个辅助函数并df.apply(helper, axis=1)明智地使用行。

这可能不是最快的实现,但至少你得到了结果。

def helper(x):
    basic_set = x[['f1','f2','f3']]
    cumsum_perc = x['cumsum_perc']
    f_pon  = basic_set[basic_set<cumsum_perc].max()
    rem = cumsum_perc - f_pon
    if not rem:
        rem = 0
    rem_perc = rem / x['cumsum']
    if not rem_perc:
        rem_perc = 0
    return f_pon + rem_perc
df['ans'] = df.apply(helper, axis=1)

>>> df
   f1  f2  f3  cumsum  cumsum_perc       ans
0  10  20  40      70            7       NaN
1   2   1  26      29            2  1.034483
2   1   2  60      63            6  2.063492

helper如果我的错误,我认为您可以调整。


推荐阅读