2015-10-05 195 views
1

上我有一個數據幀DF 看起來像這樣:優化ifelse一個大的數據幀

A B C 
1 2 3 
2 5 6 
3 8 9 

的代碼下面的行添加新的列,並相應地填滿數據。

df$Mean.Result1 <- ifelse(df[, "A"] > 0.05 & df[, "B"] > 0.05, "Equal", "") 

我使用R 2與Splunk的,並[RSplunk的不能夠認識到,上述格式。

是否有權這樣做:

df.$Mean.Result1 <- ifelse(df.$A > 0.05 & df$B > 0.05, "Equal", "") 

怎樣的兩段代碼有什麼不同?它會影響計算速度嗎?我的實際數據集大約有5億行和400列。

+1

如果你有5億行,它會更有效,不管是記憶方式還是計算方式,都要做'df。$ Mean.Result1 < - ifelse(df。$ A> 0.05&df。$ B> 0.05,1L,0L),然後是df。$ Mean。結果1 < - 因子(df。$ Mean.Result1,levels = c(1L,0L),labels = c(「Equal」,「」)) '。您將大大減少表格的大小,並且涉及'df。$ Mean.Result1'的所有操作將會快得多_much_。儘可能避免字符串,R不能有效地處理它們。 –

+3

'df [,「A」]'相當於'df $ A',而不是'df。$ A'。這兩段代碼是不同的,因爲一個使用變量'df'和另一個'df.'。就計算成本而言,使用第一種或第二種形式是嚴格等價的。 –

回答

3

There has been some discussion關於ifelse不是速度是一個重要因素的代碼的最佳選擇。您可以嘗試:

df$Mean.Result1 <- c("", "Equal")[(df$A > 0.05 & df$B > 0.05)+1] 

要看看這裏發生了什麼,讓我們分解命令。如果AB均超過0.05,則df$A > 0.05 & df$B > 0.05返回TRUE;否則FALSE。因此,如果AB均超過0.05,則(df$A > 0.05 & df$B > 0.05)+1返回2,否則返回1。這些用作向量c("", "Equal")的指示,所以當兩者都超過0.05時,我們得到"Equal",否則就是""

這裏的一個數據幀上的比較一個百萬行:

# Build dataset and functions 
set.seed(144) 
big.df <- data.frame(A = runif(1000000), B = runif(1000000)) 
OP <- function(df) { 
    df$Mean.Result1 <- ifelse(df$A > 0.05 & df$B > 0.05, "Equal", "") 
    df 
} 
josilber <- function(df) { 
    df$Mean.Result1 <- c("", "Equal")[(df$A > 0.05 & df$B > 0.05)+1] 
    df 
} 
all.equal(OP(big.df), josilber(big.df)) 
# [1] TRUE 

# Benchmark 
library(microbenchmark) 
microbenchmark(OP(big.df), josilber(big.df)) 
# Unit: milliseconds 
#    expr  min  lq  mean median  uq  max neval 
#  OP(big.df) 299.6265 311.56167 352.26841 318.51825 348.09461 540.0971 100 
# josilber(big.df) 40.4256 48.66967 60.72864 53.18471 59.72079 267.3886 100 

與向量索引的方法是大約6倍於中間的運行速度更快。

+0

感謝您的快速和清晰的解釋,它真的很有幫助。 –

+1

@josilber,很聰明! –

+1

非常好。 @kRazzyR如果內存是一個問題,考慮鑄造因素,你會減少一半的對象的大小。 –