14thTimeLord
14thTimeLord

Reputation: 373

From a sequence of numbers, how do I find an immediate smaller (and an immediate bigger) number than a particular random number, In R?

So I have 10 increasing sequence of numbers, each of them look like (say x(i) <- c(2, 3, 5, 6, 8, 10, 11, 17) for i ranging from 1 to 10 ) and I have a random sampling number say p=9. Now for each sequence x(i), I need to find the number immediately smaller than p and immediately bigger than p, and then for each i (from 1 to 10) , I need to take the difference of these two numbers and store them in a string.

For the x(i) that I have given here, the immediate smaller number than p=9 would be 8 and the immediate bigger number than p=9 would be 10, the difference of these would be (10-8)=2.

I am trying to get a code that would create a string of these differences, where first number of the string would mean the difference for i=1, second number would mean the difference for i=2 and so on. The string would have i numbers. I am relatively new to R, so anywhere connected to loops throws me off a little bit. Any help would be appreciated. Thanks.

EDIT: I am putting the code I am working with for clarification.

fr = 100
dt = 1/1000 #dt in milisecond
duration = 2 #no of duration in s
nBins = 2000 #SpikeTrain
nTrials = 20 #NumberOfSimulations
MyPoissonSpikeTrain = function(p, fr= 100) {
 p = runif(nBins)
 q = ifelse(p < fr*dt, 1, 0)
  return(q)
   }

set.seed(1)
SpikeMat <- t(replicate(nTrials, MyPoissonSpikeTrain()))

Spike_times <- function(i) {
  c(dt*which( SpikeMat[i, ]==1))}


set.seed(4)
RT <- runif(1, 0 , 2)

for (i in 1:nTrials){

The explanation for this code, is mentioned in my previous question. I have 20 (number of trials aka nTrials) strings with name Spike_times(i) here. Each Spike_times(i) is a string of time stamps between o and 2 seconds where spikes occurred and they have different number of entries. Now I have a random time sample in the form of RT, which is a random number between 0 and 2 seconds. Say RT is 1.17 seconds and Spike_times(i) are the sequence of increasing times stamps between 0 and 2 seconds.

Let me give you an example, Spike_times(3) looks like 0.003 0.015 0.017 ... 1.169 1.176 1.189 ... 1.985 1.990 1.997 then I need a code that picks out 1.169 and 1.176 and gives me the difference of these entries 0.007 and stores it in another string say W as the third entry c(_, _, 0.007, ...) and does this for all 20 strings Spike_times(i) and gives me W with 20 entries.

I hope my question is clear enough. Please let me know if I need to correct something.

Upvotes: 0

Views: 319

Answers (2)

gfgm
gfgm

Reputation: 3647

This approach should do what you want. I am making a function that extracts the desired result from a single sequence and then applying it to each sequence. I am assuming here that your sequences are row-vectors and are stacked in a matrix. If your actual data structure is different the code can be adapted, but you need to indicate how your sequences are actually stored.

x <- matrix(rep(c(2,3,5,6,8,10,11,17), 10), nrow=10, byrow = T)
x
#>       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#>  [1,]    2    3    5    6    8   10   11   17
#>  [2,]    2    3    5    6    8   10   11   17
#>  [3,]    2    3    5    6    8   10   11   17
#>  [4,]    2    3    5    6    8   10   11   17
#>  [5,]    2    3    5    6    8   10   11   17
#>  [6,]    2    3    5    6    8   10   11   17
#>  [7,]    2    3    5    6    8   10   11   17
#>  [8,]    2    3    5    6    8   10   11   17
#>  [9,]    2    3    5    6    8   10   11   17
#> [10,]    2    3    5    6    8   10   11   17

set.seed(123)
p = sample(10, 1)

# write a function to do what you want on one sequence:
# NOTE: If p appears in the sequence I assume you want the 
# closest numbers not equal to p! If you want the closest
# numbers to p including p itself change the less than/
# greater than to <= / >=
get_l_r_diff <- function(row, p) {
  temp <- row - p
  lower <- max(row[temp < 0])
  upper <- min(row[temp > 0])
  upper - lower
}

apply(x, 1, function(row)get_l_r_diff(row, p))
#>  [1] 3 3 3 3 3 3 3 3 3 3

apply(x, 1, function(row) get_l_r_diff(row, 9))
#>  [1] 2 2 2 2 2 2 2 2 2 2

# if the result really needs to be a string
paste(apply(x, 1, function(row) get_l_r_diff(row, 9)), collapse = "")
#> [1] "2222222222"

For your case you can just apply the two functions to your indices:

spikes <- sapply(1:20, function(i){get_l_r_diff(Spike_times(i), RT)})

Upvotes: 2

Relasta
Relasta

Reputation: 1106

By making a small change to your Spike_times function you can do this with sapply returning a vector of all calculated values

Spike_times <- function(i) {
    x <- c(dt*which( SpikeMat[i, ]==1))
    min(x[x > RT]) - max(x[x < RT])
}

set.seed(4)
RT <- runif(1, 0 , 2)

results <- sapply(1:20, Spike_times)

Upvotes: 1

Related Questions