R 数据帧上的行while循环?

R 数据帧上的行while循环?,r,dataframe,while-loop,dplyr,R,Dataframe,While Loop,Dplyr,我有一个基于输入变量计算的函数,但我想根据函数的结果更改输入变量。我觉得这是一个非常琐碎的问题,但我还没有找到有效的解决办法 我有一个类似的数据集: v1有一种方法可以通过使用dplyr::rowwise(): 库(tidyverse) v1 4 10 100 1 4 15 0.4 15.2 #> 5 10 100 1 2 22 0.2 22 #> 6 9 100 1 1 16 0.09 16.0 #> 7

我有一个基于输入变量计算的函数,但我想根据函数的结果更改输入变量。我觉得这是一个非常琐碎的问题,但我还没有找到有效的解决办法

我有一个类似的数据集:


v1有一种方法可以通过使用
dplyr::rowwise()

库(tidyverse)
v1 4 10 100 1 4 15 0.4 15.2
#>  5    10   100     1     2    22  0.2   22  
#>  6     9   100     1     1    16  0.09  16.0
#>  7     5   100     1     2    24  0.1   24  
#>  8    12   100     1     2    23  0.24  23.0
#>  9     8   100     1     3    30  0.24  30  
#> 10     7   100     1     2    14  0.14  14.
由reprex软件包(v0.3.0)于2020年8月28日创建
然而,在R中使用while循环通常是一个非常糟糕的主意,而在大型数据集中,
rowwise()
可能非常慢。你一定要找到一个比像你现在这样增加v3更好的算法。但是,我找不到一个适合您的示例。

使用
mapply()
和一些其他定义,您可以在base R中执行:

set.seed(42)
df <- data.frame(v1=sample(5:12, 10, replace=T), v2=rep(100, 10), v3=rep(1,10), 
                 v4=sample(1:4, 10, replace=T), t1=sample(10:30, 10, replace=T))

fun<-function(v1, v2, v3, v4) {
  #does complicated things
  result <- ((v2/(v1*v4))*v3)
  return(result)
}

fun2 <- function(v1, v2, v3, v4, t) {
  out <- fun(v1, v2, v3, v4)
  while (out < t){
    v3 <- v3 + 1
    out <- fun(v1, v2, v3, v4)
  }
  return(list(v3new=v3, out=out))
}

cbind(df, t(mapply(fun2, df$v1, df$v2, df$v3, df$v4, df$t1)))
> cbind(df, t(mapply(fun2, df$v1, df$v2, df$v3, df$v4, df$t1)))
#    v1  v2 v3 v4 t1 v3new      out
# 1   5 100  1  3 24     4 26.66667
# 2   9 100  1  4 12     5 13.88889
# 3   5 100  1  3 18     3       20
# 4   5 100  1  4 13     3       15
# 5   6 100  1  1 14     1 16.66667
# 6   8 100  1  1 22     2       25
# 7   6 100  1  2 14     2 16.66667
# 8   6 100  1  4 29     7 29.16667
# 9   5 100  1  2 11     2       20
# 10 12 100  1  2 17     5 20.83333
set.seed(42)

我不明白你的问题。你能展示你期望的最终产出吗?你到底想计算什么?为什么不为所有行计算整个结果,然后使用
filter
删除
t1>=out
的行呢
df%>%mutate(out=fun(v1,v2,v3,v4))%%>%filter(t1
。如果你不想过滤掉行,你可以将
filter
更改为第二个
mutate(out=ifelse(t1>=out,NULL,out))
我认为他想增加
v3
,直到
out
大于t1。这是有道理的。问题是是否应该在结果中更新
v3
,以及它是否是固定的时间间隔。在mutate中使用
v3+seq(n())
可以实现
while
循环的效果。这就是我一直在寻找的!不过,我认为jogo的方法在处理大型数据集时可能会更快。谢谢大家!@用户45017注意,Jogo的方法并不期望得到完全相同的结果。我不确定为什么以及哪一个是正确的,这可能是因为比较严格。我在一个10万行的样本上运行了一个小基准测试,两个方法都有相同的精确速度:-)我想知道为什么你的方法是四舍五入的
,这看起来和我的很相似,我现在发现我的错误是,当我试图让第二个函数工作时,忘记了在while循环之前定义“out”。谢谢你的解决方案@DanChaltiel我无法复制您的数据,因为您没有在代码中使用
set.seed(…)
。@Jogo true,但事实上这是因为您的代码中有一个错误:您使用了
df$v2
两次;-)
set.seed(42)
df <- data.frame(v1=sample(5:12, 10, replace=T), v2=rep(100, 10), v3=rep(1,10), 
                 v4=sample(1:4, 10, replace=T), t1=sample(10:30, 10, replace=T))

fun<-function(v1, v2, v3, v4) {
  #does complicated things
  result <- ((v2/(v1*v4))*v3)
  return(result)
}

fun2 <- function(v1, v2, v3, v4, t) {
  out <- fun(v1, v2, v3, v4)
  while (out < t){
    v3 <- v3 + 1
    out <- fun(v1, v2, v3, v4)
  }
  return(list(v3new=v3, out=out))
}

cbind(df, t(mapply(fun2, df$v1, df$v2, df$v3, df$v4, df$t1)))
> cbind(df, t(mapply(fun2, df$v1, df$v2, df$v3, df$v4, df$t1)))
#    v1  v2 v3 v4 t1 v3new      out
# 1   5 100  1  3 24     4 26.66667
# 2   9 100  1  4 12     5 13.88889
# 3   5 100  1  3 18     3       20
# 4   5 100  1  4 13     3       15
# 5   6 100  1  1 14     1 16.66667
# 6   8 100  1  1 22     2       25
# 7   6 100  1  2 14     2 16.66667
# 8   6 100  1  4 29     7 29.16667
# 9   5 100  1  2 11     2       20
# 10 12 100  1  2 17     5 20.83333