Итерация функции оптимизации по строкам CSV - PullRequest
0 голосов
/ 29 октября 2018

Что-то в том, как я написал эту функцию оптимизации, не позволяет ей ссылаться на существующие значения в моем наборе данных «Вход», чтобы заполнить новый столбец «Опция»:

Input=read.csv("....csv")
Input$Opt=0
Input$Opt <- optimize(f = function(x) abs(10.16 - KozakTaper(Bark='ob',
                                                SPP=Input$Species,
                                                DHT=x,
                                                DBH=Input$DBH,
                                                HT=Input$Ht,
                                                Planted=0)),
         lower=Input$Ht*.25, upper=Input$Ht+1,
         maximum = FALSE,  tol = .Machine$double.eps^0.25)[[1]]

Я получаю ошибку

неверное значение функции в 'optimize'

Вот краткое определение "KozakTaper", поэтому у вас есть некоторый контекст для того, что я пытаюсь сделать. Хитрость и то, почему мне нужно использовать optimize или что-то в этом роде, заключается в том, что я не хочу y (именно это возвращает KozakTaper). Я хочу знать, что такое DHT, если y = 10,16, но поскольку уравнение нельзя переставить, чтобы решить для DHT, я использую функцию оптимизации, чтобы вернуть значение DHT, которое минимизирует разницу между y и 10,16.

KozakTaper=function(Bark,SPP,DHT,DBH,HT,Planted){
  if(Bark=='ob' & SPP=='AB'){
    a0_tap=1.0693567631
    a1_tap=0.9975021951
    a2_tap=-0.01282775
    b1_tap=0.3921013594
    b2_tap=-1.054622304
    b3_tap=0.7758393514
    b4_tap=4.1034897617
    b5_tap=0.1185960455
    b6_tap=-1.080697381
    b7_tap=0}
  else if(Bark=='ob' & SPP=='RS'){
    a0_tap=0.8758
    a1_tap=0.992
    a2_tap=0.0633
    b1_tap=0.4128
    b2_tap=-0.6877
    b3_tap=0.4413
    b4_tap=1.1818
    b5_tap=0.1131
    b6_tap=-0.4356
    b7_tap=0.1042}
  else{
    a0_tap=1.1263776728
    a1_tap=0.9485083275
    a2_tap=0.0371321602
    b1_tap=0.7662525552
    b2_tap=-0.028147685
    b3_tap=0.2334044323
    b4_tap=4.8569609081
    b5_tap=0.0753180483
    b6_tap=-0.205052535
    b7_tap=0}
  p = 1.3/HT
  z = DHT/HT
  Xi = (1 - z^(1/3))/(1 - p^(1/3))
  Qi = 1 - z^(1/3)
  y = (a0_tap * (DBH^a1_tap) * (HT^a2_tap)) * Xi^(b1_tap * z^4 + b2_tap * (exp(-DBH/HT)) +
                                                    b3_tap * Xi^0.1 + b4_tap * (1/DBH) + b5_tap * HT^Qi + b6_tap * Xi + b7_tap*Planted)
  return(y=round(y,4))}

Если у вас другой подход к поиску DHT для каждой строки данных, я открыт для других предложений. Стратегия оптимизации отлично работает для одной точки данных (дерева заданных видов, диаметра и высоты), но, поскольку я вставил ссылки на имена столбцов, возникает ошибка. Все советы о том, что нужно изменить, приветствуются!

-KB

научный сотрудник Аппалачского горного клуба

Упрощенный пример ввода данных:

> dput(head(Input))
structure(list(Species = structure(c(3L, 3L, 3L, 3L, 8L, 8L), .Label = c("AB", 
"BC", "BF", "EH", "PB", "PR", "RM", "RS", "SM", "ST", "WA", "WP", 
"YB"), class = "factor"), DBH = c(6.9000001, 8.1000004, 5.8000002, 
6.5999999, 9.5, 7.5999999), Ht = c(44, 43, 34, 41, 56, 58)), .Names = c("Species", 
"DBH", "Ht"), row.names = c(NA, 6L), class = "data.frame")

1 Ответ

0 голосов
/ 24 ноября 2018

Ваша функция f возвращает вектор, а не скаляр, поскольку вы применяете его ко всему фрейму данных. optimize не может работать с векторными функциями, поэтому выводит сообщение «неверное значение функции».

Вместо этого я предполагаю, что вы хотите найти оптимизирующее решение для каждой строки фрейма данных. Тогда просто сделай это.

Bark='ob'; Planted=0
for (i in 1:6) {
SPP=Input$Species[i]; DBH=Input$DBH[i]; HT=Input$Ht[i]; 
f <- function(x) abs(10.16 - KozakTaper(Bark,SPP,x,DBH,HT,Planted))
o <- optimize(f, lower=Input$Ht[i]*.25, upper=Input$Ht[i]+1,
              maximum = FALSE,  tol = .Machine$double.eps^0.25)
cat(o$minimum, '  ')
}
## 11.00059   10.75038   8.500041   10.25055   26.2004   26.75473

(я изменил '&' на '&&' в функции KozakTaper, чтобы избежать предупреждений.)

...