我有一个数据框,其中有两列包含日期范围。
原始数据如下:
df1:
personid, visitto, intime, outtime
8, 8, 2017-07-01 06:00:00, 2017-07-01 08:00:00
17 8, 2017-07-02 09:00:00, 2017-07-02 10:00:00
df2:
location, open, close
8, 2017-07-01 04:00:00, 2017-07-01 13:00:00
这是我到目前为止所做的: 1.在visitto-> location
上合并两个数据框merged_df:
personid, visitto, intime, outtime, location, open, close
8, 8, 2017-07-01 06:00:00, 2017-07-01 08:00:00, 8, 2017-07-01 04:00:00, 2017-07-01 13:00:00
17 8, 2017-07-02 09:00:00, 2017-07-02 10:00:00, 8, 2017-07-01 04:00:00, 2017-07-01 13:00:00
personid, visitto, visittime, opentime
8, 8, [2017-07-01 06:00:00, 2017-07-01 08:00:00], [2017-07-01 04:00:00, 2017-07-01 13:00:00]
17 8, [2017-07-02 09:00:00, 2017-07-02 10:00:00], [2017-07-01 04:00:00, 2017-07-01 13:00:00]
我现在想过滤此合并的间隔数据框,以仅返回日期时间重叠的行。我的预期结果将是:
personid, visitto, visittime, opentime
8, 8, [2017-07-01 06:00:00, 2017-07-01 08:00:00], [2017-07-01 04:00:00, 2017-07-01 13:00:00]
我成功地使用iterrows()并逐行比较了重叠部分,从而获得了理想的结果,但是,这非常冗长。我想做的是这样的(非工作示例):
merged_df.loc[merged_df['visittime'].overlaps(merged_df['opentime'])]
或者,在合并数据帧期间完成此操作。 (不起作用的例子):
merge_df = pd.merge(df1[["personid", "visitto", "intime", "outtime"]], df2[["location", "open", "close"]], how='inner', left_on='visitto', right_on='location') #WHERE intime, outtime OVERLAPS open, close
是否可以通过熊猫功能而不是循环执行此操作?这可以通过数据库中的Sql轻松完成,但是,我正在努力寻找一种有效的方法来对数据框执行此操作。
答案 0 :(得分:1)
使用内置的熊猫list
功能(以及来自的答案),而不是创建您总是要反复遍历的复合对象列(如datetime
s)。 here):
from io import StringIO
import pandas as pd
csv_buff = StringIO("""personid,visitto,intime,outtime,location,open,close
8,8,2017-07-01 06:00:00,2017-07-01 08:00:00,8,2017-07-01 04:00:00,2017-07-01 13:00:00
17,8,2017-07-02 09:00:00,2017-07-02 10:00:00, 8,2017-07-01 04:00:00,2017-07-01 13:00:00""")
csv_buff.seek(0)
dtypes = {
"intime": "datetime64",
"outtime": "datetime64",
"open": "datetime64",
"close": "datetime64"
}
df = pd.read_csv(csv_buff).astype(dtypes)
df[(df["intime"] <= df["close"]) & (df["open"] <= df["outtime"])]
结果:
personid visitto intime outtime location open close
0 8 8 2017-07-01 06:00:00 2017-07-01 08:00:00 8 2017-07-01 04:00:00 2017-07-01 13:00:00
答案 1 :(得分:0)
虽然从根本上来说仍然是一个循环,但这确实可以实现。
PORT 80
答案 2 :(得分:0)
如果可以将false
与大熊猫一起使用:
IntervalIndex
答案 3 :(得分:0)
我假设所有“时间”列都是 datetime 类型。
从将两个时间都转换为 Interval 并删除 (现在是多余的)源时间列(在两个DataFrame中):
df1['visittime'] = df1.apply(lambda row: pd.Interval(
row.intime, row.outtime, closed='both'), axis=1)
df1.drop(columns=['intime', 'outtime'], inplace=True)
df2['opentime'] = df2.apply(lambda row: pd.Interval(
row.open, row.close, closed='both'), axis=1)
df2.drop(columns=['open', 'close'], inplace=True)
注意:如果由于某种原因需要“原始”时间列, 不要丢下它们。
然后合并它们并过滤掉“错误”的行:
df3 = df1.merge(df2, left_on='visitto', right_on='location')
df3 = df3[df3.apply(lambda row: row.visittime.overlaps(row.opentime), axis=1)]
没有循环或行迭代,只需调用 Pandas 方法。