繁体   English   中英

在Python中,日期间隔与数据左合并

[英]In Python left merge of data with date-intervals

我有两个数据date_to ,每个数据date_to包含一个date_fromdate_to ,分别指示数据的有效间隔,以及一个id ,指示哪些数据属于一起。

from datetime import datetime
import pandas as pd
import numpy as np

df_a = pd.DataFrame({'id' : [1, 1, 1, 1, 2], 
                     'date_from' : [datetime(2012, 1, 1), datetime(2012, 6, 1), 
                                    datetime(2013, 1, 1), datetime(2013, 6, 1),
                                    datetime(2012, 1, 1)],
                     'date_to' : [datetime(2012, 6, 1), datetime(2013, 1, 1), 
                                  datetime(2013, 6, 1), datetime(2014, 1, 1),
                                  datetime(2013, 1, 1)],
                     'data_a' : [1, 2, 3, 4, 5]})

df_b = pd.DataFrame({'id' : [1, 1], 
                     'date_from' : [datetime(2012, 8, 1), datetime(2013, 4,1)], 
                     'date_to' : [datetime(2013, 4,1), datetime(2013, 8, 1)], 
                     'data_b' :['A','B']})

如果我使用date_from的最大值作为新的date_from以及date_to的最小值作为新的date_to进行这两个表的内部date_to ,并且仅保留date_from < date_to那些条目,则得到所需的结果以正确的间隔。

df = pd.merge(df_a, df_b, suffixes=['_a','_b'],on='id', how='inner')
df['date_from'] = df[['date_from_a', 'date_from_b']].max(axis=1)  
df['date_to'] = df[['date_to_a', 'date_to_b']].min(axis=1)
df[['id', 'date_from', 'date_to', 'data_a','data_b']][(df['date_from']<df['date_to'])]

Out[2]: 
   id  date_from    date_to  data_a data_b
2   1 2012-08-01 2013-01-01       2      A
4   1 2013-01-01 2013-04-01       3      A
5   1 2013-04-01 2013-06-01       3      B
7   1 2013-06-01 2013-08-01       4      B

欢呼!

但是,现在出现了困难的部分,我真的不需要内部联接,而需要左联接。 我得到一个左合并重复上述步骤

df = pd.merge(df_a, df_b, suffixes=['_a','_b'],on='id', how='left')
df['date_from'] = df[['date_from_a', 'date_from_b']].max(axis=1)  
df['date_to'] = df[['date_to_a', 'date_to_b']].min(axis=1)
df[['id', 'date_from', 'date_to', 'data_a','data_b']][(df['date_from']<df['date_to'])]
Out[3]: 
   id  date_from    date_to  data_a data_b
2   1 2012-08-01 2013-01-01       2      A
4   1 2013-01-01 2013-04-01       3      A
5   1 2013-04-01 2013-06-01       3      B
7   1 2013-06-01 2013-08-01       4      B
8   2 2012-01-01 2013-01-01       5    NaN

您说的这张图片有什么问题...好吧,在没有重叠间隔的情况下,我也想从df_a获取数据。 基本上我想要这个结果

   id  date_from    date_to  data_a data_b
0   1 2012-01-01 2012-06-01       1    NaN
1   1 2012-06-01 2012-08-01       2    NaN
2   1 2012-08-01 2013-01-01       2      A
3   1 2013-01-01 2013-04-01       3      A
4   1 2013-04-01 2013-06-01       3      B
5   1 2013-06-01 2013-08-01       4      B
6   1 2013-08-01 2014-01-01       4    NaN
7   2 2012-01-01 2013-01-01       5    NaN

我也无法使用纯SQL产生此结果。 我知道的一种可能的解决方案是在数据前后以空白间隔“填充” df_b 但这有其自身的问题,因此我想避免篡改df_b

感谢所有帮助。 谢谢。

联接并添加了date_fromdate_to变量之后,一条简单的行“模拟”您想要的联接类型便具有所需的效果:

df.loc[(df['date_from']<df['date_to']), 'data_b'] = np.NaN

这是说“ date_from小于date_to时 ,请将data_b设置为null”。

然后,删除最后一行中的约束,该约束将删除id在df_b中没有公共键的行。 这是初始化两个数据集之后的最终代码:

df = pd.merge(df_a, df_b, suffixes=['_a','_b'],on='id', how='left')
df['date_from'] = df[['date_from_a', 'date_from_b']].max(axis=1)
df['date_to'] = df[['date_to_a', 'date_to_b']].min(axis=1)
df.loc[(df['date_from']<df['date_to']), 'data_b'] = np.NaN
df[['id', 'date_from', 'date_to', 'data_a','data_b']]

让我知道这是否无法达到预期的效果!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM