我对R编程相对较新,并试图找出如何使用自定义函数以内存有效方式使用dplyr
或data.table
来评估数据框的新列。有人可以帮忙吗
以下是我的问题的简要总结
数据框1和2具有相同的类型和列数
df1 <- data.frame(col1 = c("A", "B", "C"), col2 = c(10,20,30))
df2 <- data.frame(col1 = c("DA", "EE", "FB", "C"), col2 = c(10,20,30,40))
这些数据框有数百万条记录。
现在我想通过使用df2中的值将一个新列添加到其中一个数据框(比如df1)。
library(dplyr)
calculateCol3 <- function(word) {
df2 %>%
filter(grepl(paste0(word, "$"),col1) )%>%
summarize(col3= sum(col2))
col3
}
df1 %>% group_by(col1) %>% mutate(col3 = calcualteCol3(col1))
这种方法有效,但速度很慢,我想这是因为复制数据集太多次了。有人可以建议一个更好的方法吗?预期结果是:
col1 col2 col3
A 10 10
B 20 30
C 30 40
我也尝试将数据帧转换为data.table,如下所示
dt1 <- data.table(df1)
dt2 <- data.table(df2)
dt1[, col3 := calculateCol3(col1)}, by = 1:nrow(dt1)]
一切似乎都很慢。我确定有更好的方法来实现这一目标。有人可以帮忙吗
由于
答案 0 :(得分:3)
如果您想要一个有效的解决方案,我建议您不要使用正则表达式,也不要进行逐行操作。如果您的所有函数都是通过最后一个字母加入,那么您可以在不使用正则表达式的情况下获取后者,然后使用data.table
进行二进制连接(为了提高效率)
library(data.table)
setDT(df2)[, EndWith := substring(col1, nchar(as.character(col1)))]
setDT(df1)[df2, col3 := i.col2, on = .(col1 = EndWith)]
df1
# col1 col2 col3
# 1: A 10 10
# 2: B 20 30
# 3: C 30 40
现在,通过查看您的函数,您似乎也尝试对每个联接df2$col2
中的值求和。没问题,您也可以在data.table
中进行二进制连接时运行函数。让我们说这是你的df2
(只是为了说明你每封信的价值超过一个值)
df2 <- data.frame(col1 = c("DA", "FA", "EE", "FB", "C", "fC"), col2 = c(10,20,10,30,40,30))
df2
# col1 col2
# 1 DA 10
# 2 FA 20
# 3 EE 10
# 4 FB 30
# 5 C 40
# 6 fC 30
第一步是相同的
setDT(df2)[, EndWith := substring(col1, nchar(as.character(col1)))]
虽然第二步将涉及二进制连接 - 只是以相反的方式,同时添加, by = .EACHI
并指定所需的功能
setDT(df2)[df1, .(col2 = i.col2, col3 = sum(col2)), on = .(EndWith = col1), by = .EACHI]
# EndWith col2 col3
# 1: A 10 30
# 2: B 20 30
# 3: C 30 70
答案 1 :(得分:0)
使用fuzzyjoin
包,我认为你可以做到这一点。 E.g:
#install.packages("fuzzyjoin")
df1$col1regex <- paste0(df1$col1,"$")
regex_join(df2, df1, by=c(col1="col1regex"), mode="right")
# col1.x col2.x col1.y col2.y col1regex
#1 DA 10 A 10 A$
#2 FB 30 B 20 B$
#3 C 40 C 30 C$