简体   繁体   English

从 2 个点在 R 中创建指数函数

[英]Create exponential function in R from 2 points

I would like to create an exponential function in R when only 2 points that the line passes through are given.当只给出直线通过的 2 个点时,我想在 R 中创建一个指数函数。 I'd like to use the basic f(x) = ab^x format.我想使用基本的 f(x) = ab^x 格式。 I understand how to do this by hand, by creating two equations and then separately solving for b and a, but I'm having issues coding this in R. For example, when I try to assign a variable with another variable in it, I get the "object not found error" on the first step of this process.我了解如何通过创建两个方程然后分别求解 b 和 a 来手动执行此操作,但是我在用 R 进行编码时遇到了问题。例如,当我尝试为一个变量分配另一个变量时,我在此过程的第一步中获取“找不到对象错误”。

x <- c(4, 3, 1.8, 1.1, .6, .3, .02) 
y <- c(2, 7, 16, 27, 40, 51, 66)  
df <- data.frame(x,y)
a <- df$y[1]/b^df$x[1]

Error: object 'b' not found

I understand why I'm getting this error, but I don't know a way around it.我明白为什么我会收到这个错误,但我不知道解决方法。

I could create an exponential model by only using the first 2 the points, but the coefficients are no where close to the actual data values.我可以仅使用前 2 个点来创建指数模型,但系数与实际数据值相差甚远。

expmod <- lm(log(df$y[1:2])~df$x[1:2])
exp(expmod$coefficients)

(Intercept)        df$x 
300.1250000   0.2857143

The intercept should be closer to 66 based on the data (y = 66, when x = 0.02)根据数据截距应该更接近66(y = 66,当x = 0.02时)

I eventually want to be able to use this function to take two points on a line and then both plot the line and produce values based on other x inputs (ie c(0,1,2,3,4)), but I'm running into trouble early on.我最终希望能够使用此函数在一条线上取两个点,然后绘制这条线并根据其他 x 输入(即 c(0,1,2,3,4))生成值,但是我我很早就遇到了麻烦。

edit: I am not necessarily trying to create a model from 2 points and expecting a great prediction.编辑:我不一定要尝试从 2 点创建模型并期待一个很好的预测。 I am trying do determine the exponential function of a line that passes through two points, similar to this , but coded in R. (The line won't be perfect, because it's made up data.)我正在尝试确定通过两点的直线的指数函数,类似于this ,但用 R 编码。(这条线不会是完美的,因为它是由数据组成的。)

The reason you are not getting the intercept you want is that the first two points in your data frame are not on the same exponential curve as the other points.您没有获得所需截距的原因是数据框中的前两个点与其他点不在同一指数曲线上。 We can see this by plotting log(y) against x :我们可以通过对x绘制log(y)来看到这一点:

plot(x, log(y))

在此处输入图片说明

Now let's draw the regression using only your first two points (the two rightmost points)现在让我们只使用前两个点(最右边的两个点)绘制回归

abline(lm(log(y) ~ x, data = df[1:2, ]), col = "red")

在此处输入图片说明

and add a line for the other 5 points:并为其他 5 个点添加一条线:

abline(lm(log(y) ~ x, data = df[-c(1:2), ]), col = "blue")

在此处输入图片说明

You can see that if we only use two points, then the gradient and intercept are very sensitive to any experimental deviations from a perfect exponential curve.你可以看到,如果我们只使用两个点,那么梯度和截距对任何与完美指数曲线的实验偏差都非常敏感。

There is a larger point here, which is that if you are trying to make predictions using only two experimental data points, then your predictions will not be very accurate.这里有一个更大的观点,那就是如果您试图仅使用两个实验数据点进行预测,那么您的预测将不会非常准确。

Conversely, if we use all the points, we get a reasonable prediction for the relationship as a whole:相反,如果我们使用所有的点,我们就可以对整个关系进行合理的预测:

plot(x, y)
lines(new_frame$x, new_frame$y, col = "red")

在此处输入图片说明

And the numerical prediction for the intercept is closer to your expectations:截距的数值预测更接近你的预期:

exp(lm(log(y) ~ x, data = df)$coef)
#> (Intercept)           x 
#>  68.2345853   0.4335491 

EDIT编辑

To calculate the equation "manually" from two points, you need to take the log of the y values, then you can calculate the gradient of the log line between two points by doing:要从两点“手动”计算方程,您需要取 y 值的对数,然后您可以通过执行以下操作来计算两点之间对数线的梯度:

gradient <- (log(y2) - log(y1)) / (x2 - x1)

and you can get the intercept by solving y = gradient * x + intercept for intercept , that is:并且您可以通过求解y = gradient * x + intercept来获得截距,即:

intercept <- log(y1) - gradient * x1

you can then exponentiate the gradient and the intercept to find the coefficients of your original line.然后,您可以对梯度和截距求幂以找到原始线的系数。 For example, using this function:例如,使用这个函数:

exp_line <- function(x1, x2, y1, y2) {
  gradient  <- (log(y2) - log(y1)) / (x2 - x1)
  intercept <- log(y1) - gradient * x1
  cat("y = ", exp(gradient), "^x * ", exp(intercept), "\n", sep = "")
}

We get我们得到

exp_line(x[1], x[2], y[1], y[2])
#> y = 0.2857143^x * 300.125

exp_line(x[4], x[5], y[4], y[5])
#> y = 0.455625^x * 64.10553

And if we want to draw an exponential curve between any two points, we can do the following:如果我们想在任意两点之间画一条指数曲线,我们可以这样做:

draw_exp_line <- function(x1, x2, y1, y2, col) {
  gradient  <- (log(y2) - log(y1)) / (x2 - x1)
  intercept <- log(y1) - gradient * x1
  x <- seq(0, 5, 0.1)
  lines(x, exp(gradient)^x * exp(intercept), col = col)
}

plot(x, y)
draw_exp_line(x[2], x[1], y[2], y[1], "red")

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM