1

I have inputs:

  Tin=7.02654  ; t=0.1 ;Tou=?;sed=?

My question is how to find the value in sed sed[i]= that will give Tou which has the least difference with Tin or in other words tho closest to my Tin?

What I tried:

sed = seq(from = 0, to = 0.7, by=0.001)
for(i in 1:length(sed)) {
  Tou = 5 + t*sed[i]
  find sed[i] = min(abs(Tou-Tin)))
  sed[i] 
}

What I shoud put instead of find sed[i]?

Anders Ellern Bilgrau
  • 9,928
  • 1
  • 30
  • 37
temor
  • 935
  • 2
  • 10
  • 26
  • 3
    Please read the info about [how to ask a good question](http://stackoverflow.com/help/how-to-ask) and how to give a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/5963610). This will make it much easier for others to help you. – Jaap Dec 17 '15 at 10:57
  • I would also contribute this suggestion: `which(abs(x-your.number)==min(abs(x-your.number)))` from [here](https://stat.ethz.ch/pipermail/r-help/2008-July/167216.html). – Konrad Dec 17 '15 at 11:30
  • @Konrad Alternatively, `which.min(abs(x-your.number))` can be used which yields the same index (if no ties are present). – Anders Ellern Bilgrau Dec 17 '15 at 11:41
  • To avoid duplication, [discussion here](http://stackoverflow.com/questions/20133344/find-closest-value-in-a-vector-with-binary-search) touches on a similar subject and suggests some interesting approaches. – Konrad Dec 17 '15 at 11:44

3 Answers3

2

You're looking for the which.min function, which gives the index corresponding to the least value in the given vector. See ?which.min. Hence, something like this should give what you want:

Tin <- 5.04
t <- 0.1
sed <- seq(from = 0, to = 0.7, by = 0.001)

i <- which.min(abs(5 + t*sed - Tin))
#[1] 401

sed[i]
#[1] 0.4

Unless I've misunderstood your pseudo code, there seems to be no reason to use a for-loop.

Edit 2: To answer the comment; it should probably look like this

fun <- function(x, d, sed) { # Some complicated function
  return(x*sed^2 + d)
}

myfun <-function(Tin) { 
  sed <- seq(from = 0, to = 0.7, by = 0.001)
  Tou_vec <- fun(x = 1, d = 2, sed = sed) + 5
  i <- which.min(abs(Tou_vec - Tin))
  return(sed[i])
}

myfun(Tin = 5.5)
#[1] 0

The function which.min expects a numeric vector of values and returns the index of the least value. In you code here, you supply a vector of length one, and thus i always evaluates to 1. Also you try to return (or at least print) the (first) value from within the for-loop. This doesn't work and an explicit print or return is needed if you insist. I've attempted to rewrite your myfun in the answer. From your example(s), you do not need a for-loop.

Anders Ellern Bilgrau
  • 9,928
  • 1
  • 30
  • 37
  • 1
    @temor It's not right. I've edited my answer. – Anders Ellern Bilgrau Dec 18 '15 at 06:54
  • 1
    You set `t = sed[b] + 0.2` and right after add `5` to make `Tou`. `t` is used nowhere else. This means you could have made `Tou` directly as `sed[b] + 5.2`. Now, you do this for each `b`. Hence you can do it as a vector instead and just make a vector of `Tou`s: i.e. `Tou_vec <- sed + 5.2` (which adds the 5.2 to each element of `sed`). So your `t` and `Tou` variables are somewhat redundant. – Anders Ellern Bilgrau Dec 18 '15 at 08:01
  • 1
    @temor What are `x` and `d` here? If they are constant w.r.t `b`, then `fun` is simply applied to each element of `sed` and 5 is added afterwards--i.e. the code can be vectorized and no for-loop is needed (the `b` is nothing more than bookkeeping on the index). I've edited the answer again. Otherwise, you should update your question (or make a new) where you explain this better. – Anders Ellern Bilgrau Dec 18 '15 at 09:33
1

You can just remember the best result and update it whenever you find Tou with smaller absolute difference from Tin. Like this:

Tin = 5.04
t = 0.1

sed = seq(from = 0, to = 0.7, by = 0.001)

bestResult = 5 + t * sed[1]
bestDiff = abs(Tin - bestResult)

for (i in 2:length(sed)) {
  Tou = 5 + t * sed[i]
  diff = abs(Tin - Tou)
  if (diff < bestDiff) {
    bestDiff = diff
    bestResult = Tou
  }
}

bestResult
Ardavel
  • 1,445
  • 1
  • 12
  • 23
  • Thanks .I need to return the value from `sed` that gave the best result`bestResult`. Any idea? – temor Dec 17 '15 at 14:31
1

One downside to the which.min approach is that it returns a number rather than a vector of booleans (Which you can then use & or | with, and thus can be part of a more complicated filter)

in that case, you want to use the absolute difference as Ardavel said, but there's no reason to track it as part of a loop, this can be done entirely in a data.frame or data.table.

Tin=7.02654
t = 0.1
test <- data.frame(sed = seq(from = 0, to = 0.7, by=0.001))
test$Tou <- 5 + t * test$sed
test$sed[abs(test$Tou - Tin) == min(abs(test$Tou - Tin))]
Shape
  • 2,892
  • 19
  • 31
  • Thanks. What do you think about this function:`myfun <-function(Tin) { sed <- seq(from = 0, to = 0.7, by = 0.001); for(b in 1:length(sed)) { t=sed[b]+0.2; Tou=5+t; i <- which.min(abs(Tou - Tin)) ; sed[i]; }}` can you update your answer based on this function please? – temor Dec 17 '15 at 15:55