Shenbo
Shenbo

Reputation: 226

Create a function from a vector to another

I have two vectors:

x <- c(-2.0,-1.75,-1.50,-1.25,-1.00,-0.75,-0.50,-0.25,0.00,0.25,0.50,0.75,1.00,1.25,1.50,1.75,2.00,2.25,2.50,2.75)
y <- c(37.0000,24.1602,15.06250,8.91016,5.00000,2.72266,1.56250,1.09766,1.00000,1.03516,1.06250,1.03516,1.00000,1.09766,1.56250,2.72266,5.00000,8.91016,15.06250,24.16016)

I am trying to create a function that given a number from vector x, it returns the corresponding y value(same index). For example, func(-2.0) should return 37.0000.

Currently I have this super ugly function that I don't think is what I am supposed to do:

func1 <- function(x) {
  if (x==-2.0) {return (37.0000)}
  else if (x==-1.75){return (24.1602)}
  else if (x==-1.50){return (15.06250)}
  else if (x==-1.25){return (8.91016)}
  else if (x==-1.00){return (5.00000)}
  else if (x==-0.75){return (2.72266)}
  else if (x==-0.50){return (1.56250)}
  else if (x==-0.25){return (1.09766)}
  else if (x==0.00){return (1.00000)}
  else if (x==0.25){return (1.03516)}
  else if (x==0.50){return (1.06250)}
  else if (x==0.75){return (1.03516)}
  else if (x==1.00){return (1.00000)}
  else if (x==1.25){return (1.09766)}
  else if (x==1.50){return (1.56250)}
  else if (x==1.75){return (2.72266)}
  else if (x==2.00){return (5.00000)}
  else if (x==2.25){return (8.91016)}
  else if (x==2.50){return (15.06250)}
  else if (x==2.75){return (24.16016)}
  else {return (Inf)}
}

Upvotes: 1

Views: 50

Answers (4)

Andrie
Andrie

Reputation: 179428

You seem to be doing an interpolation. The R function for interpolation is approx().

approx(x, y, xout = -2)

$x
[1] -2

$y
[1] 37

In practise it's easier to create an interpolation function using approxfun(). Try this:

foo <- approxfun(x, y)
foo(-2)
[1] 37

You should probably avoid using an exact matching strategy using == or match(). The reason is simple - if you use calculated values to find the index position, you could find that the match is inexact.

Compare:

y[ which(x == -2.0) ]
[1] 37

y[ which(x == -2.00000000001) ]
numeric(0)

Similarly:

y[match(-2.0, x)]
[1] 37

y[match(-2.0000000000001, x)]
[1] NA

Upvotes: 2

Colonel Beauvel
Colonel Beauvel

Reputation: 31171

For exact matching:

foo = function(u) {res=y[pmatch(u,x)];ifelse(is.na(res), Inf, res)}
#> foo(-2)
#[1] 37
#> foo(-1.8)
#[1] Inf
#> foo(-4)
#[1] Inf

Not sure about what you need but beware you can use linear interpolation (you can put method as constant instead of linear):

foo = approxfun(x,y, yleft=Inf, yright=Inf)
#> foo(-2)
#[1] 37
#> foo(-1.8)
#[1] 26.72816
#> foo(-4)
#[1] Inf

In this last case, the value is not Inf in the boundary domain defined by x.

Upvotes: 2

moodymudskipper
moodymudskipper

Reputation: 47320

You don't really need a function for this, I suggest you just use:

y[x == -1.75]

x == -1.75 returns a boolean vector so it will pick the right value for y.

If you really want a function:

f <- function(x,y,xi){
return(y[x == xi])
}

Upvotes: 0

Adam Quek
Adam Quek

Reputation: 7153

Since x and y are the same length, put x as names of y

names(y)<-x
y

      -2    -1.75     -1.5    -1.25       -1    -0.75     -0.5    -0.25        0     0.25      0.5     0.75        1     1.25      1.5     1.75        2 
37.00000 24.16020 15.06250  8.91016  5.00000  2.72266  1.56250  1.09766  1.00000  1.03516  1.06250  1.03516  1.00000  1.09766  1.56250  2.72266  5.00000 
    2.25      2.5     2.75 
 8.91016 15.06250 24.16016 

This way, you can call by the names, e.g.

y["-2"]

-2 
37

y["-1.75"]

-1.75 
24.1602 

Upvotes: 0

Related Questions