【问题标题】:R. Run optimization function in data frameR. 在数据框中运行优化函数
【发布时间】:2018-11-16 19:07:53
【问题描述】:

我在 R 中有一个数据框 df1,看起来像这样(所有值都是随机选择的,但近似值来自真实数据):

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 ... ...

编辑:(澄清)

我的问题是如何在给定 H(以及上述条件)的情况下找到产生最低 G1 的 z 并得到 G1。

【问题讨论】:

  • 为什么不先创建H,然后创建G,然后创建G1?在 R 中,您可以跨列运行算术运算。不清楚您所说的 Z 是什么意思。
  • 如果您的数据框名为df,那么只需执行df$G = (df$B - df$C)^2 - df$B...
  • 你好@DanY,是的,我知道怎么做你提到的。我需要在给定 H 和最低 z 的情况下获得 G1。请参阅编辑
  • “最低的G1”是什么意思?每一行都不一样,对吧?有没有一个目标,你想最小化 G1 和其他东西之间的平方和误差?或者最小化 G1 的总和? G1的产品? G1^2的总和?此外,您多次提到“最低z” - 您是指z 的值对应于G1 的最小化(未指定功能)吗?还是别的什么?
  • 我建议查看 optim 而不是尝试编写自己的优化例程,但 optim 可以最大限度地减少 单个值,正如我的以前的评论我不明白你想最小化什么。

标签: r dataframe mathematical-optimization


【解决方案1】:

考虑通过您的 G1 函数使用数据框提供的所有其他参数循环从 0.01 到 1 的 0.01 的倍数。然后取返回值向量的最小值。

具体来说,您可以设置一个函数,使用 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)
}

数据框调用 (使用base的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

【讨论】:

  • 你好@Parfait,“主”函数中有一些东西我并不完全清楚。它在哪里指示返回给定 z 的最低 G1 值?在 Python 脚本中,您有“返回 G1”。我在“主要”中不需要类似的东西吗?非常感谢
  • 在 R 中,return() 是可选的,因为函数将返回最后一行(即 G1 对象)。
  • 您好@Parfait,我意识到您的解决方案存在错误。我要求以 0.01 为间隔的 z 值。但是,如果我在“main”函数中将 seq(0, 1) 替换为 seq(0, 1, 0.01),我会得到完全相同的 z 结果(请查看 z 值
  • R 的 optimize 中的 interval 只接受端点,因此 seq(0,1) 被读作 c(0,1)。要遍历每个间隔,请考虑构建一个向量/列表,然后返回此向量/列表的最小值。请参阅 R sapply 和 Python 列表理解的更新。
  • 嗨@Parfait。我仍然得到 z 值
【解决方案2】:

添加z 列,进行计算,找出每组中的最小值。在问题Cross join with 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)

【讨论】:

  • 谢谢@Gregor,您的解决方案也很好用,但 Parfait 先发布了解决方案
猜你喜欢
  • 1970-01-01
  • 2017-02-17
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
相关资源
最近更新 更多