【问题标题】:pandas match date in one df with timeframe in another, then groupby-sum熊猫将一个df中的日期与另一个df中的时间框架匹配,然后是groupby-sum
【发布时间】:2019-04-15 21:53:40
【问题描述】:

我有两个数据框,test1test2。对于test2 中的每个ID 值,我想检查test2 中的date 并将其与ID 中相同ID 值的日期范围进行比较@ 。如果test2 中的任何datetest1 的日期范围内,则对amount 列求和,并将该总和分配为test1 中的附加列。

输出:

所以新的test1 df 将有一个列amount_sum 这是test2 中所有金额的总和,其中datetest1 的日期范围内 - 对于@987654339 @

import random
import string

test1 = pd.DataFrame({
    'ID':[''.join(random.choice(string.ascii_letters[0:4]) for _ in range(3)) for n in range(100)],
    'date1':[pd.to_datetime(random.choice(['01-01-2018','05-01-2018','06-01-2018','08-01-2018','09-01-2018'])) + pd.DateOffset(int(np.random.randint(0, 100, 1))) for n in range(100)],
    'date2':[pd.to_datetime(random.choice(['01-01-2018','05-01-2018','06-01-2018','08-01-2018','09-01-2018'])) + pd.DateOffset(int(np.random.randint(101, 200, 1))) for n in range(100)]
})

test2 = pd.DataFrame({
    'ID':[''.join(random.choice(string.ascii_letters[0:4]) for _ in range(3)) for n in range(100)],
    'amount':[random.choice([1,2,3,5,10]) for n in range(100)],
    'date':[pd.to_datetime(random.choice(['01-01-2018','05-01-2018','06-01-2018','08-01-2018','09-01-2018'])) + pd.DateOffset(int(np.random.randint(0, 100, 1))) for n in range(100)]
})

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    用途:

    #outer join both df by ID columns
    df = test1.merge(test2, on='ID', how='outer')
    #filter by range
    df = df[(df.date > df.date1) & (df.date < df.date2)]
    #thank you @Abhi for alternative
    #df = df[df.date.between(df.date1, df.date2, inclusive=False)]
    #aggregate sum
    s = df.groupby(['ID','date1','date2'])['amount'].sum()
    #add new column to test1
    test = test1.join(s, on=['ID','date1','date2'])
    

    示例

    #https://stackoverflow.com/q/21494489
    np.random.seed(123)
    
    #https://stackoverflow.com/a/50559321/2901002
    def gen(start, end, n):
        start_u = start.value//10**9
        end_u = end.value//10**9
    
        return pd.to_datetime(np.random.randint(start_u, end_u, n), unit='s')
    
    n = 10
    test1 = pd.DataFrame({
        'ID':np.random.choice(list('abc'), n),
        'date1': gen(pd.to_datetime('2010-01-01'),pd.to_datetime('2010-03-01'), n).floor('d'),
        'date2':gen(pd.to_datetime('2010-03-01'),pd.to_datetime('2010-06-01'), n).floor('d')
    })
    
    m = 5
    test2 = pd.DataFrame({
        'ID': np.random.choice(list('abc'), m),
        'amount':np.random.randint(10, size=m),
        'date':gen(pd.to_datetime('2010-01-01'), pd.to_datetime('2010-06-01'), m).floor('d')
    })
    

    print (test1)
      ID      date1      date2
    0  c 2010-01-15 2010-05-22
    1  b 2010-02-08 2010-04-16
    2  c 2010-01-24 2010-04-12
    3  c 2010-02-01 2010-04-09
    4  a 2010-01-19 2010-05-20
    5  c 2010-01-27 2010-05-24
    6  c 2010-02-23 2010-03-15
    7  b 2010-01-31 2010-05-09
    8  c 2010-02-23 2010-03-29
    9  b 2010-01-08 2010-03-07
    
    print (test2)
      ID  amount       date
    0  a       4 2010-05-15
    1  b       6 2010-03-26
    2  a       1 2010-01-07
    3  b       5 2010-02-07
    4  a       6 2010-04-13
    
    #outer join both df by ID columns
    df = test1.merge(test2, on='ID', how='outer')
    #filter by range
    df = df[(df.date > df.date1) & (df.date < df.date2)]
    print (df)
       ID      date1      date2  amount       date
    6   b 2010-02-08 2010-04-16     6.0 2010-03-26
    8   b 2010-01-31 2010-05-09     6.0 2010-03-26
    9   b 2010-01-31 2010-05-09     5.0 2010-02-07
    11  b 2010-01-08 2010-03-07     5.0 2010-02-07
    12  a 2010-01-19 2010-05-20     4.0 2010-05-15
    14  a 2010-01-19 2010-05-20     6.0 2010-04-13
    

    #thank you @Abhi for alternative
    #df = df[df.date.between(df.date1, df.date2, inclusive=False)]
    #aggregate sum
    s = df.groupby(['ID','date1','date2'])['amount'].sum()
    #add new column to test1
    test = test1.join(s, on=['ID','date1','date2'])
    print (test)
      ID      date1      date2  amount
    0  c 2010-01-15 2010-05-22     NaN
    1  b 2010-02-08 2010-04-16     6.0
    2  c 2010-01-24 2010-04-12     NaN
    3  c 2010-02-01 2010-04-09     NaN
    4  a 2010-01-19 2010-05-20    10.0
    5  c 2010-01-27 2010-05-24     NaN
    6  c 2010-02-23 2010-03-15     NaN
    7  b 2010-01-31 2010-05-09    11.0
    8  c 2010-02-23 2010-03-29     NaN
    9  b 2010-01-08 2010-03-07     5.0
    

    【讨论】:

    • 如果IDtest2 中出现多次怎么办?外联时金额会加起来吗?
    • @jchaykow - 添加样本数据以供检查
    猜你喜欢
    • 2019-01-20
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 1970-01-01
    • 2017-06-26
    相关资源
    最近更新 更多