奇怪的是,我认为通过查看 df 开始更容易。
#reproducible data
quantiles<-c("50","90")
var=c("w","d")
df=data.frame(a=runif(20,0.01,.5),b=runif(20,0.02,.5),c=runif(20,0.03,.5),e=runif(20,0.04,.5),
q50=runif(20,1,5),q90=runif(20,10,50))
head(df)
我想自动执行一个我创建(如下)的函数,以使用来 self 的 df 的不同值组合来计算 vars
。
比如w
的计算需要使用a
和b
,d
需要使用 c
和 e
使得 w = a *q ^ b
和 d = c * q ^ e
。更进一步,q
是一个分位数,所以我其实想要w50
,w90
等,会对应到q50
、q90
等来自 df。
在我看来,棘手的部分是在不使用嵌套循环的情况下设置使用 a & b 与 c & d 的条件。
我有一个函数可以使用适当的列来计算 vars
,但是我无法有效地将所有部分组合在一起。
#function to calculate the w, d
calc_wd <- function(df,col_name,col1,col2,col3){
#Calculate and create new column col_name for each combo of var and quantile, e.g. "w_50", "d_50", etc.
df[[col_name]] <- df[[col1]] * (df[[col2]] ^ (df[[col3]]))
df
}
我可以让它适用于单个案例,但不能通过自动进行系数交换...您会看到我在下面指定了“a”和“b”。
wd<-c("w_","d_")
make_wd_list<-apply(expand.grid(wd, quantiles), 1, paste,collapse="")
calc_wdv(df,make_wd_list[1],"a",paste0("q",sapply(strsplit(make_wd_list[1],"_"),tail,1)),"b")
或者,我尝试使用嵌套的 for 循环来完成这项工作,但似乎无法正确附加数据。而且很丑。
var=c("w","d")
dataf<-data.frame()
for(j in unique(var)){
if(j=="w"){
coeff1="a"
coeff2="b"
}else if(j=="d"){
coeff1="c"
coeff1="e"
}
print(coeff1)
print(coeff2)
for(k in unique(quantiles)){
dataf<-calc_wd(df,paste0(j,k),coeff1,paste0("q",k),coeff2)
dataf[k,j]=rbind(df,dataf) #this aint right. tried to do.call outside, etc.
}
}
最后,我希望有 w_50
、w_90
等新列,它们使用 q50
、q90
和最初定义的相应系数。
最佳答案
我发现一种易于输入的方法是使用 purrr::pmap
。我喜欢这样,因为当您使用 with(list(...),)
时,您可以按名称访问 data.frame
的列名。此外,您可以提供其他参数。
library(purrr)
pmap_df(df, quant = "q90", ~with(list(...),{
list(w = a * get(quant) ^ b, d = c * get(quant) ^ e)
}))
## A tibble: 20 x 2
# w d
# <dbl> <dbl>
# 1 0.239 0.295
# 2 0.152 0.392
# 3 0.476 0.828
# 4 0.344 0.236
# 5 0.439 1.00
您可以将其与第二个 map
调用结合使用以迭代分位数。
library(dplyr)
map(setNames(quantiles,quantiles),
~ pmap_df(df, quant = paste0("q",.x),
~ with(list(...),{list(w = a * get(quant) ^ b, d = c * get(quant) ^ e)}))
) %>% do.call(cbind,.)
# 50.w 50.d 90.w 90.d
#1 0.63585897 0.11045837 1.7276019 0.1784987
#2 0.17286184 0.22033649 0.2333682 0.5200265
#3 0.32437528 0.72502654 0.5722203 1.4490065
#4 0.68020897 0.33797621 0.8749206 0.6179557
#5 0.73516886 0.38481785 1.2782923 0.4870877
然后分配一个自定义函数就很简单了。
calcwd <- function(df,quantiles){
map(setNames(quantiles,quantiles),
~ pmap_df(df, quant = paste0("q",.x),
~ with(list(...),{list(w = a * get(quant) ^ b, d = c * get(quant) ^ e)}))
) %>% do.call(cbind,.)
}
关于r - 在 R 中寻找适用于嵌套 for 循环情况的 apply、tidyr 或 dplyr 解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61487002/