首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >熊猫组,然后根据日期范围+/- x-天计算和求和

熊猫组,然后根据日期范围+/- x-天计算和求和
EN

Stack Overflow用户
提问于 2018-08-31 12:12:41
回答 2查看 3.3K关注 0票数 2

我希望在将数据帧分组到特定列之后,获得列的+/- 7天期间的值的计数和值。

示例数据(编辑以反映我的真实数据集):

代码语言:javascript
复制
group  |        date          |   amount
-------------------------------------------
A      |  2017-12-26 04:20:20 |    50000.0
A      |  2018-01-17 00:54:15 |    60000.0
A      |  2018-01-27 06:10:12 |   150000.0
A      |  2018-02-01 01:15:06 |   100000.0
A      |  2018-02-11 05:05:34 |   150000.0
A      |  2018-03-01 11:20:04 |   150000.0
A      |  2018-03-16 12:14:01 |   150000.0
A      |  2018-03-23 05:15:07 |   150000.0
A      |  2018-04-02 10:40:35 |   150000.0

group分组,然后基于date-7 < date < date+7进行和

我想要的结果:

代码语言:javascript
复制
group  |        date          |   amount    |  grouped_sum
-----------------------------------------------------------
A      |  2017-12-26 04:00:00 |    50000.0  |    50000.0
A      |  2018-01-17 00:00:00 |    60000.0  |    60000.0
A      |  2018-01-27 06:00:00 |   150000.0  |   250000.0
A      |  2018-02-01 01:00:00 |   100000.0  |   250000.0
A      |  2018-02-11 05:05:00 |   150000.0  |   150000.0
A      |  2018-03-01 11:00:04 |   150000.0  |   150000.0
A      |  2018-03-16 12:00:01 |   150000.0  |   150000.0
A      |  2018-03-23 05:00:07 |   100000.0  |   100000.0
A      |  2018-04-02 10:00:00 |   100000.0  |   100000.0

实现数据集的快速片段:

代码语言:javascript
复制
group = 9 * ['A']
date = pd.to_datetime(['2017-12-26 04:20:20', '2018-01-17 00:54:15', 
                       '2018-01-27 06:10:12', '2018-02-01 01:15:06', 
                       '2018-02-11 05:05:34', '2018-03-01 11:20:04', 
                       '2018-03-16 12:14:01', '2018-03-23 05:15:07', 
                       '2018-04-02 10:40:35'])
amount = [50000.0, 60000.0, 150000.0, 100000.0, 150000.0, 
          150000.0, 150000.0, 150000.0, 150000.0]
df = pd.DataFrame({'group':group, 'date':date, 'amount':amount})

一点解释:

  • 第二行为40,因为它将2018-01-14和2018-01-15期间A的数据相加。
  • 第四行是30,因为它在2018-01-03 +未来7天内将B的数据相加。
  • 第六行是30,因为它在2018-01-03 + prev 7天内将B的数据相加。

我不知道如何在一段时间内计算和。如果我这样做的话,我也许能做到:

1.为每一行创建显示日期-7和date+7的另一列。

代码语言:javascript
复制
group  |    date     |  amount  |    date-7    |    date+7 
-------------------------------------------------------------
A      |  2017-12-26 |  50000.0 |  2017-12-19  |  2018-01-02
A      |  2018-01-17 |  60000.0 |  2018-01-10  |  2018-01-24

2.计算日期范围之间的金额:df[df.group == 'A' & df.date > df.date-7 & df.date < df.date+7].amount.sum()

3.但这种方法相当繁琐。

编辑(2018-09-01):基于@jezrael答案找到以下方法,该方法对我有效,但只适用于单个组:

代码语言:javascript
复制
t = pd.Timedelta(7, unit='d')
def g(row):
    res = df[(df.created > row.created - t) & (df.created < row.created + t)].amount.sum()
    return res

df['new'] = df.apply(g, axis=1)
EN

回答 2

Stack Overflow用户

发布于 2018-08-31 12:28:02

下面是每个行和每个组的问题需要循环:

代码语言:javascript
复制
t = pd.Timedelta(7, unit='d')

def f(x):
    return x.apply(lambda y: x.loc[x['date'].between(y['date'] - t, 
                                                     y['date'] + t,
                                                     inclusive=False),'amount'].sum() ,axis=1)

df['new'] = df.groupby('group', group_keys=False).apply(f)
print (df)
  group       date  amount   new
0     A 2018-01-01      10  10.0
1     A 2018-01-14      20  40.0
2     A 2018-01-15      20  40.0
3     B 2018-02-03      10  30.0
4     B 2018-02-04      10  30.0
5     B 2018-02-05      10  30.0

感谢@jpp的改进:

代码语言:javascript
复制
def f(x, t):
    return x.apply(lambda y: x.loc[x['date'].between(y['date'] - t, 
                                                     y['date'] + t,
                                                     inclusive=False),'amount'].sum(),axis=1)

df['new'] = df.groupby('group', group_keys=False).apply(f, pd.Timedelta(7, unit='d'))

验证解决方案:

代码语言:javascript
复制
t = pd.Timedelta(7, unit='d')


df = df[df['group'] == 'A']

def test(y):
    a = df.loc[df['date'].between(y['date'] - t,  y['date'] + t,inclusive=False)]
    print (a)
    print (a['amount'])
    return a['amount'].sum()

  group       date  amount
0     A 2018-01-01      10
0    10
Name: amount, dtype: int64
  group       date  amount
1     A 2018-01-14      20
2     A 2018-01-15      20
1    20
2    20
Name: amount, dtype: int64
  group       date  amount
1     A 2018-01-14      20
2     A 2018-01-15      20
1    20
2    20
Name: amount, dtype: int64

df['new'] = df.apply(test,axis=1)
print (df)
  group       date  amount  new
0     A 2018-01-01      10   10
1     A 2018-01-14      20   40
2     A 2018-01-15      20   40
票数 5
EN

Stack Overflow用户

发布于 2018-08-31 12:50:52

添加列和一周中的第一天:

代码语言:javascript
复制
df['week_start'] = df['date'].dt.to_period('W').apply(lambda x: x.start_time)

结果:

代码语言:javascript
复制
  group       date  amount week_start
0     A 2018-01-01      10 2017-12-26
1     A 2018-01-14      20 2018-01-09
2     A 2018-01-15      20 2018-01-09
3     B 2018-02-03      10 2018-01-30
4     B 2018-02-04      10 2018-01-30
5     B 2018-02-05      10 2018-01-30

按新列分组并查找每周总金额:

代码语言:javascript
复制
grouped_sum = df.groupby('week_start')['amount'].sum().reset_index()

结果:

代码语言:javascript
复制
  week_start  amount
0 2017-12-26      10
1 2018-01-09      40
2 2018-01-30      30

week_start上合并数据

代码语言:javascript
复制
pd.merge(df.drop('amount', axis=1), grouped_sum, on='week_start').drop('week_start', axis=1)

结果:

代码语言:javascript
复制
  group       date  amount
0     A 2018-01-01      10
1     A 2018-01-14      40
2     A 2018-01-15      40
3     B 2018-02-03      30
4     B 2018-02-04      30
5     B 2018-02-05      30
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52115239

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档