迭代地对数据帧的每一行应用优化函数
Apply optim function on iteratively each row of dataframe
我有一个适用于单行的 optim
函数。
optim
函数通过最小化残差来估计化学数据中的矿物比例。
我想对数据框中的每一行应用相同的函数(实际上可能有大量行)。
我尝试使用 dplyr
中的 rowwise,但它不正确。
数据:
以下理想矿物成分的数据框:
Min_comp <- tibble::tribble(
~SiO2, ~TiO2, ~Al2O3, ~Fe2O3, ~MnO, ~MgO, ~CaO, ~Na2O, ~K2O, ~P2O5, ~CO2, ~S,
100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64.8, 0, 18.3, 0, 0, 0, 0, 0, 16.9, 0, 0, 0,
0, 0, 0, 0, 0, 0, 54.7, 0, 0, 41.7, 0, 0,
0, 0, 0, 103.45, 0, 0, 0, 0, 0, 0, 0, 0,
51.4, 0, 0, 42.7, 0, 0, 0, 6.6, 0, 0, 0, 0,
0, 0, 0, 17.9, 0, 10.1, 28, 0, 0, 0, 0, 0,
0, 0, 0, 66.6, 0, 0, 0, 0, 0, 0, 0, 53.4
)
矿物比例的初步估计
Min_Est <- tibble::tribble(
~Quartz, ~K.feldspar, ~Apatite, ~Magnetite, ~Riebeckite, ~Ankerite, ~Pyrite,
39.4, 4.3, 0, 25.4, 9.3, 4.9, 0
)
实际化学成分:
Act_comp <- tibble::tribble(
~SiO2, ~TiO2, ~Al2O3, ~Fe2O3, ~MnO, ~MgO, ~CaO, ~Na2O, ~K2O, ~P2O5, ~CO2, ~S,
46.91, 0.02, 0.88, 31.2, 0.05, 2.33, 0.73, 0.62, 0.61, 0.25, 0, 0.05
)
待优化函数(单行):
Mineral_Estimation_opt <- function(MinProp, par, Actual){
return(sum(Actual-(colSums(as.matrix(MinProp/100*par[1:7]))))^2)
}
功能优化
# start parameters
start <- c(40,5, 3, 30, 5, 1, 3) # estimate realistic parameters
# order of values qtz, k.feld, apatite, magnetite, riebeckite, ankerite, pyrite
result <- optim(par = start, fn = Mineral_Estimation_opt, MinProp = Min_comp, Actual = Act_comp,method = "L-BFGS-B", lower = c(0), upper = c(100), control = list(maxit = 1000))
result
上面的代码有效,现在是 Act_comp 数据帧中有多行数据的示例:
Act_comp_rows <- tibble::tribble(
~SiO2, ~TiO2, ~Al2O3, ~Fe2O3, ~MnO, ~MgO, ~CaO, ~Na2O, ~K2O, ~P2O5, ~CO2, ~S,
48.707, 0.027, 1.395, 27.81, 0.079, 3.577, 0.863, 0.297, 0.308, 0.15, 0L, 0.062,
49.324, 0.018, 0.559, 30.98, 0.016, 2.115, 0.621, 0.567, 0.461, 0.31, 0L, 0.017,
46.919, 0.021, 0.955, 31.35, 0.07, 2.688, 0.547, 0.566, 0.572, 0.303, 0L, 0.032
)
我可以通过添加rowSums来获得数据框每一行的数据残差:
Mineral_Estimation_opt <- function(MinProp, par, Actual){
return(rowSums(Actual-(colSums(as.matrix(MinProp/100*par[1:7]))))^2)
}
result <- optim(par = start, fn = Mineral_Estimation_opt, MinProp = min_comp1, Actual = act_comp1,method = "L-BFGS-B", lower = c(0), upper = c(100), control = list(maxit = 1000))
但是,当尝试重新运行 optim
函数时 returns 出现错误
Error in optim(par = start, fn = Mineral_Estimation_opt, MinProp = Min_comp, :
objective function in optim evaluates to length 3 not 1
由于它不是按行计算的。
为数据帧的每一行计算此函数的最佳方法是什么。
非常感谢
马特
您可以使用函数 purrr::map
并遍历 Min_comp
.
的行
results
将是一个包含每一行结果的列表。
results <- purrr::map(
seq_len(nrow(Min_comp)),
function(line_nb) {
start <- c(40,5, 3, 30, 5, 1, 3)
optim(par = start,
fn = Mineral_Estimation_opt,
MinProp = Min_comp,
Actual = Min_comp[line_nb,],
method = "L-BFGS-B",
lower = c(0),
upper = c(100),
control = list(maxit = 1000))})
map
函数作为一个循环工作,但同时它将每次迭代的输出收集为一个列表。
我有一个适用于单行的 optim
函数。
optim
函数通过最小化残差来估计化学数据中的矿物比例。
我想对数据框中的每一行应用相同的函数(实际上可能有大量行)。
我尝试使用 dplyr
中的 rowwise,但它不正确。
数据:
以下理想矿物成分的数据框:
Min_comp <- tibble::tribble(
~SiO2, ~TiO2, ~Al2O3, ~Fe2O3, ~MnO, ~MgO, ~CaO, ~Na2O, ~K2O, ~P2O5, ~CO2, ~S,
100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64.8, 0, 18.3, 0, 0, 0, 0, 0, 16.9, 0, 0, 0,
0, 0, 0, 0, 0, 0, 54.7, 0, 0, 41.7, 0, 0,
0, 0, 0, 103.45, 0, 0, 0, 0, 0, 0, 0, 0,
51.4, 0, 0, 42.7, 0, 0, 0, 6.6, 0, 0, 0, 0,
0, 0, 0, 17.9, 0, 10.1, 28, 0, 0, 0, 0, 0,
0, 0, 0, 66.6, 0, 0, 0, 0, 0, 0, 0, 53.4
)
矿物比例的初步估计
Min_Est <- tibble::tribble(
~Quartz, ~K.feldspar, ~Apatite, ~Magnetite, ~Riebeckite, ~Ankerite, ~Pyrite,
39.4, 4.3, 0, 25.4, 9.3, 4.9, 0
)
实际化学成分:
Act_comp <- tibble::tribble(
~SiO2, ~TiO2, ~Al2O3, ~Fe2O3, ~MnO, ~MgO, ~CaO, ~Na2O, ~K2O, ~P2O5, ~CO2, ~S,
46.91, 0.02, 0.88, 31.2, 0.05, 2.33, 0.73, 0.62, 0.61, 0.25, 0, 0.05
)
待优化函数(单行):
Mineral_Estimation_opt <- function(MinProp, par, Actual){
return(sum(Actual-(colSums(as.matrix(MinProp/100*par[1:7]))))^2)
}
功能优化
# start parameters
start <- c(40,5, 3, 30, 5, 1, 3) # estimate realistic parameters
# order of values qtz, k.feld, apatite, magnetite, riebeckite, ankerite, pyrite
result <- optim(par = start, fn = Mineral_Estimation_opt, MinProp = Min_comp, Actual = Act_comp,method = "L-BFGS-B", lower = c(0), upper = c(100), control = list(maxit = 1000))
result
上面的代码有效,现在是 Act_comp 数据帧中有多行数据的示例:
Act_comp_rows <- tibble::tribble(
~SiO2, ~TiO2, ~Al2O3, ~Fe2O3, ~MnO, ~MgO, ~CaO, ~Na2O, ~K2O, ~P2O5, ~CO2, ~S,
48.707, 0.027, 1.395, 27.81, 0.079, 3.577, 0.863, 0.297, 0.308, 0.15, 0L, 0.062,
49.324, 0.018, 0.559, 30.98, 0.016, 2.115, 0.621, 0.567, 0.461, 0.31, 0L, 0.017,
46.919, 0.021, 0.955, 31.35, 0.07, 2.688, 0.547, 0.566, 0.572, 0.303, 0L, 0.032
)
我可以通过添加rowSums来获得数据框每一行的数据残差:
Mineral_Estimation_opt <- function(MinProp, par, Actual){
return(rowSums(Actual-(colSums(as.matrix(MinProp/100*par[1:7]))))^2)
}
result <- optim(par = start, fn = Mineral_Estimation_opt, MinProp = min_comp1, Actual = act_comp1,method = "L-BFGS-B", lower = c(0), upper = c(100), control = list(maxit = 1000))
但是,当尝试重新运行 optim
函数时 returns 出现错误
Error in optim(par = start, fn = Mineral_Estimation_opt, MinProp = Min_comp, : objective function in optim evaluates to length 3 not 1
由于它不是按行计算的。
为数据帧的每一行计算此函数的最佳方法是什么。
非常感谢
马特
您可以使用函数 purrr::map
并遍历 Min_comp
.
results
将是一个包含每一行结果的列表。
results <- purrr::map(
seq_len(nrow(Min_comp)),
function(line_nb) {
start <- c(40,5, 3, 30, 5, 1, 3)
optim(par = start,
fn = Mineral_Estimation_opt,
MinProp = Min_comp,
Actual = Min_comp[line_nb,],
method = "L-BFGS-B",
lower = c(0),
upper = c(100),
control = list(maxit = 1000))})
map
函数作为一个循环工作,但同时它将每次迭代的输出收集为一个列表。