user2814482
user2814482

Reputation: 651

Shifting a vector

I have a data frame and I would like to 'align' each column so that the maximum value for each column is on the same row.

I was trying to do this using base functionality, but am getting the wrong results, ie. just overwriting and not shifting. I just found the Lag function in Hmisc, however, I am sure there is a way to do this in base and I"m just thinking about it wrong. I would prefer this, as when I try to run this later on another computer with a different verison of R there are always some package that aren't supported.

Thanks for any help,

maxIndices<-apply(df,2,function(x){
maxInt<-max(x,na.rm=T)
maxInt_indx<-which(x==maxInt) 
})
maxMaxIndex<-max(maxIndices)
minMaxIndex<-min(maxIndices)
##
apply(df,2,function(x){
  maxInt<-max(x,na.rm=T)
  maxInt_indx<-which(x==maxInt)
 shift<-maxMaxIndex-maxInt_indx
shifted_vec<-c(rep(NA,times=shift), x[1:length(x)+shift]) ## this is producing the wrong results
# shifted_vec<-Lag(x,shift) # is there a way to do this using just base functionality
})

Upvotes: 4

Views: 18298

Answers (4)

qwr
qwr

Reputation: 11024

If you're using tidyverse, you have dplyr lag/lead:

dplyr::lag(1:5)
#> [1] NA  1  2  3  4
dplyr::lead(1:5)
#> [1]  2  3  4  5 NA

You can define the padding value with argument default.

Importing tidyverse or dplyr will mask base R's stats::lag.

Upvotes: 1

Peter Thejll
Peter Thejll

Reputation: 31

You might like Lag from Hmisc. "Lag" - not "lag".

library(Hmisc)
Lag(1:10,3)
 [1] NA NA NA  1  2  3  4  5  6  7

Upvotes: 2

petermeissner
petermeissner

Reputation: 12900

My interpretation of what a shift function implementation might / should look like:

#' function that shifts vector values to right or left
#'
#' @param x Vector for which to shift values
#' @param n Number of places to be shifted.
#'    Positive numbers will shift to the right by default.
#'    Negative numbers will shift to the left by default.
#'    The direction can be inverted by the invert parameter.
#' @param invert Whether or not the default shift directions
#'    should be inverted.
#' @param default The value that should be inserted by default.

shift <- function(x, n, invert=FALSE, default=NA){
  stopifnot(length(x)>=n)
  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)))
  }
}

Example Usage

shift(1:10, 5)
## [1] NA NA NA NA NA  1  2  3  4  5

shift(1:10, -5, default = 999)
## [1]   6   7   8   9  10 999 999 999 999 999

Upvotes: 10

nograpes
nograpes

Reputation: 18323

I think you just have a typo in one line:

  shifted_vec<-c(rep(NA,times=shift), x[1:(length(x)-shift)]) ## this is producing the wrong results

Notice the (length(x)-shift). The + should be a - and there should be brackets around it.


Although a more concise version of your code would be:

max.ind <- sapply(df, which.max)
diff <- max(max.ind) - max.ind
shift <- function (x, shift) c(rep(NA,times=shift), x[1:(length(x)-shift)])
mapply(shift, df, diff)

Upvotes: 2

Related Questions