【问题标题】:R foverlaps equivalent in PythonR foverlaps 等效于 Python
【发布时间】:2017-03-07 22:09:52
【问题描述】:

我正在尝试用 Python 重写一些 R 代码,但无法通过特定的代码位。我发现 R 中的 foverlaps 函数在执行基于时间的连接时非常有用,但在 Python3 中没有发现任何可以正常工作的东西。

我正在做的是连接两个数据表,其中一个表中的time 介于另一个表中的start_timeend_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 中尝试了很多不同的东西,但还没有找到解决方案。

从示例数据中可能不明显的一件事是,多个 x 和 y 值出现在同一 start_timeend_times 内的 times 处。

> 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 

【问题讨论】:

  • 是的,我正在使用熊猫。我认为也许 asof 或合并的联接会起作用,但没有运气。我希望得到一些想法,而不是试图解决我可能偏离基础的尝试之一。
  • 您能否提供table_Atable_Bjoined 的示例(假设您为AB 提供的示例)看起来像。有了这个,我可以帮助你......如果其他人没有打败我
  • 一个简单的模拟方法是使用numpy.searchsorted,并将time 数据排序到start_timeend_time 的数组中。根据您的数据结构,start_time 甚至可能不需要使用。
  • 我添加了一些示例数据,虽然很难完全描绘数据集(通常由 1M+ 行和许多列组成)。

标签: python r pandas join bigdata


【解决方案1】:

考虑使用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']])

【讨论】:

  • 进展如何?我运行了您的示例数据,但它返回了一个空数据框,因为没有匹配项,因为 11:52a 早于 12p 之后的记录。
  • 因此,pd.merge 有效,但是仅使用少量数据样本(大约是典型数据集的 1/20),它就创建了一个包含 40M 行的数据框。当我尝试执行子集代码时,它会立即填满我的 16GB 内存并且永远不会完成。 table_A.shape Out[118]: (10961, 25) table_B.shape Out[119]: (3666, 7)joined.shape Out[120]: (40183026, 30)
  • 您可能需要分块进行此处理,例如按特定月份过滤 A 和 B,然后将所有月份连接在一起。您是否在 R 中对这些大型数据集运行了 data.table 的 foverlaps
  • 我在 R 中使用 foverlaps 没有这个问题,我想是因为我从来没有进行完全连接并创建一个巨大的表。如果有足够的内存和时间,理论上这个解决方案应该可以工作,但不幸的是不是我的数据集的解决方案。
  • foverlaps 是 data.table 子宇宙的一部分。因此,预计您会寻找 SQL 引擎的 API。
猜你喜欢
  • 2022-03-03
  • 1970-01-01
  • 2021-12-29
  • 2013-04-26
  • 2015-08-04
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2020-03-18
相关资源
最近更新 更多