2015-10-05 199 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如果内存是一个问题,考虑铸造因素,你会减少一半的对象的大小。 –