2016-10-17 106 views
0

在R中,我有一個相當大的數據幀(d),它是10500乘以6000.所有值都是數字。 它在行和列中都有許多na值元素,我正在用零替換這些值。我已經使用:將缺失值設置爲R中的常數,計算速度

d[is.na(d)] <- 0

但這是相當緩慢。在R中有更好的方法嗎?

我願意使用其他R軟件包。

例如,如果討論的重點是計算速度而不是「爲什麼要用零代替na」。而且,當我意識到已經提出類似的Q(How do I replace NA values with zeros in an R dataframe?)時,重點並不是針對具有許多缺失值的大數據幀的計算速度。

謝謝!

被修改解決方案: 作爲有益建議,改變d,以一個矩陣施加is.na通過一個數量級加快了計算之前

+4

是否該數據幀具有相同的類型(即,所有的數值,或所有的字符)的列?將它存儲爲矩陣可能會加快速度。 – Spacedman

+1

經常轉換爲'data.table'可以提高許多操作的速度,但'is.na.data.table'不是其中之一。 – shayaa

+0

@ Spacedman,所有數字 - 抱歉應該指定。將編輯。 – Peter

回答

1

我想,所有列必須是數字或分配0到NAS將不明智。

我得到以下計時,有大約10,000的NA:

> M <- matrix(0, 10500, 6000) 
> set.seed(54321) 
> r <- sample(1:10500, 10000, replace=TRUE) 
> c <- sample(1:6000, 10000, replace=TRUE) 
> M[cbind(r, c)] <- NA 
> D <- data.frame(M) 
> sum(is.na(M)) # check 
[1] 9999 
> sum(is.na(D)) # check 
[1] 9999 
> system.time(M[is.na(M)] <- 0) 
    user system elapsed 
    0.19 0.12 0.31 
> system.time(D[is.na(D)] <- 0) 
    user system elapsed 
    3.87 0.06 3.95 

所以,用這個數字來港定居的,我得到加速級的順序使用矩陣。 (使用更少的NAs時,差異會更小。)但是,使用數據框的時間在我的筆記本電腦上僅爲4秒 - 比回答問題花費的時間少得多。如果問題真的如此嚴重,那爲什麼這麼慢?

我希望這會有所幫助。

+0

我正在循環數百個這樣的大小的數據框架,其中一些還要大得多,所以速度提升具有實際意義。感謝你的回答。 – Peter

1

使用data.table軟件包可以大幅提升性能。通常,通過大量的操作和轉換,速度要快得多。 缺點是語法的學習曲線。然而,如果你正在尋求提高速度性能,那麼投資可能是值得的。

生成假數據

r <- 10500 
c <- 6000 
x <- sample(c(NA, 1:5), r * c, replace = TRUE) 
df <- data.frame(matrix(x, nrow = r, ncol = c)) 

基礎R

df1 <- df 
system.time(df1[is.na(df1)] <- 0) 

    user system elapsed 
    4.74 0.00 4.78 

tidyr - replace_na()

dfReplaceNA <- function (df) { 
    require(tidyr) 
    l <- setNames(lapply(vector("list", ncol(df)), function(x) x <- 0), names(df)) 
    replace_na(df, l) 
} 
system.time(df2 <- dfReplaceNA(df)) 

    user system elapsed 
    4.27 0.00 4.28 

數據。表 - set()

dtReplaceNA <- function (df) { 
    require(data.table) 
    dt <- data.table(df) 
    for (j in 1:ncol(dt)) {set(dt, which(is.na(dt[[j]])), j, 0)} 
    setDF(dt) # Return back a data.frame object 
} 
system.time(df3 <- dtReplaceNA(df)) 

    user system elapsed 
    0.80 0.31 1.11 

比較數據幀

all.equal(df1, df2) 

[1] TRUE 

all.equal(df1, df3) 

[1] TRUE