【问题标题】:Iterate over rows and apply function based on conditions in existing dataframe columns根据现有数据框列中的条件迭代行并应用函数
【发布时间】:2020-02-17 19:52:08
【问题描述】:

我有以下脚本:

df = pd.DataFrame()
df["Stake"]=[0.25,0.15,0.26,0.30,0.10,0.40,0.32,0.11,0.20,0.25]
df["Odds"]=[2.5,4.0,1.75,2.2,1.85,3.2,1.5,1.2,2.15,1.65]
df["Ftr"]=["H","D","A","H","H","A","D","H","H","A"]
df["Ind"]=[1,2,2,1,3,3,3,1,2,2]

导致:

    Stake   Odds    Ftr Ind
0   0.25    2.50    H   1
1   0.15    4.00    D   2
2   0.26    1.75    A   2
3   0.30    2.20    H   1
4   0.10    1.85    H   3
5   0.40    3.20    A   3
6   0.32    1.50    D   3
7   0.11    1.20    H   1
8   0.20    2.15    H   2
9   0.25    1.65    A   2

我想创建两个额外的列“开始余额”和“结束余额”。索引 0 中的“开始余额”等于 1000。“结束余额”总是等于:

"Start Balance" - "Stake" * "Start Balance" + "Stake" x "Start Balance" x "Odds" if column "Ftr" = "H".

或者,

"Start Balance" - "Stake" * "Start Balance" if column "Ftr" different than "H".

然后下一个索引“起始余额”变为前一个索引“结束余额”。例如,索引 0 中的“结束余额”变为索引 1 中的“开始余额”。

为了让事情变得更复杂一点,“开始平衡”应该考虑另外一个条件。如果“Ind”列与 1 不同,例如 2,则两行(索引 1 和 2)的“开始余额”等于索引 0 中的“结束余额”。同样,如果“Ind”为 3,则所有索引(4,5,6) 的“起始余额”应等于索引 3 中的“结束余额”。预期结果为:

    Stake   Odds    Ftr Ind Start Balance   End Balance
0   0.25    2.5      H   1     1000.0          1375.0
1   0.15     4       D   2     1375.0          1168.8
2   0.26    1.75     A   2     1375.0          1017.5
3   0.3     2.2      H   1     1017.5          1383.8
4   0.1     1.85     H   3     1383.8          1501.4
5   0.4     3.2      A   3     1383.8           830.3
6   0.32    1.5      D   3     1383.8           941.0
7   0.11    1.2      H   1      941.0           961.7
8   0.2     2.15     H   2      961.7          1182.9
9   0.25    1.65     A   2      961.7           721.3

我没有尝试过任何事情,因为我真的不知道如何处理这么多条件:)。干杯

【问题讨论】:

    标签: python pandas if-statement lambda


    【解决方案1】:

    我想不出一个矢量化函数来做你想做的事,所以 for 循环是我能想到的唯一解决方案:

    # A temp dataframe to keep track of the End Balance by Ind
    # It's empty to start
    tmp = pd.DataFrame(columns=['index', 'End Balance']).rename_axis('ind')
    
    for index, row in df.iterrows():
        stake, odds, ind = row['Stake'], row['Odds'], row['Ind']
    
        if index == 0:
            start_balance = 1000
        elif row['Ind'] == 1:
            start_balance = df.loc[index - 1, 'End Balance']
        else:
            start_balance = tmp.query('ind != @ind').sort_values('index')['End Balance'].iloc[-1]
    
        end_balance = start_balance * (1 - stake + stake * odds) if row['Ftr'] == 'H' else start_balance * (1 - stake)
    
        # Keep track of when the current Ind last occurs
        tmp.loc[ind, ['index', 'End Balance']] = [index, end_balance]
    
        df.loc[index, 'Start Balance'] = start_balance
        df.loc[index, 'End Balance'] = end_balance
    

    结果:

       Stake  Odds Ftr  Ind  Start Balance  End Balance
    0   0.25  2.50   H    1    1000.000000  1375.000000
    1   0.15  4.00   D    2    1375.000000  1168.750000
    2   0.26  1.75   A    2    1375.000000  1017.500000
    3   0.30  2.20   H    1    1017.500000  1383.800000
    4   0.10  1.85   H    3    1383.800000  1501.423000
    5   0.40  3.20   A    3    1383.800000   830.280000
    6   0.32  1.50   D    3    1383.800000   940.984000
    7   0.11  1.20   H    1     940.984000   961.685648
    8   0.20  2.15   H    2     961.685648  1182.873347
    9   0.25  1.65   A    2     961.685648   721.264236
    

    【讨论】:

    • 事实上,这不是一个错误,而是让我为此苦苦挣扎的条件之一。如果“Ind”列与 1 不同,例如 2,则出现 2 的两行的“起始余额”应等于 2s 之前行中的最终余额。在示例中,索引 1 和 2 的“起始余额”应为索引 0 的“结束余额”。同样,如果“Ind”列为 3,则所有为 3 的行的“起始余额”应等于“结束余额” 3s 之前的行(来自表格 - 索引 4、5、6 的“开始余额”应等于索引 3 中的“结束余额”)。
    • 你提供的解决方案非常接近,但还没有:),谢谢
    • 让我看看我是否正确理解了您的问题:如果Ind == 1,则开始余额 = 上一行的结束余额。如果Ind == 2,则开始余额 = 最后一行与Ind != 2 的结束余额。如果Ind == 3,则开始余额 = 最后一行的结束余额与Ind != 3?你是这个意思吗?
    • 正是我的意思,是的
    • 它只需要在循环中进行一些小的修改。查看我编辑的答案
    猜你喜欢
    • 2019-07-08
    • 1970-01-01
    • 2021-09-29
    • 2019-10-09
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2022-11-17
    相关资源
    最近更新 更多