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和你收到的错误信息是什么,这样我们可以提供帮助,并且安装页面可以修复(如果需要)。