R. Запустите функцию оптимизации во фрейме данных. - PullRequest
0 голосов
/ 16 ноября 2018

У меня есть кадр данных df1 в R, который выглядит следующим образом (все значения были выбраны случайным образом, но приблизительные значения из реальных данных):

A B    C    D   E   F      G     H
a 0.04 0.01 50  70  0.01   ...   0.0002
b 0.03 0.1  49  69  0.01   ...   0.0003
c 0.03 0.02 51  71  0.005  ...   0.004
d 0.04 0.02 50  70  0.006  ...   0.0005

G получается следующим образом:

# Equation 1:

G = (B - C)^2 - B*(1 - B)/(D- 1) - C*(1 - C)/(E - 1)

library(dplyr)
df2 = df1 %>% mutate(G = (B - C)^2 - B*(1 - B)/(D- 1) - C*(1 - C)/(E - 1))

Я хочу создать новый столбец G1, применяя функцию оптимизации в каждой строке.

G1 получается с использованием уравнения 1, но замена B на H. H получается с использованием уравнения 2:

# Equation 2:

H = (B - z*F)/(1 - z)

Я хотел бы создать новый столбец Z со значением z в диапазоне от 0 до 1 (шаг = 0,01), который дает наименьшее значение G1.

Я ожидаю получить что-то вроде этого:

A B    C    D   E   F      G     H      G1  Z
a 0.04 0.01 50  70  0.01   ...   0.0002 ... ...
b 0.03 0.1  49  69  0.01   ...   0.0003 ... ...
c 0.03 0.02 51  71  0.005  ...   0.004  ... ...
d 0.04 0.02 50  70  0.006  ...   0.0005 ... ...

РЕДАКТИРОВАТЬ: (уточнение)

Мой вопрос заключается в том, как найти z, которое дает наименьшее значение G1 для заданного значения H (и условия, указанные выше), а также получить значение G1.

Ответы [ 2 ]

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

Рассмотрите возможность циклического перебора множителей 0,01 от 0,01 до 1 с помощью функции G1 со всеми другими параметрами, предоставляемыми фреймом данных.Затем возьмите минимум возвращенного вектора значений.

В частности, вы можете настроить функцию, которая передает в строке значения, используя mapply (элементная функция итератора) и возвращает минимум для z значение.

Данные (F изменено на F_ во избежание проблем с FALSE)

txt <- "A B    C    D   E   F_
a 0.04 0.01 50  70  0.01  
b 0.03 0.1  49  69  0.01  
c 0.03 0.02 51  71  0.005 
d 0.04 0.02 50  70  0.006"

df <- read.table(text=txt, header=TRUE)

Функция

main <- function(B_param, C_param, D_param, E_param, F_param) {

  # EXTENDED G1 FUNCTION (WITH HELPER H)
  func <- function(z) {
    H <- (B_param - z*F_param)/(1 - z)
    G1 <- (H - C_param)^2 - H*(1 - H)/(D_param- 1) - C_param*(1 - C_param)/(E_param - 1)
  }

  # ITERATE THROUGH 0.01 MULTIPLES 
  tmp <- sapply(seq(0.01, 0.99, 0.01), func)

  # RETURN Z AT THE MINIMUM OF VECTOR OF VALUES
  min_z <- seq(0.01, 0.99, 0.01)[which.min(tmp)]

  return(min_z)
}

вызов фрейма данных (с использованием базовых within для добавления новых столбцов)

final_df <- within(df, {

  G <- (B - C)^2 - B*(1 - B)/(D- 1) - C*(1 - C)/(E - 1)

  # CALCULATE z BY PASSING COLUMN VALUES ELEMENTWISE
  z <- mapply(main, B, C, D, E, F_)
  H <- (B - z*F_)/(1 - z)
  G1 <- (H - C)^2 - H*(1 - H)/(D- 1) - C*(1 - C)/(E - 1)      
})

options(scipen=999)

# RE-ORDER COLUMNS
final_df[order(names(final_df))]
#   A    B    C  D  E    F_              G             G1          H    z
# 1 a 0.04 0.01 50 70 0.010 -0.00002715173 -0.00001456576 0.04030303 0.01
# 2 b 0.03 0.10 49 69 0.010  0.00297022059 -0.00326311275 0.11000000 0.80
# 3 c 0.03 0.02 51 71 0.005 -0.00076200000 -0.00076163193 0.03025253 0.01
# 4 d 0.04 0.02 50 70 0.006 -0.00066773144 -0.00066032187 0.04034343 0.01
0 голосов
/ 17 ноября 2018

Добавьте столбец z, сделайте расчет, найдите минимум в каждой группе.Как и в вопросе Перекрестное соединение с dplyr , мы добавляем фиктивный столбец, чтобы присоединиться к нему для создания перекрестного соединения.

df2 %>% mutate(cj = 1) %>%
  full_join(data.frame(cj = 1, z = seq(0, 1, by = 0.01)) %>%
  select(-cj) %>%
  mutate(H = (B - z*F)/(1 - z),
         G1 = (H - C)^2 - H*(1 - H)/(D- 1) - C*(1 - C)/(E - 1)) %>%
  group_by(A, B, C, D, E, F) %>%
  arrange(G1) %>%
  slice(1)
...