【问题标题】:Can I use mapply function in R with a starting value?我可以在 R 中使用具有起始值的 mapply 函数吗?
【发布时间】:2021-07-17 15:44:18
【问题描述】:

我想知道是否可以在 R 中使用带有起始值的 mapply 函数。我知道如何使用 for 循环(参见下面的示例),但由于我的数据非常大,我喜欢使用 mapply 来加快计算时间。 是否可以在第一次迭代中使用前置条件值?

这是我喜欢使用 mapply 运行的示例:

start_value=4 
df=data.frame(A=1:10,B=2:11, C=NA)

for(i in seq_along(df[,1])){
if (i==1){
  df[i,"C"]=start_value- df[i,"A"]+df[i,"B"]
}else{
  df[i,"C"]=df[i-1,"C"]- df[i,"A"]+df[i,"B"]
}
}

【问题讨论】:

  • mapply 通常在每一行都依赖于前一行时没有多大用处。对于您的玩具示例,您可以使用 df$C <- start_value + cumsum(df$B - df$A) 进行矢量化(应该会更快),但不确定这将如何转化为您的实际用例
  • 我认为超前/滞后函数可能与此相关。

标签: r time-series apply lapply mapply


【解决方案1】:

这里是发布的for 循环的 3 个不同版本。

  1. f1:从循环中移除条件;
  2. f2:预计算差异B - A
  3. f3:预先计算差异B - A,将它们与start_value 作为第一个元素和cumsum 滞后。

第 3 个函数 f3 比原来快 6 倍。

f0 <- function(df, start_value){
  for(i in seq_along(df[,1])){
    if (i==1){
      df[i,"C"]=start_value- df[i,"A"]+df[i,"B"]
    }else{
      df[i,"C"]=df[i-1,"C"]- df[i,"A"]+df[i,"B"]
    }
  }
  df
}
f1 <- function(df, start_value){
  df[1, "C"] <- start_value - df[1, "A"] + df[1, "B"]
  for(i in seq_len(nrow(df))[-1]){
    df[i, "C"] <- df[i - 1, "C"] - df[i, "A"] + df[i, "B"]
  }
  df
}
f2 <- function(df, start_value){
  tmp <- as.vector(as.matrix(df[c("A", "B")]) %*% c(-1, 1))
  df[1, "C"] <- start_value + tmp[1]
  for(i in seq_len(nrow(df))[-1]){
    df[i, "C"] <- df[i - 1, "C"] + tmp[i]
  }
  df
}
f3 <- function(df, start_value){
  tmp <- as.vector(as.matrix(df[c("A", "B")]) %*% c(-1, 1))
  y <- c(start_value + tmp[1], tmp[-1])
  df[["C"]] <- cumsum(y)
  df
}


start_value <- 4 
df <- data.frame(A=1:10, B=2:11, C=NA)

x0 <- f0(df, 4)
x1 <- f1(df, 4)
x2 <- f2(df, 4)
x3 <- f3(df, 4)
identical(x0, x1)  # TRUE
identical(x0, x2)  # TRUE
identical(x0, x3)  # TRUE

library(microbenchmark)

mb <- microbenchmark(
  f0 = f0(df, 4),
  f1 = f1(df, 4),
  f2 = f2(df, 4),
  f3 = f3(df, 4)
)
print(mb, order = "median")
#Unit: microseconds
# expr      min        lq      mean   median       uq       max neval cld
#   f3  223.560  234.1325  456.6144  253.780  299.273 19289.107   100 a  
#   f2  962.414 1372.4640 1417.5630 1394.816 1457.883  1899.316   100  b 
#   f1 1561.998 1916.0750 1962.7880 1938.282 1980.583  2379.496   100   c
#   f0 1229.716 1932.5730 1969.8554 1957.974 1992.095  3161.792   100   c

【讨论】:

  • 非常感谢!我会根据你的建议尝试改变我的功能!!!
猜你喜欢
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
  • 2021-08-18
  • 2015-07-01
  • 1970-01-01
  • 2018-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多