BurninLeo
BurninLeo

Reputation: 4484

How to apply a formula to a vector in R?

not for the first time, I guess that the answer is quite simple. But searching for R solutions is regularly hard work and after two hours its probably at time to ask someone...

I am working with a non-linear formula (this is only the first work on it, it will actually become non-linear soon) and to test my initial values, i would like to simply calculate the values over a series of x values.

Here is some code:

x <- c(1,2,3,4,5,6,7,8,9,10,11,12) #etc
y <- c(NA,332,248,234,84,56,26,24,27,33,37,25) #etc
# This is my formula I shall soon expand
fEst <- y ~ 1 / (x / a + 1) * b
# Initial value
a <- 800
# Initial value based on inverted formula and second measure
b <- y[2] * (x[2] / a + 1)

# Can i use my formula fEst to do this step?
p <- 1 / (x / a + 1) * b

The point is that I am working on the formula - and it seems strange to make each change, twice...

What I found was a package nls2 where something like this was possible and a function apply.a.formula which seems to be an element from another package - but as this is a very basic use of a function, I guess that the R base packe already has the appropriate functions. Just ... where?

Thanks!

Upvotes: 2

Views: 7235

Answers (1)

Gavin Simpson
Gavin Simpson

Reputation: 174948

I came across this thread whilst looking up the avenues you'd tried and the solution posted by Gabor. Note that apply.a.formula() is a made up function name that the OP in the thread was looking to find a real function for.

Using the example that Gabor provided in the thread this is a solution using the nls2 package:

## your data
x <- c(1,2,3,4,5,6,7,8,9,10,11,12) #etc
y <- c(NA,332,248,234,84,56,26,24,27,33,37,25) #etc
# This is my formula I shall soon expand
fEst <- y ~ 1 / (x / a + 1) * b
# Initial value
a <- 800
# Initial value based on inverted formula and second measure
b <- y[2] * (x[2] / a + 1)

## install.packages("nls2", depend = TRUE) if not installed
require(nls2)
fitted(nls2(fEst, start = c(a = a, b = b), alg = "brute"))

The last line gives:

R> fitted(nls2(fEst, start = c(a = a, b = b), alg = "brute"))
 [1] 332.4145 332.0000 331.5866 331.1741 330.7627 330.3524 329.9430 329.5347
 [9] 329.1273 328.7210 328.3157 327.9113
attr(,"label")
[1] "Fitted values"

which is essentially the same as 1 / (x / a + 1) * b would give:

R> 1 / (x / a + 1) * b
 [1] 332.4145 332.0000 331.5866 331.1741 330.7627 330.3524 329.9430 329.5347
 [9] 329.1273 328.7210 328.3157 327.9113

From the comments, Carl Witthoft notes that if you want to generalise equations like 1 / (x / a + 1) * b then a function might be a useful way of encapsulating the operation without typing out 1 / (x / a + 1) * b every time. For example

myeqn <- function(a, b, x) { 1 / (x / a + 1) * b }

R> myeqn(a, b, x)
[1] 332.4145 332.0000 331.5866 331.1741 330.7627 330.3524 329.9430 329.5347
[9] 329.1273 328.7210 328.3157 327.9113

Upvotes: 3

Related Questions