jordanawhite
jordanawhite

Reputation: 49

Row function converting matrix to vector

I'm in a bit of a predicament where I have several matrices held within a list, and each row of every matrix has a peak-finder function run on it. This all works fine, only the end result is a vector held within a matrix held within the list. What I would like is a matrix similar to what I started with, but just with the column numbers identified as peaks within each row.

I have made a reproducible example, where we start with a list called rows, these get moved to split each matrix in to its rows within the list. This is subsetted based on a range of the maximum values, and then a peak-finder function is used to find the peaks in each row. It is here where the issue arises, as the data format is changed. I do not need the peaks to remain in the same column of the matrix necessarily, but I need to keep each row within each matrix separate. As it currently stands all I can do is unlist, but with this I lose the row of the matrix that the peak was originally held in. I cannot make a new matrix by ncol= something, as the number of peaks will differ. If NAs were in the data to make a full matrix this would work absolutely fine.

##function 1: from Quantmod pkg (source here in case mods should be made to the function)
em.peaks <-
function(x, thresh=50) {
  pks <- which(diff(sign(diff(x, na.pad=FALSE)),na.pad=FALSE) < 0) + 2
  if( !missing(thresh) ) {
    if(sign(thresh) < 0)
      thresh <- -thresh
    pks[x[pks-1]-x[pks] > thresh]
  } else pks
}

##function 2: for subsetting data in a given range (by @konrad-rudolph)
between = function (x, lower, upper){
    x >= lower & x <= upper }

set.seed(42)

rows<- list()
for (i in 1:10)
{ rows[[i]] <- matrix ( sample.int ( 100, 10*10, TRUE), 10, 10) }

for (i in 1:10)
{ rows[[i]] <- do.call ( rbind, lapply ( rows, function(x) x[i,] )) }

for (i in 1:10)
{ rows[[i]] <- rows[[i]][ between ( apply ( rows[[i]], 1, max), 95, 100), ] }

mypeaks <- list()
for (i in 1:10)
{ mypeaks[[i]] <- matrix ( apply ( rows[[i]], 1, FUN = em.peaks )) }

mypeaks[[1]][c(1:3),]


for (i in 1:10)
{ mypeaks[[i]] <- t ( mypeaks[[i]] ) }

mypeaks[[1]]

for (i in 1:10)
{ mypeaks[[i]] <- matrix ( unlist ( mypeaks[[i]] ), ncol = length ( mypeaks[[i]] )) }

mypeaks[[1]]

What I would like to see in mypeaks[[1]] is a 3x4 matrix (with some empty spaces), though my output is a 1D vector.

Upvotes: 1

Views: 164

Answers (1)

ExperimenteR
ExperimenteR

Reputation: 4473

Try

row.em.peaks <- function(m){
  s <- apply(m, 1, FUN = em.peaks )
  n <- max(lengths(s))
  do.call(`rbind`, lapply(s, function(i)`length<-`(i, n)))
}
mypeaks <- lapply(rows, row.em.peaks)
mypeaks[[1]]
#     [,1] [,2] [,3] [,4]
#[1,]    3    6   NA   NA
#[2,]    3    6    8   NA
#[3,]    4    6    8   10

Upvotes: 2

Related Questions