当前位置: 首页 > 知识库问答 >
问题:

合并数据帧并根据开始/结束日期填写空白值

夔桐
2023-03-14

我有一个数据帧(df),它具有特定值(在本例中为“货币”)的开始和结束日期。我需要将其与另一个数据帧(tbl)合并,并根据第一个DF的开始/结束日期填写空白货币行。NULL表示没有结束日期,所以一切都在继续。在这种情况下,2020年11月1日之后的所有费用均为美元。因此,来自SQL的数据为空。

df = pd.DataFrame(data={
        'port': 'PortA'
        'currency': ['USD', 'CAD', 'EUR', 'USD'],
        'start_date': ['01/01/2020', '01/04/2020', '01/06/2020', '01/11/2020'],
        'end_date': ['01/04/2020', '01/06/2020', '01/11/2020', '01/15/2020']
        })
df[['start_date', 'end_date']] = df[['start_date', 'end_date']].apply(pd.to_datetime, errors='ignore')
tbl = pd.DataFrame(data={
        'port': 'PortA',
        'as_of_date': [x for x in pd.date_range(start='01/01/2020', end='01/15/2020')]
        })

这就是我需要的

df_合并是我需要的最终外观。第二个问题-如果我没有第二个数据帧(tbl)来合并怎么办。是否有一种简单的方法“取消堆叠”现有df,使其看起来与df_合并相同?

非常感谢。

共有2个答案

姬康平
2023-03-14

您可以使用pd.date\u rangeexplodemerge这样做:

df_dates = df.assign(dates=[pd.date_range(i, j + pd.Timedelta(days=-1), freq='D') 
                             for i, j in zip(df['start_date'], df['end_date'])])\
             .explode('dates')

bl.merge(df_dates[['port','dates','currency']], 
         left_on=['port', 'as_of_date'], 
         right_on=['port', 'dates'])

输出:

     port as_of_date      dates currency
0   PortA 2020-01-01 2020-01-01      USD
1   PortA 2020-01-02 2020-01-02      USD
2   PortA 2020-01-03 2020-01-03      USD
3   PortA 2020-01-04 2020-01-04      CAD
4   PortA 2020-01-05 2020-01-05      CAD
5   PortA 2020-01-06 2020-01-06      EUR
6   PortA 2020-01-07 2020-01-07      EUR
7   PortA 2020-01-08 2020-01-08      EUR
8   PortA 2020-01-09 2020-01-09      EUR
9   PortA 2020-01-10 2020-01-10      EUR
10  PortA 2020-01-11 2020-01-11      USD
11  PortA 2020-01-12 2020-01-12      USD
12  PortA 2020-01-13 2020-01-13      USD
13  PortA 2020-01-14 2020-01-14      USD

注意: pd.Timedelta(天=-1)处理多行上的重复日期。End_date与下一行start_date重叠。

更改代码以确定最后日期:

d = pd.Timedelta(days=-1)
l = pd.date_range #To shorten typing
df_dates = df.assign(dates=[l(i, j + d) if j != df.iloc[-1, df.columns.get_loc('end_date')] 
                               else l(i, j) for i, j in zip(df['start_date'], df['end_date'])])\
             .explode('dates')

print(tbl.merge(df_dates[['port','dates','currency']], left_on=['port', 'as_of_date'], right_on=['port', 'dates']))
龙俊良
2023-03-14
  1. 首先创建一个as_of_date列与pd.date_range在你的数据框,这是一个列表之间的开始和结束日期每行与lambda x:(删除重复并保持最后以及)。
  2. dateport的合并预置中爆炸as_of_date上的数据帧。
  3. 简单地,合并数据帧(根据次要问题,您可以简单地排除此步骤)。

步骤1:创建日期范围列

df['as_of_date'] = df.apply(lambda x: list(pd.date_range(x['start_date'], x['end_date'], freq='d')), axis=1)
df
Out[1]: 
    port currency start_date   end_date  \
0  PortA      USD 2020-01-01 2020-01-04   
1  PortA      CAD 2020-01-04 2020-01-06   
2  PortA      EUR 2020-01-06 2020-01-11   
3  PortA      USD 2020-01-11 2020-01-15   

                                          as_of_date  
0  [2020-01-01 00:00:00, 2020-01-02 00:00:00, 202...  
1  [2020-01-04 00:00:00, 2020-01-05 00:00:00, 202...  
2  [2020-01-06 00:00:00, 2020-01-07 00:00:00, 202...  
3  [2020-01-11 00:00:00, 2020-01-12 00:00:00, 202...  

步骤2:爆炸数据框并删除重复项

df = df.explode('as_of_date').drop_duplicates('as_of_date', keep='last')
df
Out[2]: 
    port currency start_date   end_date as_of_date
0  PortA      USD 2020-01-01 2020-01-04 2020-01-01
0  PortA      USD 2020-01-01 2020-01-04 2020-01-02
0  PortA      USD 2020-01-01 2020-01-04 2020-01-03
1  PortA      CAD 2020-01-04 2020-01-06 2020-01-04
1  PortA      CAD 2020-01-04 2020-01-06 2020-01-05
2  PortA      EUR 2020-01-06 2020-01-11 2020-01-06
2  PortA      EUR 2020-01-06 2020-01-11 2020-01-07
2  PortA      EUR 2020-01-06 2020-01-11 2020-01-08
2  PortA      EUR 2020-01-06 2020-01-11 2020-01-09
2  PortA      EUR 2020-01-06 2020-01-11 2020-01-10
3  PortA      USD 2020-01-11 2020-01-15 2020-01-11
3  PortA      USD 2020-01-11 2020-01-15 2020-01-12
3  PortA      USD 2020-01-11 2020-01-15 2020-01-13
3  PortA      USD 2020-01-11 2020-01-15 2020-01-14
3  PortA      USD 2020-01-11 2020-01-15 2020-01-15

步骤3:合并两个数据帧(根据您的次要问题-如果您没有tbl数据帧,您可以忽略此步骤。相反,只需运行df=df[['port','as_of_date','currency']]来保留和重新排序所需的列:

df_merge = pd.merge(df[['port', 'currency', 'as_of_date']], tbl, how='left', on=['as_of_date', 'port'])
df_merge
Out[3]: 
     port currency as_of_date
0   PortA      USD 2020-01-01
1   PortA      USD 2020-01-02
2   PortA      USD 2020-01-03
3   PortA      CAD 2020-01-04
4   PortA      CAD 2020-01-05
5   PortA      EUR 2020-01-06
6   PortA      EUR 2020-01-07
7   PortA      EUR 2020-01-08
8   PortA      EUR 2020-01-09
9   PortA      EUR 2020-01-10
10  PortA      USD 2020-01-11
11  PortA      USD 2020-01-12
12  PortA      USD 2020-01-13
13  PortA      USD 2020-01-14
14  PortA      USD 2020-01-15

完整代码

df = pd.DataFrame(data={
        'port': ['PortA','PortA','PortA','PortA'],
        'currency': ['USD', 'CAD', 'EUR', 'USD'],
        'start_date': ['01/01/2020', '01/04/2020', '01/06/2020', '01/11/2020'],
        'end_date': ['01/04/2020', '01/06/2020', '01/11/2020', '01/15/2020']
        })
df[['start_date', 'end_date']] = df[['start_date', 'end_date']].apply(pd.to_datetime, errors='ignore')
tbl = pd.DataFrame(data={
        'port': 'PortA',
        'as_of_date': [x for x in pd.date_range(start='01/01/2020', end='01/15/2020')]
        })
df['as_of_date'] = df.apply(lambda x: list(pd.date_range(x['start_date'], x['end_date'], freq='d')), axis=1)
df = df.explode('as_of_date').drop_duplicates('as_of_date', keep='last')
df_merge = pd.merge(df[['port', 'currency', 'as_of_date']], tbl, how='left', on=['as_of_date', 'port'])
df_merge
 类似资料:
  • 这是我的密码: 我想知道如何将df3绑定到单个数据帧中作为"NA"s? 我在r_blogger上找到了一篇关于将向量或长度不等的数据帧组合成一个数据帧的文章。http://www.r-bloggers.com/r-combining-vectors-or-data-frames-of-unequal-length-into-one-data-frame/ 但是我从数据中得到的数据框,其中一些是空的

  • 我有一个pandas数据帧,如下所示: 我希望将第0行添加到数据帧的末尾,并获得如下所示的新数据帧: 我在熊猫身上能做什么来做到这一点?

  • 我目前有以下数据帧; 我要做的是创建一个如下所示的dataframe; 其中,每当“感情”列中的值为“正”时,就会添加1,每当它为负时,就会从新创建的sentiment_score列中扣除1。最后,数据帧将被聚合成每个日期的股票及其相应的情绪得分。 然而,我的问题是我知道如何在Excel中这样做,但我刚刚开始使用Python,因此对如何在Excel中这样做几乎一无所知。 任何帮助都将非常感谢!

  • 我想使用excel来跟踪多年来我每个月有多少实习生。 有没有一种方法,我可以使用excel列出每个实习生工作的月数,如下所示,以便我能够将我每月有多少实习生放入图表中 感谢您的帮助!提前感谢:)

  • 我有不同的数据帧,需要根据日期列将它们合并在一起。如果我只有两个数据帧,我可以使用,要使用三个数据帧,我可以使用,但是使用多个数据帧会变得非常复杂和不可读。 所有数据帧都有一个公共列-,但它们的行数和列数都不相同,我只需要其中每个日期对每个数据帧都是公共的行。 所以,我试图编写一个递归函数,返回一个包含所有数据的数据帧,但它不起作用。那么我应该如何合并多个数据帧呢? 我尝试了不同的方法,得到了一些