r - 在 R 中寻找适用于嵌套 for 循环情况的 apply、tidyr 或 dplyr 解决方案

标签 r for-loop dplyr nested apply

奇怪的是,我认为通过查看 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的计算需要使用abd需要使用 ce 使得 w = a *q ^ bd = c * q ^ e。更进一步,q是一个分位数,所以我其实想要w50w90等,会对应到q50q90 等来自 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_50w_90 等新列,它们使用 q50q90 和最初定义的相应系数。

最佳答案

我发现一种易于输入的方法是使用 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/

相关文章:

r - 如何在 R 中一次删除多列的单个列中的重复值

python - 从文本文件输入中删除重复的单词?

r - 有条件改变或不改变组中的所有变量

R:使用 eval() 的 dbplyr

java - 将 stringbuilder 与 for 循环一起使用

r - 为什么 .env 代词在 dplyr::slice_max 中不起作用?

r - 使用动态列名以编程方式分配 data.table 中的列

r - 将图另存为pdf,并同时在窗口(x11)中显示

r - 嵌入 R 包中的 Shiny 应用程序和数据

java - Java元音计数器的问题