代码之家  ›  专栏  ›  技术社区  ›  darkpool

更新第一组最后一行的列

  •  0
  • darkpool  · 技术社区  · 4 年前

    我有以下数据帧:

    data = {
        "date": {
            0: "2019-02-01",
            2: "2019-02-07",
            3: "2019-02-15",
            5: "2019-02-18",
            12: "2019-03-02",
            17: "2019-03-06",
            19: "2019-03-13",
            21: "2019-03-20",
        },
        "date_month_start": {
            0: "2019-02-01",
            2: "2019-02-01",
            3: "2019-02-01",
            5: "2019-02-01",
            12: "2019-03-01",
            17: "2019-03-01",
            19: "2019-03-01",
            21: "2019-03-01",
        },
        "account": {0: 67, 2: 69, 3: 67, 5: 67, 12: 67, 17: 67, 19: 67, 21: 69,},
        "balance": {
            0: 1705.65,
            2: 1929.49,
            3: 2004.46,
            5: 2595.54,
            12: 4428.41,
            17: 2301.5,
            19: 3089.82,
            21: 3141.19,
        },
        "amount": {0: 0, 2: 0, 3: 0, 5: 0, 12: 0, 17: 0, 19: 0, 21: 0},
        "category__name": {
            0: "aaa",
            2: "aaa",
            3: "bbb",
            5: "aaa",
            12: "aaa",
            17: "bbb",
            19: "aaa",
            21: "aaa",
        },
    }
    df = pd.DataFrame(data)
    df["date"] = pd.to_datetime(df["date"])
    df["date_month_start"] = pd.to_datetime(df["date_month_start"])
    df.sort_values('date', inplace=True)
    

    其结果是:

          date           date_month_start   account   balance   amount   category__name
    0     2019-02-01     2019-02-01         67        1705.65   0        aaa
    2     2019-02-07     2019-02-01         69        1929.49   0        aaa
    3     2019-02-15     2019-02-01         67        2004.46   0        bbb
    5     2019-02-18     2019-02-01         67        2595.54   0        aaa
    12    2019-03-02     2019-03-01         67        4428.41   0        aaa
    17    2019-03-06     2019-03-01         67        2301.50   0        bbb
    19    2019-03-13     2019-03-01         67        3089.82   0        aaa
    21    2019-03-20     2019-03-01         69        3141.19   0        aaa
    

    我需要确定第一个 date_month_start 对于每种组合 account category__name 。然后,对于每个组,我需要设置 amount 最后一行到 balance .

    结果将是:

          date           date_month_start   account   balance   amount   category__name
    0     2019-02-01     2019-02-01         67        1705.65   0        aaa
    2     2019-02-07     2019-02-01         69        1929.49   1929.49  aaa
    3     2019-02-15     2019-02-01         67        2004.46   2004.46  bbb
    5     2019-02-18     2019-02-01         67        2595.54   2595.54  aaa
    12    2019-03-02     2019-03-01         67        4428.41   0        aaa
    17    2019-03-06     2019-03-01         67        2301.50   0        bbb
    19    2019-03-13     2019-03-01         67        3089.82   0        aaa
    21    2019-03-20     2019-03-01         69        3141.19   0        aaa
    

    换言之:

    • 第一个 date_start_month 对于 account = 69 category__name = aaa 2019-02-01 .设置 数量 从该组的最后一行到 平衡 ,即: 1929.49
    • 第一个 日期_开始_月份 对于 account = 67 category__name = bbb 2019-02-01 .设置 数量 从该组的最后一行到 平衡 ,即: 2004.46
    • 第一个 日期_开始_月份 对于 账户=67 category_name=aaa 2019-02-01 .设置 数量 从该组的最后一行到 平衡 ,即: 2595.54

    在这种情况下,最早 日期_月份_开始 在所有情况下都是一样的,但并非总是如此。

    0 回复  |  直到 4 年前
        1
  •  2
  •   jezrael    4 年前

    创建2个面具并链接 & 按位 AND -首先比较以下值 date_month_start 如果匹配所有值,则按组分组,然后按多列测试最后的重复项 DataFrame.duplicated :

    mask1 = (df.groupby(['account','category__name'])['date_month_start'].transform('first')
              .eq(df['date_month_start']))
    mask2 = df.duplicated(['date_month_start','account','category__name'], keep='last')
    
    df['amount'] = df['amount'].mask(mask1 & ~mask2, df['balance'])
    print (df)
             date date_month_start  account  balance   amount category__name
    0  2019-02-01       2019-02-01       67  1705.65     0.00            aaa
    2  2019-02-07       2019-02-01       69  1929.49  1929.49            aaa
    3  2019-02-15       2019-02-01       67  2004.46  2004.46            bbb
    5  2019-02-18       2019-02-01       67  2595.54  2595.54            aaa
    12 2019-03-02       2019-03-01       67  4428.41     0.00            aaa
    17 2019-03-06       2019-03-01       67  2301.50     0.00            bbb
    19 2019-03-13       2019-03-01       67  3089.82     0.00            aaa
    21 2019-03-20       2019-03-01       69  3141.19     0.00            aaa
    
        2
  •  1
  •   alec_djinn    4 年前

    Thy是一个快速而肮脏的实现,只是为了让逻辑正确。这可能有助于人们把注意力集中在这类问题上。 @杰兹雷尔版本是速度之热的出路。

    for i,g in df.groupby(['account','category__name']): 
        date = g.iloc[0]['date_month_start'] 
        same_start_date = g.loc[g.date_month_start == date] 
        last_balance = same_start_date.balance.values[-1] 
        #print(i, date, last_balance) 
        df.at[same_start_date.index[-1], 'amount'] = last_balance 
                                                                                                                                                 
    #(67, 'aaa') 2019-02-01 00:00:00 2595.54
    #(67, 'bbb') 2019-02-01 00:00:00 2004.46
    #(69, 'aaa') 2019-02-01 00:00:00 1929.49
    
    df                                                                                                                                           
             date date_month_start  account  balance  amount category__name
    0  2019-02-01       2019-02-01       67  1705.65       0            aaa
    2  2019-02-07       2019-02-01       69  1929.49    1929            aaa
    3  2019-02-15       2019-02-01       67  2004.46    2004            bbb
    5  2019-02-18       2019-02-01       67  2595.54    2595            aaa
    12 2019-03-02       2019-03-01       67  4428.41       0            aaa
    17 2019-03-06       2019-03-01       67  2301.50       0            bbb
    19 2019-03-13       2019-03-01       67  3089.82       0            aaa
    21 2019-03-20       2019-03-01       69  3141.19       0            aaa