2014-03-24 44 views
0

我有一個包含+10百萬條記錄(all_postcodes)的數據框。 [編輯]以下是隻有幾個記錄:使用gsub和sapply的R性能問題

pcode area east north area2  area3  area4  area5 
AB101AA 10 394251 806376 S92000003 S08000006 S12000033 S13002483 
AB101AB 10 394232 806470 S92000003 S08000006 S12000033 S13002483 
AB101AF 10 394181 806429 S92000003 S08000006 S12000033 S13002483 
AB101AG 10 394251 806376 S92000003 S08000006 S12000033 S13002483 

我想創建一個包含其中一列的歸一化版本使用下面的函數新列:

pcode_normalize <- function (x) { 
x <- gsub(" ", " ", x) 
if (length(which(strsplit(x, "")[[1]]==" ")) == 0) { 
x <- paste(substr(x, 1, 4), substr(x, 5, 7)) 
} 
x 
} 

我試圖執行它如下:

all_postcodes$npcode <- sapply(all_postcodes$pcode, pcode_normalize) 

但它需要很長時間。任何建議如何提高性能?

+2

你可以請'dput'幾行'all_postcodes $ pcode'? [如何創建**最小,可重現的示例**](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/5963610#5963610) – Henrik

+0

對不起 - 剛剛做到了!感謝您的建議! – Nick

+0

你可能想使用'(g)sub(「[] {2,}」,'',x)',這是更一般的 – Janhoo

回答

6

您在pcode_normalize中使用的所有功能已被矢量化。沒有必要使用sapply進行循環。它也看起來像你使用strsplit來尋找單個空間。 grepl會更快。

在您撥打gsubgrepl的電話中使用fixed=TRUE會更快,因爲您實際上沒有使用正則表達式。

pcode_normalize <- function (x) { 
    x <- gsub(" ", " ", x, fixed=TRUE) 
    sp <- grepl(" ", x, fixed=TRUE) 
    x[!sp] <- paste(substr(x[!sp], 1, 4), substr(x[!sp], 5, 7)) 
    x 
} 
all_postcodes$npcode <- pcode_normalize(all_postcodes$pcode) 

我無法實際測試這一點,因爲你沒有提供任何數據,例如,但它應該讓你在正確的道路上。

+0

@Nick:它適用於你的示例數據...我不是千里眼。 –

+0

你是對的 - 它的工作,閃電般快!最大的改進是刪除sapply(之前我不得不停止R,因爲它需要超過一個小時),但是你的函數版本也快得多。現在沒有sapply和你的代碼,它不到一秒鐘。非常感謝! – Nick