簡體   English   中英

使用嵌套的Apply函數而不是嵌套的for循環

[英]Using nested apply functions instead of nested for loops

我的目標是迭代df中的每一列,然后針對每一列向下迭代每一行並執行一個函數。 在這種情況下,特定功能將NA值替換為最后一列中的相應值,但是所需功能的詳細信息與此處的問題無關。 我得到了使用兩個嵌套的for循環所需的結果,如下所示:

for (j in 1:ncol(df.i)) {
  for (i in 1:nrow(df.i)) {
    df.i[i,j] <- ifelse(is.na(df.i[i,j]), df.i[i,39], df.i[i,j])
  }
}

不過,我相信這應該使用有可能apply(df.i, 1, function)嵌套的內部apply(df.i, 2, function) ,但我不能完全肯定這是可能的,或者怎么做的。 有誰知道如何通過apply函數來實現同一目標?

這是執行內部指令的四種方法。

首先,一個數據集示例。

set.seed(5345)    # Make the results reproducible
df.i <- matrix(1:400, ncol = 40)
is.na(df.i) <- sample(400, 50)

現在,@ Dave2e的注釋:僅一個for循環,矢量化最里面的一個。

df.i2 <- df.i3 <- df.i1 <- df.i    # Work with copies

for (j in 1:ncol(df.i1)) {
  df.i1[,j] <- ifelse(is.na(df.i1[, j]), df.i1[, 39], df.i1[, j])
}

然后,進行矢量化處理, 完全沒有循環

df.i2 <- ifelse(is.na(df.i), df.i[, 39], df.i)

@Gregor在評論中對另一個向量進行了矢量化,這要好得多,因為已知ifelse相對較慢。

df.i3[is.na(df.i3)] <- df.i3[row(df.i3)[is.na(df.i3)], 39]

和您的解決方案,如問題中所述。

for (j in 1:ncol(df.i)) {
  for (i in 1:nrow(df.i)) {
    df.i[i,j] <- ifelse(is.na(df.i[i,j]), df.i[i,39], df.i[i,j])
  }
}

比較結果。

identical(df.i, df.i1)
#[1] TRUE

identical(df.i, df.i2)
#[1] TRUE

identical(df.i, df.i3)
#[1] TRUE

基准。

@Gregor發表評論后,我決定對這4個解決方案進行基准測試。 不出所料,每次優化都會產生明顯的滲漏,並且他的完全矢量化解決方案是最快的。

f <- function(df.i){
  for (j in 1:ncol(df.i)) {
    for (i in 1:nrow(df.i)) {
      df.i[i,j] <- ifelse(is.na(df.i[i,j]), df.i[i,39], df.i[i,j])
    }
  }
  df.i
}

f1 <- function(df.i1){
  for (j in 1:ncol(df.i1)) {
    df.i1[,j] <- ifelse(is.na(df.i1[, j]), df.i1[, 39], df.i1[, j])
  }
  df.i1
}

f2 <- function(df.i2){
  df.i2 <- ifelse(is.na(df.i2), df.i2[, 39], df.i2)
  df.i2
}

f3 <- function(df.i3){
  df.i3[is.na(df.i3)] <- df.i3[row(df.i3)[is.na(df.i3)], 39]
  df.i3
}

microbenchmark::microbenchmark(
  two_loops = f(df.i),
  one_loop = f1(df.i1),
  ifelse = f2(df.i2),
  vectorized = f3(df.i3)
)
#Unit: microseconds
#      expr      min        lq       mean    median       uq      max neval
# two_loops 1125.017 1143.4995 1226.93089 1152.5665 1190.599 5209.431   100
#  one_loop  492.945  500.7045  518.73060  504.9435  516.638  678.951   100
#    ifelse   42.269   45.7770   50.55519   48.4140   50.470  198.533   100
#vectorized   12.626   14.5520   16.21975   15.6380   17.663   27.525   100

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM