2

I have an R coding question which I want to share. Suppose we have the following:

z1= c(2, 4, 6, 8)
s1= seq(-13, 14, by = 0.1)
s2= seq(-13, 14, by = 0.1)

Function<-function(s1,s2){
  Y<-matrix(0,nrow=length(s1),ncol=length(z1))
  for (j in 1:length(s1)){
    for (i in 1:length(z1)){
      Y[j,i]<- s1[j]*s2[j] + z1[i]}}
  return(Y)
 }

So, s1 and s2 are the inputs, and they can have any values in the interval [-13, 14]. They can have the same value, or different values as well for each time. Now, I wonder how to identify which combinations of s1 and s2 produce outpots that are (all) less than a certain threshold, say 20. For example, if s1= 2 and s2= 4 then we know the function above has four outputs (four because i=1,...,4), which are as follows:

Y= 8+ 2 for i=1
Y= 8+ 4 for i=2
Y= 8+ 6 for i=3
Y= 8+ 8 for i=4

In this case, all of these outpots are less than 20 so that the combination (2,4) is possible to be chosen. But, how to apply this to the whole range of the possible values of s1 and s2 and then choose only those combinations whose outputs are all less than 20? Any hint is really appriciated.

Thanks!

Blue999
  • 23
  • 5

2 Answers2

2

With two vectors of different lengths, you can use expand.grid + apply:

#Create the vectors
s1 = seq(2, 5, by = 1)
s2 = seq(0, 3, by = 1)
z1 = c(2, 4, 6, 8)

#I simplified your function
f <- function(x1, x2) sapply(x1 * x2, `+`, z1) 

gr <- expand.grid(s1, s2)
gr[apply(gr, 1, \(x) all(f(x[1], x[2]) <= 20)), ]
Maël
  • 45,206
  • 3
  • 29
  • 67
  • Thanks Mael. But I think the scripts i and j in the function are important. For example, s1*s2+z1 works to multiply each element in s1 with its corresponding element in s2 and then sum it up with the corresponding in z1. This is not what we aim to do. We want to sum up the result of s1*s2 with each element of z1, and if the results (all) below the threshold then it's a good combination of s1 and s2. Also, may I ask why do not we consider the cases when the combination has equal entries so (2,2) for example? – Blue999 Aug 02 '23 at 12:27
  • 1
    You could use `sapply` in the function then – Maël Aug 02 '23 at 12:49
  • 1
    If you have two vector, you can use `expand.grid` – Maël Aug 02 '23 at 12:51
  • 1
    Check edits in the answer – Maël Aug 02 '23 at 12:55
  • 1
    I guess OP wants to keep track of all *index* combinations of `s1` and `s2`, thus `expand.grid` might be the thing: *"They can have the same value, or different values as well for each time. "* – ThomasIsCoding Aug 03 '23 at 09:15
  • 2
    Indeed! I removed the part with `combn` – Maël Aug 03 '23 at 09:21
  • Thanks! The last line of the code does not work properly though. I think I should Install some package? It says: 'Error: unexpected input in "gr[apply(gr, 1, \"' – Blue999 Aug 03 '23 at 10:43
2

If you care about the indices of all possible combinations of s1, s2 with a specific filtering condition, you can try expand.grid + subset like below

subset(
    expand.grid(
        j1 = seq_along(s1),
        j2 = seq_along(s2)
    ),
    s1[j1] * s2[j2] < 20 - max(z1)
)
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
  • 1
    From what I understand of OP's question, they are looking for combinations of `s1` and `s2` only (not with `z1`) too, so an extra step of filter would be needed here, grouping by s1 and s2, and retaining only those groups with the four possible `i` since all outputs should be below 20 – Maël Aug 03 '23 at 09:22
  • 1
    @Maël aha, you are right! Thanks for correcting me. I misread the objective. I updated my solution. – ThomasIsCoding Aug 03 '23 at 09:42
  • @Blue999 maybe replace `max(z1)` by `max(z1+ z2)` – ThomasIsCoding Aug 03 '23 at 10:22