基于项目和ID的两列的SUM

时间:2019-08-12 14:46:00

标签: python pandas numpy

当前,我正在寻找基于ID和项目的开始日期的每个项目类型(又称为groupby)的单个ID的30天SUM()。每次出现相同的ID和项目代码时,都应重复此操作。我知道查询可以帮助我按ID和项目获得每月的总和,但是每月的总金额无法回答我的问题。

这是一个示例数据集:

<form onSubmit={this.handleSubmit}>

过去,我尝试过一个基本查询,该查询为我提供了groupby ID和Project,以及每月的SUM()金额。但是,每月进行一次付款并不能回答我的问题。我希望30天的时间范围从首次看到ID和项目开始。

这是我用于每月金额的示例代码。

ID  Project Amount  Start Date
1234    203 29.65   5/29/18
1234    203 2       6/24/18
1234    203 345.34  7/12/18
1234    201 100     7/16/18
1234    203 200     7/16/18
2345    251 3       4/11/17
2345    251 4       4/16/17
2345    203 95.12   8/13/18
2345    203 10      4/12/19
3456    251 50      3/23/18
3456    251 100     3/23/18
3456    251 43.75   6/5/18
df.groupby(['ID', 'Project', pd.Grouper(key='Date', freq='M')])['Amount'].sum()

1 个答案:

答案 0 :(得分:1)

理想的解决方案是使用:

import pandas as pd
import numpy as np

df = pd.read_csv('something.csv')

df['Start Date'] = pd.to_datetime(df['Start Date'], infer_datetime_format=True)
df = df.sort_values(by='Start Date')
new_df1 = (df.groupby(['ID', 'Project', pd.Grouper(key='Start Date', freq='M')]).agg({'Amount':'sum'}))
print(new_df1)

哪个给你:

ID   Project Start Date        
1234 201     2018-07-31  100.00
     203     2017-04-30  200.00
             2018-05-31   29.65
             2018-06-30   52.00
             2018-07-31  645.34
2345 203     2018-08-31   95.12
             2019-04-30   10.00
     251     2017-04-30    7.00
3456 251     2018-03-31  150.00
             2018-06-30   43.75

但是,这与您的值有点差,因为您要添加到6/12/18和6/24/18中的'5/29/18'值实际上不在同一个月内-因此考虑一个独立的值。

如果您要根据“开始日期”列中的日期自定义频率,一种解决方案是根据日期进行排序,将第一个日期用作开始日期,并将其添加30,在其中找到所有值该范围并为其分配一些唯一的“ Period” ID(我将其设置为起始值的索引),然后找到超出范围的第一个值,并将其重新分配为开始并重复该过程。这是一个工作代码,可以产生所需的输出:

import pandas as pd
import numpy as np

df = pd.read_csv('something.csv')

df['Start Date'] = pd.to_datetime(df['Start Date'], infer_datetime_format=True)
df = df.sort_values(by='Start Date')

df['Period'] = np.nan
indices = df.index.values.tolist()
start = indices[0]
for v in range(0, len(indices)):
    if v == 0:
        df['Period'] = start
    else:
        if df['Start Date'].loc[indices[v]] - df['Start Date'].loc[start] < pd.Timedelta(days=30):
            df['Period'].loc[indices[v]] = start
        else:
            df['Period'].loc[indices[v]] = indices[v] 
            start = indices[v]
new_df = (df.groupby(['ID', 'Project', 'Period']).agg({'Amount':'sum'}))
print(new_df)

输出:

ID   Project Period        
1234 201     6       100.00
     203     3        81.65
             6       645.34
             11      200.00
2345 203     9        95.12
             10       10.00
     251     11        7.00
3456 251     3        43.75
             13      150.00