R 如何加速此条件联接(因为循环很慢)?
以下是该问题的数据、代码和解释示例:R 如何加速此条件联接(因为循环很慢)?,r,performance,for-loop,join,R,Performance,For Loop,Join,以下是该问题的数据、代码和解释示例: require(data.table) require(dplyr) df1 <- read.table(text= " col1 col2 col3 col4 col5 123 121 16519 1 4 123 121 16519 2 5 123 121 16518 3
require(data.table)
require(dplyr)
df1 <- read.table(text= "
col1 col2 col3 col4 col5
123 121 16519 1 4
123 121 16519 2 5
123 121 16518 3 5
123 121 16517 4 6
123 121 16512 5 7
123 121 16554 6 8
124 333 16554 7 9
124 333 16552 8 5
124 333 16549 1 1
124 333 16495 2 2
124 555 16573 4 4
125 555 16573 5 3
125 555 16569 6 5
125 555 16567 7 6
125 555 16568 8 7
", header=TRUE, na.strings=NA, stringsAsFactors=FALSE)
df2 <- distinct(df1[c("col1","col2","col3")])
setnames(df2, old=c("col1","col2","col3"), new=c("col11","col22","col33"))
res <- vector("list", nrow(df2))
for(i in 1:nrow(df2)) {
one_row <- df2[i,]
df <- merge(select(one_row, col11, col22, col33),
select(df1,col1,col2,col3,col4,col5),by=NULL)%>%
filter((col3 >= (col33-(7))) & (col3 < col33))
res[[i]] = df%>%
group_by(col11, col22,col33)%>%
summarise(Averagecol4=mean(col4,na.rm=TRUE), Count=n())
}
as.data.frame(do.call("rbind", res))
# col11 col22 col33 Averagecol4 Count
# 1 123 121 16519 4.0 3
# 2 123 121 16518 4.5 2
# 3 123 121 16517 5.0 1
# 4 123 121 16554 4.5 2
# 5 124 333 16554 4.5 2
# 6 124 333 16552 1.0 1
# 7 124 555 16573 7.0 3
# 8 125 555 16573 7.0 3
# 9 125 555 16569 7.5 2
# 10 125 555 16568 7.0 1
require(data.table)
需要(dplyr)
df1以下是一个data.table解决方案,该解决方案使用了新的非等联接功能,目前在:
有关安装说明,请参阅链接。从df1
(这是一个data.frame)开始,下面是我的步骤:
require(data.table) # v1.9.7+
df2 = setDT(df1)[, .N, by = col1:col3][, col3_minus_7 := col3 - 7] ## (1)
ans = df1[df2, ## (2)
on = .(col3 >= col3_minus_7, col3 < col3), ## (3)
.(col1 = i.col1, col2 = i.col2,
mean = mean(col4, na.rm=TRUE), count = .N), ## (4)
by = .EACHI, ## (5)
nomatch = 0L, ## (6)
allow.cartesian = TRUE] ## (7)
setnames(ans, 1:2, c("col3_minus_7", "col3")) ## (8)
# col3_minus_7 col3 col1 col2 mean count
# 1: 16512 16519 123 121 4.0 3
# 2: 16511 16518 123 121 4.5 2
# 3: 16510 16517 123 121 5.0 1
# 4: 16547 16554 123 121 4.5 2
# 5: 16547 16554 124 333 4.5 2
# 6: 16545 16552 124 333 1.0 1
# 7: 16566 16573 124 555 7.0 3
# 8: 16566 16573 125 555 7.0 3
# 9: 16562 16569 125 555 7.5 2
# 10: 16561 16568 125 555 7.0 1
require(data.table)#v1.9.7+
df2=setDT(df1)[,.N,by=col1:col3][,col3_减7:=col3-7]##(1)
ans=df1[df2,##(2)
on=(col3>=col3_减_7,col3
[1] 获取唯一行(通过在按col1、col2、col3
分组时间接生成计数,这只是另一种方式)并添加一个新列col3\u减7
,我们稍后将需要该列作为联接条件
[2] df1[df2,
——对于df2
的每一行,在df1
中查找匹配的行索引
[3] 基于以下条件:on=(col3>=col3\u减7,col3
,即,df1$col3>=df2$col3\u减7
和df1$col3
[4] +[5]对于每个df2
(.EACHI
)的匹配行,计算所需的表达式(平均值和计数以及其他列)。详细阅读by=.EACHI
[6] 对于指定的条件,df2
在df1
中没有任何匹配行时,不要返回任何内容
[7] allow.cartesian
是一个用于保护意外无效联接的参数。请阅读
[8] 手动重命名间隔列(目前,这应该很快自动完成).您的代码现在出错了。setnames
从哪里来?它是不是与setnames
不同的版本?@alistaire感谢您指出。它已经修复了!仍然出错,因为res
现在不是以data.frame结束的。更好的问题:您想要的输出是什么?@alistaire它工作正常,但我仍然添加了数据。res的帧。所需的输出是res。“distinct”不是base-R函数…感谢您的解决方案。但我在[.data.table
(setDT(df1),.N,by=col1:col3)中收到以下错误错误:'by'或'keyby'列表中的项是长度(16397)。每个项的长度必须与x中的行或I(15)返回的行数相同。此外:警告消息:1:In col1:col3:数值表达式有15个元素:只有第一个使用的2:In col1:col3:数值表达式有15个元素:只有第一个使用的DI提到这需要开发版本,并提供了一个链接,显示了如何安装它。我将按照此链接获得v1.9.7,但仍然获得v1.9.6#安装data.table安装程序包的开发版本(“data.table”,type=“source”,repos=“)#恢复到CRAN版本删除程序包(“data.table”)#首先删除当前版本的安装程序包(“data.table”)#然后重新安装CRAN版本。我仍然收到错误,因为我无法下载data.table的1.9.7版本,是否有任何方法可以替换”。"在您的脚本中被其他适用于v1.9.6的函数使用,您必须阅读其中的说明并仔细遵循。您可以将
替换为列表
,但正如我清楚地提到的那样,该功能在v1.9.6
中不可用。如果您认为您仔细遵循了说明,请创建一个很明显,你尝试过的新Q和你收到的错误信息是什么,这样我们可以提供帮助,并且安装页面可以修复(如果需要)。