R: Map a matrix with another matrix in r - r

I found a same question in map a matrix with another matrix. But, that is in Matlab. If I want to map a matrix with another matrix in R, How can I easily get without using a loop. For example, I have following matrices,
A = [ 1 4 3
2 3 4
4 3 1
4 5 5
1 2 1]
B = [3 3 2
2 0 1
1 1 5
4 1 3
5 2 0]
My mapping should be as given bellow;
R = [1 4 3
2 3 4
4 3 5
4 1 3
5 2 0]
The result R will take the values from A starting from [1,1] to [3,2]. Then remaining values are from B starting from [3,3] to [5,3].

As simple as:
R <- t(A)
R[9:15] <- t(B)[9:15]
t(R)
[,1] [,2] [,3]
[1,] 1 4 3
[2,] 2 3 4
[3,] 4 3 5
[4,] 4 1 3
[5,] 5 2 0
Sample data
A <- matrix(c(1,4,3,2,3,4,4,3,1,4,5,5,1,2,1), nrow = 5, ncol = 3, byrow = TRUE)
B <- matrix(c(3,3,2,2,0,1,1,1,5,4,1,3,5,2,0), nrow = 5, ncol = 3, byrow = TRUE)

A little different to Djack's approach, I used matrix with a byrow = T, and indexed the original matrices:
matrix(c(t(A)[1:8], t(B)[9:15]), byrow = T, ncol = 3)

Related

Selecting the top X values of each individual column in R

Say you have the following data set.
df1<-matrix(data = 1:10,
nrow = 5,
ncol = 5)
colnames(df1)=c("a","b","c","d","e")
How would you extract the top X values from each individual column as a new data frame?
The expected output would be something like this (for the top 3 values in each column
a
b
c
d
e
5
10
5
10
5
4
9
4
9
4
3
8
3
8
3
You can use apply to apply a function to each column (MARGIN = 2). Here, the function is \(x) head(sort(x, decreasing = T), 3), which sorts the column by decreasing order, and select the top three values (head(x, 3)).
apply(df1, 2, \(x) head(sort(x, decreasing = T), 3))
a b c d e
[1,] 5 10 5 10 5
[2,] 4 9 4 9 4
[3,] 3 8 3 8 3
Note: \(x) is a shorthand for function(x) in lambda-like functions since 4.1.0.
We can sort, then use head:
head(apply(df1, 2, sort, decreasing = TRUE), 3)
# a b c d e
# [1,] 5 10 5 10 5
# [2,] 4 9 4 9 4
# [3,] 3 8 3 8 3

R function for creating monotonic (increasing or decreasing) permutations [duplicate]

This question already has answers here:
How to generate permutations or combinations of object in R?
(3 answers)
Closed 2 years ago.
I'm trying to create an efficient function to generate all monotonically increasing permutations of a large vector. Obviously, reducing the outputs from expand.grid or gtools::permutations works, but only for smaller vectors.
Example:
x = 1:3
Desired output:
1, 1, 1
1, 1, 2
1, 1, 3
1, 2, 2
1, 2, 3
1, 3, 3
2, 2, 2
2, 2, 3
2, 3, 3
3, 3, 3
Any suggestions using base R or, existing packages with this capability?
EDIT: An ideal solution would avoid generating the complete set of permutations to then subset.
Using data.table this is fairly easy:
expand.monotonic <- function(x, len=length(x)){
do.call(CJ, lapply(integer(len), function(...) x ))[
eval(parse(text=paste0("V", 2:len, ">=", "V", 1:(len-1), collapse="&") )), ]
}
expand.monotonic(1:3)
V1 V2 V3
1: 1 1 1
2: 1 1 2
3: 1 1 3
4: 1 2 2
5: 1 2 3
6: 1 3 3
7: 2 2 2
8: 2 2 3
9: 2 3 3
10: 3 3 3
explanation:
First create a list containing the replicated vector len times, Use data.table::CJ to cross join all the vectors. And this is where the magic happens based on the len create an expression basically V2>=V1&V3>=V2 as V# is the default name for unnamed columns, and subset by the result of evaluating said expression.
parse(text=paste0("V", 2:len, ">=", "V", 1:(len-1), collapse="&") )
# expression(V2>=V1&V3>=V2)
Here's some code which creates permutations with repeats allowed as in your example, and detects whether each permutation is monotonic
x <- 1:3
# Generate permutations of length x
out <- gtools::permutations(length(x), length(x), v = x, repeats.allowed=TRUE)
# Detect if they're monotonic
mono <- apply(out, 1, function(x) { all(x == cummax(x)) })
output_with_monotonic_label <- cbind(out, mono)
# output_with_monotonic_label
# mono
# [1,] 1 1 1 1
# [2,] 1 1 2 1
# [3,] 1 1 3 1
# [4,] 1 2 1 0
# [5,] 1 2 2 1
# [6,] 1 2 3 1
# [7,] 1 3 1 0
# [8,] 1 3 2 0
# [9,] 1 3 3 1
# [10,] 2 1 1 0
# ....

function to calculate score

Calculate sequence score based on score matrix.
sum(j[k])
j <- matrix(1:25, ncol = 5, nrow = 5)
diag(j) <- 0
j
n <- 1:5
k <- sample(n, 5, replace = FALSE)
k <- replicate(5, sample(n, 5, replace = FALSE))
j is score matrix.
k is sequence type matrix.
lets say k[1,] = 4 1 5 3 2
k[2,] = 2 5 4 2 4
solution: Please help answer two issues;
Issue 1:
add one more column to matrix k (lets call it "score"). Based on J matrix the score for this sequence should be 48.
4 1 5 3 2 48
Issue 2:
k[2,] = 2 5 4 2 4 The sample function is producing wrong permutations. I don't want any repetition in the sequence. Here 4 is repeated. Secondly 1 is missing. is there any other best way to generate random permutations.
You better double check the result. Without a reproducible example from your end it's difficult to confirm the values.
set.seed(1)
k <- replicate(5, sample(5))
# each column is a random permutation of 1:5
k
# [,1] [,2] [,3] [,4] [,5]
# [1,] 2 5 2 3 5
# [2,] 5 4 1 5 1
# [3,] 4 2 3 4 2
# [4,] 3 3 4 1 4
# [5,] 1 1 5 2 3
j <- matrix(1:25, 5)
diag(j) <- 0
nr <- nrow(k)
# arrange successive values as a column pair
ix <- cbind(c(k[-nr,]), c(k[-1,]))
# use the column pair to reference indices in j
jx <- j[ix]
# arrange j-values into a matrix and sum by column, producing the scores
scores <- colSums(matrix(jx, nr-1))
cbind(t(k), scores)
# scores
# [1,] 2 5 4 3 1 59
# [2,] 5 4 2 3 1 44
# [3,] 2 1 3 4 5 55
# [4,] 3 5 4 1 2 53
# [5,] 5 1 2 4 3 42

how to create numeral combinations

I have 6 digits (1, 2, 3, 4, 5, 6), and I need to create all possible combinations (i.e. 6*5*4*3*2*1 = 720 combinations) in which no number can be used twice and O is not allowed. I would like to obtain combinations like: 123456, 246135, 314256, etc.
Is there a way to create them with Matlab or R? Thank you.
In Matlab you can use
y = perms(1:6);
This gives a numerical 720×6 array y, where each row is a permutation:
y =
6 5 4 3 2 1
6 5 4 3 1 2
6 5 4 2 3 1
6 5 4 2 1 3
6 5 4 1 2 3
···
If you want the result as a char array:
y = char(perms(1:6)+'0');
which produces
y =
654321
654312
654231
654213
654123
···
In R:
library(combinat)
p <- permn(1:6)
gives you a list; do.call(rbind, p) or matrix(unlist(p), ncol=6, byrow=TRUE) will give a numeric array; sapply(p,paste,collapse="") gives a vector of strings.
Here's a base R 'solution':
p <- unique(t(replicate(100000, sample(6,6), simplify="vector")))
nrow(p)
#> [1] 720
head(p)
#> [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,] 3 5 4 2 1 6
#> [2,] 6 3 5 4 1 2
#> [3,] 5 1 6 2 3 4
#> [4,] 6 5 3 2 4 1
#> [5,] 5 2 3 6 4 1
#> [6,] 1 4 2 5 6 3
It's a hack of course, and this potentially only applies to the example given, but sometimes it's useful to do things in silly ways... this takes an excessive number of samples (without replacement) of the vector 1:6, then removes any duplicates. It does indeed produce the unique 720 results, but they're not sorted.
A base R approach is
x <- do.call(expand.grid, rep(list(1:6), 6))
x <- x[apply(x, MAR = 1, function(x) length(unique(x)) == 6), ]
which creates a matrix with 6^6 rows, then retains only rows that contain all 6 numbers.

Reshape array into distance matrix (in R)

I've got an array that was generated by flattening of a bottom triangle of a symmetrical square matrix (i.e distance matrix). I'm looking to reverse that process and generate the full square matrix from the array.
Let's say the original matrix was:
0 1 2 4
1 0 3 5
2 3 0 6
4 5 6 0
The lower triangle is:
1
2 3
4 5 6
...which was then flattened and recorded as array
1 2 3 4 5 6
I want to take that array and convert it back to the original matrix. I was hoping that it'd be as simple as
as.matrix(as.dist(ar)) + t(as.matrix(as.dist(ar)))
...but as.dist(...) actually goes on calculate distances in various ways, instead of simply filling in the values from the array. There's probably a simple alternative, right?
ar <- 1:6
d <- (1 + sqrt(1 + 8 * length(ar))) / 2
x <- matrix(0, d, d)
x[upper.tri(x)] <- ar
x[lower.tri(x)] <- t(x)[lower.tri(x)]
x
# [,1] [,2] [,3] [,4]
# [1,] 0 1 2 4
# [2,] 1 0 3 5
# [3,] 2 3 0 6
# [4,] 4 5 6 0
Let n1 be such that 1+2+3+...+n1 is the length of x and let n = n1 + 1. Then m is an n x n matrix so:
ar <- 1:6
n <- which(cumsum(seq_along(ar)) == length(ar)) + 1
m <- matrix(0, n, n)
as.dist(t(replace(m, upper.tri(m), ar)))
giving:
1 2 3
2 1
3 2 3
4 4 5 6

Resources