我有一个函数根据输入变量计算一些东西,但我想根据函数的结果更改输入变量。我觉得这是一个非常微不足道的问题,但我还没有找到一个可行的解决方案。
我有一个类似下面的数据集:
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)和一个函数,它使用变量v1到v4来计算一些东西:
fun<-function(v1, v2, v3, v4){
#does complicated things
result<-((v2/(v1*v4))*v3
return(result)
}
out<-fun(v1, v2, v3, v4)
df<-data.frame(v1, v2, v3, v4, t1, out)我需要t1 < out。对于非矢量化的数据,这似乎是可行的:
while (out < t1){
v3= v3 + 1
out<- fun(v1, v2, v3, v4)
}理想情况下,v3的最后一个值是以某种方式存储的。
v1 v1 v2 v3 v4 t1 out out_new v3_new
1 6 100 1 2 15 8.333333 16 2
2 12 100 1 2 17 4.166667 20 5
3 5 100 1 1 12 20.000000 20 1
4 10 100 1 4 26 2.500000 . .
5 8 100 1 2 15 6.250000 . .
6 6 100 1 3 18 5.555556
7 10 100 1 4 20 2.500000
8 11 100 1 2 12 4.545455
9 12 100 1 3 28 2.777778
10 6 100 1 2 25 8.333333我正在寻找的输出是一个数据帧,看起来像这样:我正在寻找的是一个在大型(100.000行)数据帧/tibble上工作的矢量化解决方案。我用dplyr尝试了不同的方法(用case_when变异),但没有找到一个可行的解决方案。
发布于 2020-08-28 17:20:59
有一种方法可以使用dplyr::rowwise()实现这一点
library(tidyverse)
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<-(v1/v2)*v4*v3
return(result)
}
reallyWeirdFunction = function(v1, v2, v3, v4, t){
out<- fun(v1, v2, v3, v4)
while (out < t){
v3= v3 + 1
out<- fun(v1, v2, v3, v4)
}
out
}
df<-data.frame(v1, v2, v3, v4, t1)
df %>%
rowwise() %>%
mutate(
out=fun(v1, v2, v3, v4),
out2=reallyWeirdFunction(v1, v2, v3, v4, t1)
)
#> # A tibble: 10 x 7
#> # Rowwise:
#> v1 v2 v3 v4 t1 out out2
#> <int> <dbl> <dbl> <int> <int> <dbl> <dbl>
#> 1 7 100 1 3 17 0.21 17.0
#> 2 11 100 1 2 24 0.22 24.2
#> 3 12 100 1 1 11 0.12 11.0
#> 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.
Created on 2020-08-28 by the reprex package (v0.3.0)然而,在R中使用while循环通常是一个非常糟糕的主意,并且rowwise()在大型数据集中可能非常慢。您绝对应该尝试找到一种更好的算法,而不是像现在这样递增v3。不过,我找不到适合你的例子。
发布于 2020-08-28 17:46:47
使用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.83333https://stackoverflow.com/questions/63630844
复制相似问题