我有两个数据框,每个数据框包含一个date_from
和一个date_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
的最小值作为新{{{}来对这两个表进行内部联接1}},并且只关注那些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
我也无法使用普通的sql生成此结果。我所知道的一个可能的解决方案是在数据之前和之后使用空间隔“填充” 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
。但这有其自身的问题,所以我想避免篡改df_b
。
感谢所有帮助。谢谢。
答案 0 :(得分:0)
在加入并添加 date_from 和 date_to 变量后,可以使用一条简单的线条来模拟&#39;你之后加入的那种具有预期效果的那种:
df.loc[(df['date_from']<df['date_to']), 'data_b'] = np.NaN
它说&#34; date_from 小于 date_to ,将 data_b 设置为null&#34;。
然后,删除最后一行中的约束,该约束删除其中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']]
如果这不能产生预期的结果,请告诉我!