在R中多次循环后填充数据帧

时间:2019-03-17 10:41:47

标签: r loops dataframe for-loop fill

我正在执行多个循环,我想创建一个具有不同结果的数据框。

MWE如下:

# define cases 
debt   <-c(0,0.05) 
thetas <- c(1, 1.5) 
rhos   <- c(0, 0.99, 2) # 0:C-D case, 1 = linear (no effect on prices)%

然后要遍历以上向量

for (theta in thetas){
  for (rho in rhos){
    for (b in debt) {
      sols <-nleqslv(0.05, k_ss) # k_ss is defined in the end
      kss  <-round(sols$x,5)
    }
  }
} 

我希望在每次迭代中存储kss值并创建一个数据框,该数据框本质上应在一个易于理解的数据框中汇总所有可能的(i.e. length(theta)*length(rho)*length(debt) = 12 in this example)组合。

我的预期结果应如下所示:

thetas <- c(1, 1.5) 
rhos   <- c(0,0.99, 2) # 0:C-D case, 1 = linear (no effect on prices)%
debts   <-c(0,0.05) 

n = length(debt)*length(thetas)*length(rhos)

theta<-c(rep(1,6),rep(1.5,6))
rho  <-c(rep(0,2),rep(0.99,2), rep(2,2), rep(0,2),rep(0.99,2), rep(2,2))
debt <-rep(c(0,0.05),6)
kss  <-rnorm(12,0,1)  # suppose these are my true ('expected' kss valuesthat i get for the iterations

df   <- data.frame(theta,rho,debt,kss)

 df
   theta  rho debt     kss
1    1.0 0.00 0.00  1.1090
2    1.0 0.00 0.05  1.8436
3    1.0 0.99 0.00  0.7718
4    1.0 0.99 0.05  0.5628
5    1.0 2.00 0.00 -1.1774
6    1.0 2.00 0.05  2.1973
7    1.5 0.00 0.00  0.8531
8    1.5 0.00 0.05 -0.1252
9    1.5 0.99 0.00  0.4784
10   1.5 0.99 0.05  1.8334
11   1.5 2.00 0.00  0.3693
12   1.5 2.00 0.05  1.0470

仅作记录我的kss的生成方式

# compute steady state 



k_ss<-function(k){
  # this function is defined for given values in b, theta, rho 
  # all other variables not defined here are some scalars not defined here 
  # for simplicity 

  if (rho == 0){
    R <- A*alpha*k^(alpha-1)      
    w <- A*(1-alpha)*k^(alpha)    

  } else{
    y  <-A*(alpha*k^rho + (1-alpha))^(1/rho)
    R  <- A*alpha*(y/A*k)^(1-rho)           
    w  <- A*(1-alpha)*(y/A)^(1-rho)  

   }

  kt  <-nn*(dt/beta*nn)^(1/theta)
  sd  <-((beta*R)^(1/theta))*(1+kt)/(R+(beta*R)^(1/theta)*(1+kt))
  mpb <-(1/nn)*(kt/(1+kt))
  ego <-sd/(1-sd*mpb*R)

  kss <-(nn)*(k+b) - (ego*(w-(R-nn)*b))

  return(kss)

}

然后:

sols <-nleqslv(0.05, k_ss)
      kss  <-round(sols$x,5)

3 个答案:

答案 0 :(得分:1)

如果kss只是debtrhotheta的总和,则可以很容易地做到这一点:

thetas <- c(1, 1.5) 
rhos   <- c(0, 0.99, 2)
debts   <-c(0, 0.05)

df <- expand.grid(theta = thetas, rho = rhos, debt =debts)

non_linear_equation_solver <- function(theta, rho, debt) {
  kss <- (theta + rho + debt) # for example
  return(kss)
}

df$kss <- apply(df, 1, function(x) non_linear_equation_solver(x[1], x[2], x[3]))

df
#>    theta  rho debt  kss
#> 1    1.0 0.00 0.00 1.00
#> 2    1.5 0.00 0.00 1.50
#> 3    1.0 0.99 0.00 1.99
#> 4    1.5 0.99 0.00 2.49
#> 5    1.0 2.00 0.00 3.00
#> 6    1.5 2.00 0.00 3.50
#> 7    1.0 0.00 0.05 1.05
#> 8    1.5 0.00 0.05 1.55
#> 9    1.0 0.99 0.05 2.04
#> 10   1.5 0.99 0.05 2.54
#> 11   1.0 2.00 0.05 3.05
#> 12   1.5 2.00 0.05 3.55

reprex package(v0.2.1)于2019-03-17创建

答案 1 :(得分:1)

使用/application中的pmappurrr中的mutate的一种可能的解决方案如下。在这里,您可以将dplyr替换为您要完成的所有操作。请注意,my_function期望返回一个双精度数,但是您也可以使用pmap_dbl来返回一个列表。

pmap

library(dplyr) library(purrr) theta <- c(1, 1.5) rho <- c(0, 0.99, 2) debt <- c(0, 0.05) my.df <- expand.grid(theta = theta, rho = rho, debt = debt) my_function <- function(theta, rho, debt) { kss <- theta + rho + debt } my.df %>% mutate(kss = pmap_dbl(list(theta = theta, rho = rho, debt = debt), my_function)) %>% arrange(theta, rho, debt) # theta rho debt kss # 1 1.0 0.00 0.00 1.00 # 2 1.0 0.00 0.05 1.05 # 3 1.0 0.99 0.00 1.99 # 4 1.0 0.99 0.05 2.04 # 5 1.0 2.00 0.00 3.00 # 6 1.0 2.00 0.05 3.05 # 7 1.5 0.00 0.00 1.50 # 8 1.5 0.00 0.05 1.55 # 9 1.5 0.99 0.00 2.49 # 10 1.5 0.99 0.05 2.54 # 11 1.5 2.00 0.00 3.50 # 12 1.5 2.00 0.05 3.55 替换您指定的循环。它采用一个函数并将其应用于data.frame pmap的每一行,并使用列表中指定的参数作为该函数的参数。

使用my.df,可以订购原始订单。

答案 2 :(得分:0)

我找到了另一个非常直观的解决方案:

首先,@ kath建议定义一个通用函数,该函数将要循环的参数作为输入:

my_function <- function(theta, rho, debt) {
  kss <- (theta + rho + debt) 
}

然后可以如下构造所请求的数据框:

output<-list() # create an empty list 
i     <-0   # counter 

for (theta in thetas){
  for (rho in rhos){
    for (b in debt) {
      i=i+1
      kss<-my_function(theta,rho,b)
      output[[i]]<-data.frame(Theta = theta, Rho = rho, Debt = b, K = kss)
    }
  }
} 

然后绑定列表中的数据框:

df<-do.call(rbind,output)

And here is the result: 

Theta  Rho Debt    K
1    1.0 0.00 0.00 1.00
2    1.0 0.00 0.05 1.05
3    1.0 0.99 0.00 1.99
4    1.0 0.99 0.05 2.04
5    1.0 2.00 0.00 3.00
6    1.0 2.00 0.05 3.05
7    1.5 0.00 0.00 1.50
8    1.5 0.00 0.05 1.55
9    1.5 0.99 0.00 2.49
10   1.5 0.99 0.05 2.54
11   1.5 2.00 0.00 3.50
12   1.5 2.00 0.05 3.55
>