[英]how to speed this R code in SparkR
我有以下代碼可在常規R中使用,但我想移植到SparkR以加快速度:
sample_data<- structure(list(idnty_frst_nm = structure(c(3L, 2L), .Label = c("","I", "Ima"), class = "factor"), idnty_last_nm = structure(c(2L,2L), .Label = c("", "NINJA"), class = "factor"), PERSON_IDENTIFIER_VALUE = c(9021099834,9021099834), RECEIPT_NUMBER = structure(c(2L, 2L), .Label = c("","MISC1234567"), class = "factor"), a_nbr.1 = structure(c(2L,2L), .Label = c("", "A079577094"), class = "factor"), ssn = structure(c(2L,2L), .Label = c("", "123-456-7891"), class = "factor"), idnty_dob = structure(c(2L,2L), .Label = c("", "1/2/2020"), class = "factor"), a_nbr = structure(c(2L,2L), .Label = c("", "AO79577094"), class = "factor")), .Names = c("idnty_frst_nm","idnty_last_nm", "PERSON_IDENTIFIER_VALUE", "RECEIPT_NUMBER","a_nbr.1", "ssn", "idnty_dob", "a_nbr"), row.names = 1:2, class = "data.frame")
sample_data$name<-paste(sample_data$idnty_frst_nm, sample_data$idnty_last_nm)
innov.df<-sample_data
rownames(innov.df)<-1:nrow(innov.df)
#Checking for duplicate names, using 'agrep' function and storing intermediate
#results in table 'p'
p<-data.frame(a=integer(),b=integer())
k<-1
for(i in 1:nrow(innov.df)){
for (j in agrep(innov.df$name[i], innov.df$name,
ignore.case=TRUE, value=FALSE,
max.distance = 0.07, useBytes = TRUE)) {
if(i!=j)
{
if((innov.df[i,2]==innov.df[j,2])&&(innov.df[i,3]==innov.df[j,3]))
{
p[k,1]<-min(i,j)
p[k,2]<-max(i,j)
k<-k+1
}
}
}
}
p<-unique(p)
關於如何加快速度的任何想法將不勝感激!!
盡管確實有更好的例子,但這只是一些小例子,說明如何加快該過程。 我試圖維護您的循環結構並對其進行了優化。
而不是在循環中附加到數據框,我將在開頭創建一個列表並為其分配值,最后將它們綁定在一起。 這已經為您帶來了大約40%的加速。
下一個函數僅在第二個if語句中使用as.character()
,因為它們是其他因素。 這帶來了另外10%。
最后一個函數使用矩陣而不是data.frame並將值附加到該矩陣 。 最后一個實現了上述所有優點:)
到目前為止,還沒有使用過data.tables或應用函數,甚至沒有並行處理,這無疑會進一步加快代碼的速度,但是我敢肯定其他人對此有更豐富的經驗,並且可能會表現出更好的做法。
fdf <- function(){
p <- data.frame(a=integer(),b=integer())
for (i in 1:nrow(innov.df)){
for (j in agrep(innov.df$name[i], innov.df$name, ignore.case=TRUE, value=FALSE,
max.distance = 0.07, useBytes = TRUE)) {
if (i!=j) {
if ((innov.df[i,2]==innov.df[j,2])&&(innov.df[i,3]==innov.df[j,3])) {
p[k,1] <- min(i,j)
p[k,2] <- max(i,j)
k <- k+1
}
}
}
}
p <- data.frame(matrix(p[!is.na(p)],ncol=2, byrow = T))
colnames(p) <- c("a","b")
p
}
flist <- function(){
p <- list()
for (i in 1:nrow(innov.df)) {
for (j in agrep(innov.df$name[i], innov.df$name,
ignore.case=TRUE, value=FALSE,
max.distance = 0.07, useBytes = TRUE)) {
if (i!=j) {
if ((innov.df[i,2])==(innov.df[j,2])&&
(innov.df[i,3])==(innov.df[j,3]))
{
p[[k]] <- cbind(a=min(i,j), b=max(i,j))
k <- k+1
}
}
}
}
p <- data.frame(Filter(Negate(is.null), p))
colnames(p) <- c("a","b")
p
}
flistOpti <- function(){
p <- list()
for (i in 1:nrow(innov.df)) {
for (j in agrep(innov.df$name[i], innov.df$name,
ignore.case=TRUE, value=FALSE,
max.distance = 0.07, useBytes = TRUE)) {
if (i!=j) {
if (as.character(innov.df[i,"idnty_last_nm"])==as.character(innov.df[j,"idnty_last_nm"]) &&
(as.character(innov.df[i,"PERSON_IDENTIFIER_VALUE"])==as.character(innov.df[j,"PERSON_IDENTIFIER_VALUE"]))) {
p[[k]] <- cbind(a=min(i,j), b=max(i,j))
k <- k+1
}
}
}
}
p <- data.frame(Filter(Negate(is.null), p))
colnames(p) <- c("a","b")
p
}
fma <- function(){
p <- matrix(c(a=integer(),b=integer()), ncol=2)
for (i in 1:nrow(innov.df)){
for (j in agrep(innov.df$name[i], innov.df$name, ignore.case=TRUE, value=FALSE,
max.distance = 0.07, useBytes = TRUE)) {
if (i!=j) {
if ((innov.df[i,2]==innov.df[j,2])&&(innov.df[i,3]==innov.df[j,3])) {
p <- c(p, cbind(min(i,j),max(i,j)))
k <- k+1
}
}
}
}
p <- data.frame(matrix(p[!is.na(p)],ncol=2, byrow = T))
colnames(p) <- c("a","b")
p
}
fmaOptim <- function(){
p <- matrix(c(a=integer(),b=integer()), ncol=2)
for (i in 1:nrow(innov.df)){
for (j in agrep(innov.df$name[i], innov.df$name, ignore.case=TRUE, value=FALSE,
max.distance = 0.07, useBytes = TRUE)) {
if (i!=j) {
if (as.character(innov.df[i,"idnty_last_nm"])==as.character(innov.df[j,"idnty_last_nm"]) &&
(as.character(innov.df[i,"PERSON_IDENTIFIER_VALUE"])==as.character(innov.df[j,"PERSON_IDENTIFIER_VALUE"]))) {
p <- c(p, cbind(min(i,j),max(i,j)))
k <- k+1
}
}
}
}
p <- data.frame(matrix(p[!is.na(p)],ncol=2, byrow = T))
colnames(p) <- c("a","b")
p
}
library(microbenchmark)
mc <- microbenchmark(times = 1000,
fdfR = fdf(),
flistR = flist(),
flistOptiR = flistOpti(),
fmaR = fma(),
fmaOptimR = fmaOptim()
)
mc
Unit: microseconds
expr min lq mean median uq max neval cld
fdfR 782.725 831.056 1059.789348 883.3505 1018.7130 24732.664 1000 c
flistR 449.700 470.089 576.289776 489.5335 545.9820 23600.677 1000 b
flistOptiR 394.949 417.227 581.230449 435.1620 492.9325 45357.250 1000 b
fmaR 370.784 389.664 484.542990 402.5015 452.3420 24713.785 1000 ab
fmaOptimR 313.015 335.670 431.991723 349.8295 393.0620 25033.973 1000 a
您還可以將nrow(innov.df)
放在for(i in 1:nrow(innov.df))
,因為否則它將計算每個循環中的行數。 這不會導致速度加快,但是示例中的行數僅為2,因此它可能很小,無法顯示出一些改進。 這個小例子表明,隨着行數的增加,需要進行一些小的性能優化。
df <- data.frame(
x = runif(100000, 1,10),
id = 1:100000
)
mc <- microbenchmark(times = 1000,
Nrow = {for (i in 1:nrow(df)) {}},
NoNrow = for (i in 1:100000) {}
)
mc
Unit: milliseconds
expr min lq mean median uq max neval cld
Nrow 3.895500 4.060691 4.311444202 4.1584845 4.3051750 10.454830 1000 b
NoNrow 3.384633 3.516409 3.734800425 3.6017420 3.7303085 36.621923 1000 a
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.