thomas leon
thomas leon

Reputation: 153

Make a function to find the value of Y according to X value

Hello everybody,

data <- structure(list(nb_p = c(5, 35, 65, 95, 125, 155, 185, 215, 245, 
        275, 305, 335, 365, 395, 425, 455, 485, 515, 545, 575), nb_obs = c(0.467687074829932, 
        2.96031746031746, 4.97619047619048, 6.58134920634921, 7.84126984126984, 
        8.80328798185941, 9.5187074829932, 10.0325963718821, 10.3543083900227, 
        10.5379818594104, 10.5969387755102, 10.5603741496599, 10.4348072562358, 
        10.2539682539683, 10.0011337868481, 9.72675736961451, 9.41043083900227, 
        9.07568027210884, 8.72534013605442, 8.36649659863946), inf90 = c(0.440447845804989, 
        2.87573696145125, 4.85711451247166, 6.44331065759637, 7.68307823129252, 
        8.6342970521542, 9.31232993197279, 9.80609410430839, 10.1116496598639, 
        10.2891156462585, 10.346768707483, 10.2799886621315, 10.1522675736961, 
        9.95918367346939, 9.6920918367347, 9.41646825396825, 9.08503401360544, 
        8.75396825396825, 8.40578231292517, 8.01924603174603), sup90 = c(0.495493197278912, 
        3.05045351473923, 5.09481292517007, 6.73137755102041, 8.01360544217687, 
        8.98642290249433, 9.71496598639456, 10.2392573696145, 10.587358276644, 
        10.7700396825397, 10.8317176870748, 10.8084183673469, 10.6950396825397, 
        10.5011904761905, 10.2920068027211, 10.0045918367347, 9.70646258503401, 
        9.3702380952381, 9.01590136054422, 8.66785714285714)), row.names = c(NA, 
        -20L), class = c("tbl_df", "tbl", "data.frame"))

My plot :

g <- ggplot(data)
g + geom_ribbon(aes(x = nb_p, ymin = inf90, ymax = sup90), fill = "yellow") +
     geom_line(aes(x = nb_p, y =nb_obs)) + theme_bw()

I would like to do two things please. First, create a function that (i) when I give the "nb_p" it gives me a "nb_obs" and (ii) and vice versa. Secondly, I would like that when I give a "nb_p", draw a line (abbline) vertical "nb_p" and the line "nb_obs" corresponding horizontal. Thx !

Upvotes: 0

Views: 238

Answers (3)

Leonard Armstrong
Leonard Armstrong

Reputation: 75

Here is a solution to the first part of your question.

    f <- function(nb_p) {
      result = data[which(data$nb_p == nb_p), 'nb_obs']
      return (ifelse(length(result[[1]]) == 0, NaN, result))
    }

Upvotes: 1

January
January

Reputation: 17120

First one is more tricky than you know it. The reason is that both nb_p and nb_obs are doubles. The problem is as follows: you print the data, and see the following:

    nb_p nb_obs  inf90  sup90
   <dbl>  <dbl>  <dbl>  <dbl>
 1     5  0.468  0.440  0.495
 2    35  2.96   2.88   3.05 
 3    65  4.98   4.86   5.09

Say you wish to have the nb_p corresponding to nb_obs == 2.96. Seems easy enough:

> data %>% filter(nb_obs == 2.96) %>% pull(nb_p)
numeric(0)

Bummer! The problem is that you should never use == or %in% to compare doubles, because computers do not have infinite precision and you are always rounding up one way or the other. You could solve it for nb_p by converting the data to integer:

data$nb_p <- as.integer(data$nb_p)

It would make much more sense to get the given numbers based on the row number:

data %>% slice(2) %>% pull(nb_p)
data %>% slice(2) %>% pull(nb_obs)

I don't see much of a need of a special function to do this, though, but OK:

p2obs <- function(data, p) {
   data %>% filter(nb_p == p) %>% pull(nb_obs)
}

This one is a little bit more complicated because of the problem I mentioned before.

obs2p <- function(data, obs, eps=0.01) {
    data %>% filter(abs(nb_obs - obs) < eps) %>% pull(nb_p)

}

Regarding your second question.

g <- ggplot(data) g <- g + geom_ribbon(aes(x = nb_p, ymin = inf90, ymax = sup90), fill = "yellow") + geom_line(aes(x = nb_p, y =nb_obs)) + theme_bw()

We use geom_vline and geom_hline.

 with_lines <- function(data, g, p) {
    obs <- p2obs(data, p)
    g + geom_vline(xintercept=p) + geom_hline(yintercept=obs)
 }

For example

with_lines(data, g, 185)

Upvotes: 1

CrunchyTopping
CrunchyTopping

Reputation: 814

Make a function that just mirrors whatever model you are trying to fit (you need to do this on your own to get your various coefficients, lm is just a linear regression and this doesn't look linear but the principle will be the same).

model<-(lm(nb_p~nb_obs))
pfobs<-function(nb_obs){round(coefficients(model)[1],2)+coefficients(model)[-1]*nb_obs}
pfobs(11)

Then add a line using that function

g + geom_ribbon(aes(x = nb_p, ymin = inf90, ymax = sup90), fill = "yellow") +
  geom_line(aes(x = nb_p, y =nb_obs)) + theme_bw()+
  geom_vline(xintercept = pfobs(11)) 

Repeat for the y axis variable.

Upvotes: 1

Related Questions