Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用嵌套的应用函数而不是嵌套的for循环_R_Apply_Nested Loops - Fatal编程技术网

使用嵌套的应用函数而不是嵌套的for循环

使用嵌套的应用函数而不是嵌套的for循环,r,apply,nested-loops,R,Apply,Nested 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]) } } for(1中的j:ncol(

我的目标是在
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])
  }
}
for(1中的j:ncol(df.i)){
用于(1:nrow中的i(df.i)){

这里有四种方法可以实现内部指令的功能

首先是一个数据集示例

set.seed(5345)    # Make the results reproducible
df.i <- matrix(1:400, ncol = 40)
is.na(df.i) <- sample(400, 50)
然后,矢量化,完全没有循环

df.i2 <- ifelse(is.na(df.i), df.i[, 39], 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])
  }
}
基准。

在@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

f这里有四种方法可以实现内部指令的功能

首先是一个数据集示例

set.seed(5345)    # Make the results reproducible
df.i <- matrix(1:400, ncol = 40)
is.na(df.i) <- sample(400, 50)
然后,矢量化,完全没有循环

df.i2 <- ifelse(is.na(df.i), df.i[, 39], 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])
  }
}
基准。

在@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

f
ifelse
是一个矢量化函数,因此您的内部循环可以替换为:
df.i[,j]在对data.frames使用
apply()
时要小心。
apply()
将data.frame强制转换为矩阵,其中所有列都是相同的数据类型。在您的特定情况下,这似乎不是一个问题,但通常使用
lappy()
更安全,如果else
是一个向量化函数,那么您的内部循环可以替换为:
df.i[,j]使用
apply()时要小心
使用data.frames.
apply()
将data.frames强制到所有列都是相同数据类型的矩阵中。在您的特定情况下,这似乎不是问题,但通常使用
lappy()
。完全矢量化,无
ifelse
df.i3[is.na(df.i3)]=df.i3[行(df.i3)[is.na(df.i3)],39]
(对于循环,无
ifelse
,将内行替换为
df.i1[is.na(df.i1[,j])@Gregor谢谢,我使用了第一条注释,请参见编辑。完全矢量化,无
ifelse
df.i3[is.na(df.i3)]=df.i3[row(df.i3)[is.na(df.i3)],39]
(对于循环,没有
ifelse
,将内行替换为
df.i1[is.na(df.i1[,j]),j]@Gregor谢谢,我使用了第一条注释,请参见编辑。