【发布时间】:2015-07-29 07:16:29
【问题描述】:
短版:我有一个比平常更复杂的合并操作,我想帮助使用 dplyr 或合并进行优化。我已经有很多解决方案,但是这些解决方案在大型数据集上运行速度很慢,我很好奇 R 中是否存在更快的方法(或者在 SQL 或 python 中)
我有两个 data.frames:
- 与 Store 相关的异步事件日志,以及
- 一个表格,提供有关该日志中商店的更多详细信息。
问题:商店 ID 是特定位置的唯一标识符,但商店位置的所有权可能会从一个时期到下一个时期发生变化(为了完整起见,没有两个所有者可能同时拥有同一家商店)。因此,当我合并商店级别信息时,我需要某种条件来合并正确时期的商店级别信息。
可重现的例子:
# asynchronous log.
# t for period.
# Store for store loc ID
# var1 just some variable.
set.seed(1)
df <- data.frame(
t = c(1,1,1,2,2,2,3,3,4,4,4),
Store = c(1,2,3,1,2,3,1,3,1,2,3),
var1 = runif(11,0,1)
)
# Store table
# You can see, lots of store location opening and closing,
# StateDate is when this business came into existence
# Store is the store id from df
# CloseDate is when this store when out of business
# storeVar1 is just some important var to merge over
Stores <- data.frame(
StartDate = c(0,0,0,4,4),
Store = c(1,2,3,2,3),
CloseDate = c(9,2,3,9,9),
storeVar1 = c("a","b","c","d","e")
)
现在,我只想合并Store d.f. 中的信息。记录,如果 Store 在此期间营业(t)。 CloseDate 和StartDate 分别表示该业务运营的最后一个时期和第一时期。 (为了完整性但不太重要,StartDate0 商店在样本之前就已经存在。对于CloseDate9,商店在样本结束时在该位置还没有倒闭。 em>)
一种解决方案依赖于句点t 级别split() 和dplyr::rbind_all(),例如
# The following seems to do the trick.
complxMerge_v1 <- function(df, Stores, by = "Store"){
library("dplyr")
temp <- split(df, df$t)
for (Period in names(temp))(
temp[[Period]] <- dplyr::left_join(
temp[[Period]],
dplyr::filter(Stores,
StartDate <= as.numeric(Period) &
CloseDate >= as.numeric(Period)),
by = "Store"
)
)
df <- dplyr::rbind_all(temp); rm(temp)
df
}
complxMerge_v1(df, Stores, "Store")
从功能上讲,这似乎有效(反正还没有遇到重大错误)。然而,我们正在处理(越来越常见的)数十亿行日志数据。
如果您想将其用于基准测试,我在 sense.io 上制作了一个更大的可重现示例。见这里:https://sense.io/economicurtis/r-faster-merging-of-two-data.frames-with-row-level-conditionals
两个问题:
- 首先,是否有其他方法可以使用运行速度更快的类似方法来解决此问题?
- 在 SQL 和 Python 中是否有一个快速简便的解决方案(我不太熟悉,但如果需要可以依赖)。
- 另外,您能帮我以更笼统、更抽象的方式表达这个问题吗?现在我只知道如何用特定于上下文的术语来讨论问题,但我希望能够用更合适但更通用的编程或数据操作术语来讨论这些类型的问题。
【问题讨论】:
-
在使用
runif等使用随机种子的函数创建可重现示例时,请使用set.seed。
标签: python mysql r merge dplyr