Extract Consecutive Pairs of Elements from a Vector and Place in a Matrix

Extract Consecutive Pairs of Elements from a Vector and Place in a Matrix

This fits your desired output:

cbind(C[-length(C)], C[-1])
[,1] [,2]
[1,] 1 20
[2,] 20 44
[3,] 44 62
[4,] 62 64
[5,] 64 89
[6,] 89 91
[7,] 91 100

How to construct consecutive pairs from a vector with last element included

This should do it

cbind(x, c(x[-1], x[1]))

R iterate over consecutive pairs in a list

We can remove the first and last elements and concatenate in Map

Map(c,  v1[-length(v1)], v1[-1])
#[[1]]
#[1] 1 2

#[[2]]
#[1] 2 3

#[[3]]
#[1] 3 4

Or rbind and use asplit

asplit(rbind(v1[-length(v1)], v1[-1]), 2)

R: return largest consecutive pair of numbers in a matrix

Here is a solution using matrix arithmetic that will be much more efficient than a nested loop over the rows and columns, especially on large matrices.

directionalSums <- function(x){
stopifnot(is.matrix(x))

# padding functions to allow matrix addition
padL <- function(x) cbind(-Inf,x)
padR <- function(x) cbind(x,-Inf)
padU <- function(x) rbind(-Inf,x)
padD <- function(x) rbind(x,-Inf)

# these padding functions are just for readability
padLU <- function(x) padL(padU(x))
padLD <- function(x) padL(padD(x))
padRU <- function(x) padR(padU(x))
padRD <- function(x) padR(padD(x))

m <- nrow(x)
n <- ncol(x)

sumR <- padR( (padL(x) + padR(x))[1:m,2:n] )
sumD <- padD( (padU(x) + padD(x))[2:m,1:n])
sumRD <- padRD( (padLU(x) + padRD(x))[2:m,2:n] )
sumRU <- padRU( (padRU(x) + padLD(x))[2:m,2:n] )

list(`right`=sumR,
`down`=sumD,
`right and down`=sumRD,
`right and up`=sumRU)

}

Let's try it out.

(sumList <- directionalSums(ma))

maxLocList <- lapply(sumList, function(x) which(x==max(x), arr.ind=TRUE))

for (i in 1:length(maxLocList) ){
nameD <- names(maxLocList)[i]
startCell <- maxLocList[[i]]
maxSum <- sumList[[i]][startCell]
x1 <- ma[startCell]
x2 <- maxSum - x1
writeLines(paste0('The max-sum consec. pair going ',
nameD, ' starts at [',
paste(startCell, collapse=', '),
'], with sum ', maxSum,
' and components ', x1, ' and ',x2)
)
}

Returns:

$right
[,1] [,2] [,3] [,4]
[1,] 15 13 8 -Inf
[2,] 9 15 24 -Inf
[3,] 12 25 28 -Inf
[4,] 16 26 24 -Inf

$down
[,1] [,2] [,3] [,4]
[1,] 12 12 16 16
[2,] 7 14 26 26
[3,] 4 24 27 25
[4,] -Inf -Inf -Inf -Inf

$`right and down`
[,1] [,2] [,3] [,4]
[1,] 13 17 20 -Inf
[2,] 13 21 22 -Inf
[3,] 18 20 29 -Inf
[4,] -Inf -Inf -Inf -Inf

$`right and up`
[,1] [,2] [,3] [,4]
[1,] -Inf -Inf -Inf -Inf
[2,] 11 11 12 -Inf
[3,] 8 19 30 -Inf
[4,] 10 31 23 -Inf

The max-sum consec. pair going right starts at [3, 3], with sum 28 and components 16 and 12
The max-sum consec. pair going down starts at [3, 3], with sum 27 and components 16 and 11
The max-sum consec. pair going right and down starts at [3, 3], with sum 29 and components 16 and 13
The max-sum consec. pair going right and up starts at [4, 2], with sum 31 and components 15 and 16

Applying a function over consecutive pairs of list elements in R without loops

I use mapply for that. For example

a<-1:1000
mapply(function(x,y)x-y,a[-1000],a[-1])

It appears to be slightly faster than the for loop version:

> f <- function(x,y)x-y
> g <- function(){
o<-c();
for(i in a[-1000])o<-c(o,f(i,i+1))
> }

>
> system.time(
+ for(i in 1:1000){
+ mapply(f,a[-1000],a[-1])
+ }
+ )
user system elapsed
2.344 0.000 2.345

> system.time(for(i in 1:1000)g())
user system elapsed
3.399 0.000 3.425

Extract and count pairs of adjacent numbers within rows

A base alternative.

1. Find and count pairs

Because you only have numerical values, we coerce data to matrix. This will make subsequent calculations considerably faster. Create lag and lead versions (column-wise) of the data, i.e. remove the last column (m[ , -ncol(m)]) and first column (m[ , -ncol(m)]) respectively.

Coerce the lag and lead data to 'from' and 'to' vectors, and count pairs (table). Convert table to matrix. Select first pair with max frequency.

m <- as.matrix(d)
tt <- table(from = as.vector(m[ , -ncol(m)]), to = as.vector(m[ , -1]))
m2 <- cbind(from = as.integer(dimnames(tt)[[1]]),
to = rep(as.integer(dimnames(tt)[[2]]), each = dim(tt)[1]),
freq = as.vector(tt))
m3 <- m2[which.max(m2[ , "freq"]), ]
# from to freq
# 3 0 3

If you want all pairs with maximum frequency, use m2[m2[ , "freq"] == max(m2[ , "freq"]), ] instead.


2. Replace values of most frequent pair and set rest to zero

Make a copy of the original data. Fill it with zero. Grab the 'from' and 'to' values of the 'max pair'. Get indexes of matches in lag and lead data, which correspond to 'from' columns. rbind with indexes of 'to' columns. At the indexes, replace zeros with 2.

m_bin <- m
m_bin[] <- 0
ix <- which(m[ , -ncol(m)] == m3["from"] &
m[ , -1] == m3["to"],
arr.ind = TRUE)
m_bin[rbind(ix, cbind(ix[ , "row"], ix[ , "col"] + 1))] <- 2
m_bin
# var1 var2 var3 var4 var5
# [1,] 0 0 2 2 0
# [2,] 0 0 2 2 0
# [3,] 2 2 0 0 0
# [4,] 0 0 0 0 0

3. Benchmark

I use data of a size somewhat similar to that mentioned by OP in comment: a data frame with 10000 rows, 100 columns, and sampling from 100 different values.

I compare the code above (f_m()) with the zoo answer (f_zoo(); functions below). To compare the output, I add dimnames to the zoo result.

The result shows that f_m is considerably faster.

set.seed(1)
nr <- 10000
nc <- 100
d <- as.data.frame(matrix(sample(1:100, nr * nc, replace = TRUE),
nrow = nr, ncol = nc))

res_f_m <- f_m(d)
res_f_zoo <- f_zoo(d)
dimnames(res_f_zoo) <- dimnames(res_f_m)

all.equal(res_f_m, res_f_zoo)
# [1] TRUE

system.time(f_m(d))
# user system elapsed
# 0.12 0.01 0.14

system.time(f_zoo(d))
# user system elapsed
# 61.58 26.72 88.45

f_m <- function(d){
m <- as.matrix(d)
tt <- table(from = as.vector(m[ , -ncol(m)]),
to = as.vector(m[ , -1]))
m2 <- cbind(from = as.integer(dimnames(tt)[[1]]),
to = rep(as.integer(dimnames(tt)[[2]]),
each = dim(tt)[1]),
freq = as.vector(tt))

m3 <- m2[which.max(m2[ , "freq"]), ]
m_bin <- m
m_bin[] <- 0
ix <- which(m[ , -ncol(m)] == m3["from"] &
m[ , -1] == m3["to"],
arr.ind = TRUE)
m_bin[rbind(ix, cbind(ix[ , "row"], ix[ , "col"] + 1))] <- 2
return(m_bin)
}

f_zoo <- function(d){
pairs <- sort(table(c(rollapply(t(d), 2, toString))))
top <- scan(text = names(tail(pairs, 1)), sep = ",", what = 0L, quiet = TRUE)
right <- rollapplyr(unname(t(d)), 2, identical, top, fill = FALSE)
left <- rbind(right[-1, ], FALSE)
t(2 * (left | right))
}

How to assign values to a vector in pairs of 10 in R?

After you create your matrix X and vector X_mean, you could do:

X[,2] <- rep(c(0,3,5, 10) - X_mean, each = 10)

Extract and store a specific position from multiple matrices in an array in R

If you would like to fix your loop, this could be one way to do it:

unouno <- NULL
for (i in 1:dim(y)[3]){
unouno[i]<-y[2,1,i]
}

It seems that you were mising indexing on the vector unouno as well

Extract difference between every 2 consecutive elements

You can simply use

diff(wss)

which returns a vector of the differences.

To illustrate what you did wrong. lapply should be used on a list and evaluates a function for each element in the list. This is not applicable here because: i) you don't have a list, ii) you need the differences between 2 consecutive elements and in the method you used , even if it were a list, you only supply one to the function diff

numpy create array of the max of consecutive pairs in another array

A loop-free solution is to use max on the windows created by skimage.util.view_as_windows:

list(map(max, view_as_windows(A, (2,))))
[8, 33, 33, 4, 6]

Copy/pastable example:

import numpy as np
from skimage.util import view_as_windows

A = np.array([8, 2, 33, 4, 3, 6])

list(map(max, view_as_windows(A, (2,))))


Related Topics



Leave a reply



Submit