【问题标题】:Optimizing ifelse on a large data frame在大型数据帧上优化 ifelse
【发布时间】:2016-01-02 10:52:45
【问题描述】:

我有一个如下所示的数据框 df

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 和 Splunk,而 Splunk 中的 R 无法识别上述格式.

这样做对吗:

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

这两段代码有何不同?会影响计算速度吗?我的实际数据集大约有 5 亿行和 400 列。

【问题讨论】:

  • 如果您有 5 亿行,那么执行df.$Mean.Result1 &lt;- ifelse(df.$A &gt; 0.05 &amp; df.$B &gt; 0.05, 1L, 0L)df.$Mean.Result1 &lt;- factor(df.$Mean.Result1, levels=c(1L, 0L), labels=c("Equal", ""))在内存方面和在计算方面更加高效。您将大大减小表的大小,并且涉及df.$Mean.Result1 的所有操作都将快得多。尽可能避免使用字符串,R 不能有效地处理它们。
  • df[, "A"] 等价于df$A,而不是df.$A。两段代码不同,因为一段使用变量df,另一段使用df.。就计算成本而言,使用第一种或第二种形式是严格等价的。

标签: r if-statement dataframe subset splunk


【解决方案1】:

has been some discussion 关于ifelse 对于速度是一个重要因素的代码来说,这不是最佳选择。您可以尝试:

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

要查看这里发生了什么,让我们分解命令。如果AB 都超过0.05,df$A &gt; 0.05 &amp; df$B &gt; 0.05 返回TRUE,否则返回FALSE。因此,如果 AB 都超过 0.05,(df$A &gt; 0.05 &amp; df$B &gt; 0.05)+1 返回 2,否则返回 1。这些被用作向量c("", "Equal")的指示,所以当两者都超过0.05时我们得到"Equal",否则我们得到""

这是一个有 100 万行的数据框的比较:

# 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 倍。

【讨论】:

  • 感谢快速清晰的解释,真的很有帮助。
  • @josilber,非常聪明!
  • 非常好。 @kRazzyR 如果内存是个问题,请考虑转换为因子,您会将对象的大小减半。
  • @josilber ,可以解释一下代码行df$Mean.Result1 &lt;- c("", "Equal")[(df$A &gt; 0.05 &amp; df$B &gt; 0.05)+1]
  • @kRazzyR 我已经添加了一段解释
猜你喜欢
  • 2019-09-24
  • 2015-02-17
  • 1970-01-01
  • 2019-11-21
  • 1970-01-01
  • 2021-05-22
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多