1
$\begingroup$

I am looking for an algorithm that can align a vector of numbers . I don't know exactly where to look because I am not sure how you would name it, so I am sorry if this is already asked (I couldn't find it).

For example, consider the following example (df data: https://pastebin.com/guWGThsT) where peaks are shifted slightly and you can clearly see how they should align. The objective would be to return how much you need to shift the observations (e.g. in a certain window) in order to make the variables most similar to each other. I think of it as illustrator's horizontal/vertical allign.

Are there standard algorithm to do this? I am working mostly in R so R code is also helpful.

image(df): enter image description here

$\endgroup$
1
$\begingroup$

I thought I would my post the solution that I took for now. It is based on a shifting each variable to maximise the Pearson between that variable and a template. Where the template was defined as the variable that had the largest sum of all Pearson correlations. rowMaxs(cor(df));

# https://rdrr.io/cran/diffrprojects/src/R/tools.R
shift <- function(x, n=0, default=NA, invert=FALSE){
  n <-
    switch (
      as.character(n),
      right    =  1,
      left     = -1,
      forward  =  1,
      backward = -1,
      lag      =  1,
      lead     = -1,
      as.numeric(n)
    )
  if( length(x) <= abs(n) ){
    if(n < 0){
      n <- -1 * length(x)
    }else{
      n <- length(x)
    }
  }
  if(n==0){
    return(x)
  }
  n <- ifelse(invert, n*(-1), n)
  if(n<0){
    n <- abs(n)
    forward=FALSE
  }else{
    forward=TRUE
  }
  if(forward){
    return(c(rep(default, n), x[seq_len(length(x)-n)]))
  }
  if(!forward){
    return(c(x[seq_len(length(x)-n)+n], rep(default, n)))
  }
}


find.max <- function(target,ref,istart,iend){
  c <- unlist(lapply(-(istart-1):(istart),function(i) cor(target[(istart+i):(iend+i)],ref[istart:iend])))
  return(which.max(c))
}


window.finetune=25

dfy<-df

i.template <- which.max(rowSums(cor(dfy))) # define template according to the maxium sum of R. 
istart=round((nrow(dfy)/2))-window.finetune
iend=round((nrow(dfy)/2))+window.finetune

for (i in 1:ncol(dfy)){
  i.max <- find.max(target=dfy[,i],ref=dfy[,i.template],istart,iend)
  s <- (i.max-istart)
  dfy[,i] <- shift(dfy[,i],-s,default = 0)
  
}

image(dfy)
  

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.