我正在尝试用Python重写一些R代码,并且无法通过一些特定的代码。我发现R中的foverlaps
函数在执行基于时间的连接时非常有用,但是在Python3中找不到任何可行的函数。
我正在做的是加入两个数据表,其中一个表中的time
介于另一个表中的start_time
和end_time
之间。两个表的周期不同 - table_A
每秒发生一次,每个时间间隔可以有多个条目,而table_B
每隔0到10分钟会有一个条目,不定期。
这个问题与我提出的问题非常相似: Merge pandas dataframes where one value is between two others
以下代码在R中提供了我想要的输出:
# Add dummy column to use with foverlaps
table_A <- table_A[, dummy := time]
# Set keys
setkey(table_B, x, y, start_time, end_time)
setkey(table_A, x, y, time, dummy)
# Join tables based on time
joined <- foverlaps(table_A, table_B, type = "within", by.x=c("x", "y", "time", "dummy"), by.y=c("x", "y", "start_time", "end_time"), nomatch=0L)[, dummy := NULL]
> head(table_A)
time x y dummy
1: 2016-07-11 11:52:27 4077 1 2016-07-11 11:52:27
2: 2016-07-11 11:52:27 4077 1 2016-07-11 11:52:27
3: 2016-07-11 11:52:27 4077 1 2016-07-11 11:52:27
4: 2016-07-11 11:52:27 4077 1 2016-07-11 11:52:27
5: 2016-07-11 11:52:32 4077 1 2016-07-11 11:52:32
6: 2016-07-11 11:52:32 4077 1 2016-07-11 11:52:32
> head(table_B)
x y start_time end_time
1: 6183 1 2016-07-11 12:00:45 2016-07-11 12:00:56
2: 6183 1 2016-07-11 12:01:20 2016-07-11 12:01:20
3: 6183 1 2016-07-11 12:01:40 2016-07-11 12:03:26
4: 6183 1 2016-07-11 12:04:20 2016-07-11 12:04:40
5: 6183 1 2016-07-11 12:04:55 2016-07-11 12:04:57
6: 6183 1 2016-07-11 12:05:40 2016-07-11 12:05:51
因此,table_A中时间落在start_time和end_time之间的任何行都将与table_B中的相应行连接,给出如下所示的输出。我在Python中尝试了很多不同的东西,但尚未找到解决方案。
从示例数据中可能不明显的一件事是,在同一time
和start_time
s内的end_time
s处出现多个x和y值。
> head(joined)
y x start_time end_time time
1 1 4077 2016-07-11 12:00:45 2016-07-11 12:00:56 2016-07-11 12:00:46
2 1 4077 2016-07-11 12:00:45 2016-07-11 12:00:56 2016-07-11 12:00:46
3 1 4077 2016-07-11 12:00:45 2016-07-11 12:00:56 2016-07-11 12:00:46
4 1 4077 2016-07-11 12:00:45 2016-07-11 12:00:56 2016-07-11 12:00:46
5 1 4077 2016-07-11 12:00:45 2016-07-11 12:00:56 2016-07-11 12:00:46
6 1 4077 2016-07-11 12:00:45 2016-07-11 12:00:56 2016-07-11 12:00:55
答案 0 :(得分:2)
考虑使用pandas.Series.between()
与子集直接合并。合并连接连接列的所有组合,子集保持与时间间隔对齐的行。
df = pd.merge(table_A, table_B, on=['x', 'y'])
df = df[df['time'].between(df['start_time'], df['end_time'], inclusive=True)]
但是,一个重要的项目是您的日期应该作为日期时间类型。目前,您的帖子显示的字符串日期会影响.between()
以上。以下假设美国日期以月份为MM/DD/YYYY
。您可以在文件读取期间转换类型:
dateparse = lambda x: pd.datetime.strptime(x, '%m/%d/%Y %H:%M:%S')
table_A = pd.read_csv('data.csv', parse_dates=[0], date_parser=dateparse, dayfirst=False)
table_B = pd.read_csv('data.csv', parse_dates=[0,1], date_parser=dateparse, dayfirst=False)
或者在阅读之后:
table_A['time'] = pd.to_datetime(table_A['time'], format='%m/%d/%Y %H:%M:%S')
table_B['start_time'], table_B['end_time']=(pd.to_datetime(ser, format='%m/%d/%Y %H:%M:%S') \
for ser in [table_B['start_time'], table_B['end_time']])