Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/74.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
R while在apply中的函数中循环_R_While Loop_Apply - Fatal编程技术网

R while在apply中的函数中循环

R while在apply中的函数中循环,r,while-loop,apply,R,While Loop,Apply,我有这样一个数据帧: df <- data.frame(A=1:10, B=3, C=17) for (i in 1:nrow(df)) { print(fun_iter(df[i, ])) } 正确返回3的平方根。此外,我可以使用for循环循环遍历数据帧,如下所示: df <- data.frame(A=1:10, B=3, C=17) for (i in 1:nrow(df)) { print(fun_iter(df[i, ])) } 这给了我列“A”中所有值的平

我有这样一个数据帧:

df <- data.frame(A=1:10, B=3, C=17)
for (i in 1:nrow(df)) {
  print(fun_iter(df[i, ]))
}
正确返回3的平方根。此外,我可以使用for循环循环遍历数据帧,如下所示:

df <- data.frame(A=1:10, B=3, C=17)
for (i in 1:nrow(df)) {
  print(fun_iter(df[i, ]))
}
这给了我列“A”中所有值的平方根。但是,由于我有一个相当大的数据帧,我想使用“应用”或“映射”或类似的高效方式来获取输出,但它总是返回以下错误:

apply(df, 2, fun_iter)

Error in while (diff > 0.01) { : Missing Value, where TRUE/FALSE is needed

因此,似乎apply在评估函数中的“while”条件时遇到了问题。“map”、“mapply”、“do.call”也会发生同样的情况。非常感谢对解决此问题的任何提示。

根据评论中的说明,我们可以使用其中一个对行进行迭代。对于那些有名称的解决方案,如果不需要,请在结果上使用
unname

# 1
nr <- nrow(df)
sapply(1:nr, function(i) fun_iter(df[i, ]))
##  [1] 1.000000 1.414216 1.732051 2.000000 2.236069 2.449494 2.645767 2.828427
##  [9] 3.000000 3.162278

# 2
do.call("c", by(df, 1:nr, fun_iter, simplify = FALSE))
##        1        2        3        4        5        6        7        8 
## 1.000000 1.414216 1.732051 2.000000 2.236069 2.449494 2.645767 2.828427 
##        9       10 
## 3.000000 3.162278 

# 3
sapply(split(df, 1:nr), fun_iter)
##        1        2        3        4        5        6        7        8 
## 1.000000 1.414216 1.732051 2.000000 2.236069 2.449494 2.645767 2.828427 
##        9       10 
## 3.000000 3.162278 
CRAN上还有许多列表理解包(comprer、eList、listcmpr)。比如说,

# 5
library(listcompr)
gen.vector(fun_iter(df[i, ]), i = 1:nr)
## [1] 1.000000 1.414216 1.732051 2.000000 2.236069 2.449494 2.645767 2.828427
## [9] 3.000000 3.162278

# 6
library(comprehenr)
to_vec(for(i in 1:nr) fun_iter(df[i, ]))
## [1] 1.000000 1.414216 1.732051 2.000000 2.236069 2.449494 2.645767 2.828427
## [9] 3.000000 3.162278
古老的 我们遵循问题下方的注释,但我们只传递
df[“A”]
,因为
apply
将强制输入到普通向量,如果有任何列是空的,则可能导致行变为字符。通过使用
df[“A”]
我们可以避免这种情况

apply(df["A"], 1, fun_iter)
##  [1] 1.000000 1.414216 1.732051 2.000000 2.236069 2.449494 2.645767 2.828427
##  [9] 3.000000 3.162278
如果将函数编写为接受
A
而不是
df
,则会更简单,而且由于列不需要命名为A,因此也可以避免上述问题。我们已经留下了原来的名字,但你可以考虑使用更短的名字。函数中使用的过于冗长的命名只会增加很少的内容,实际上会使代码变得模糊

fun_iter2 <- function(A, diff = 10) {
  sqrt_iter <- A
  while(diff > 0.01) {
      sqrt_iter_new <- (sqrt_iter + A / sqrt_iter) / 2
      diff <- abs(sqrt_iter - sqrt_iter_new)
      sqrt_iter <- sqrt_iter_new
  }
  sqrt_iter
}
sapply(df$A, fun_iter2)
## [1] 1.000000 1.414216 1.732051 2.000000 2.236069 2.449494 2.645767 2.828427
## [9] 3.000000 3.162278

fun\u iter2
apply
只是一个伪装的循环。它不会给你矢量化带来的同样的速度提升(假设矢量化是可能的)。即使你得到了正确的细节,你也可能会对结果感到失望。试试这个应用(df,1,fun_iter)它很有效,谢谢!我似乎对apply中“1”和“2”的方向感到困惑,尽管使用了多年。可能与以下答案中描述的输入格式有关。谢谢@约翰·科尔曼:谢谢,很遗憾,矢量化是不可能的。我更喜欢将
应用于for循环,这样我就不必将每个迭代步骤写入预定义的数据框架。我使用了df[“a”],因为我有多个变量作为输入(到目前为止有20个,它将变得更多)。因此,我认为将整个df作为输入是最容易的。但正如您所指出的,“应用”将其更改为character,以您的方式提供变量可能是不可避免的。谢谢请参阅修改后的答案。感谢您提供备选方案<代码>应用(df,1,fun_iter)对我来说是删除带有名称的向量后最快的。
sapply
函数的速度要慢得多(慢了18倍!),这可能与数据存储在数据帧中并首先将其转换为矩阵有关。如果矩阵都是数值的,你可以从一开始就尝试将它存储在矩阵中。另外,如果你将矩阵存储为转置,然后使用
m,那么矩阵是逐列存储的
fun_iter2 <- function(A, diff = 10) {
  sqrt_iter <- A
  while(diff > 0.01) {
      sqrt_iter_new <- (sqrt_iter + A / sqrt_iter) / 2
      diff <- abs(sqrt_iter - sqrt_iter_new)
      sqrt_iter <- sqrt_iter_new
  }
  sqrt_iter
}
sapply(df$A, fun_iter2)
## [1] 1.000000 1.414216 1.732051 2.000000 2.236069 2.449494 2.645767 2.828427
## [9] 3.000000 3.162278