Sum of absolute differences of all possible pairs in array - r

I am trying to calculate the sum of the differences of all possible pairs of an array (sum of difference first/second + difference first/third, difference second/first + difference second/third, difference third/first + difference third/second). The original dataframe consists of multiple columns like the one below, still the colSum function doesn't work because of:
"Error in colSums(FC_TS1test1, dims = 1) : 'x' must be an array of at least two dimensions".
I appreciate your help!
array <- c(5, 3, 1)
The calculation behind it should be:
|(5-3)|+|(5-1)|=2+4=6
|(3-5)|+|(3-1)|=2+2=4
|(1-5)|+|(1-3)|=4+2=6
6+4+6=16

We can use sum + dist
> sum(dist(array))
[1] 840

We need combinations without repetition.
sum(combn(a, 2, diff))
# [1] -94
Or, with some packages:
colSums(matrixStats::rowDiffs(RcppAlgos::comboGeneral(a, 2, repetition=F)))
# [1] -94
or
sum(unlist(RcppAlgos::comboGeneral(a, 2, repetition=F, FUN=diff)))
# [1] -94
Two smaller examples demonstrate what the core of the code does.
combn(b, 2)
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 3 3 3 4 4 2
# [2,] 4 2 5 2 5 5
RcppAlgos::comboGeneral(b, 2, repetition=F)
# [,1] [,2]
# [1,] 3 4
# [2,] 3 2
# [3,] 3 5
# [4,] 4 2
# [5,] 4 5
# [6,] 2 5
Edit
For the absolute differences according to your recent edit we may define an anonymous function:
sum(combn(a, 2, function(x) abs(diff(x))))
# [1] 840
Data:
a <- c(3, 4, 2, 5, 4, 4, 1, 5, 5, 4, 1, 4, 7, 2, 1, 3, 5, 2, 4, 2,
7, 4, 4, 1, 4, 3, 4, 4, 2, 4, 1)
b <- c(3, 4, 2, 5)

Related

Sample without replacement x number of times from a vector

I have a vector c(1,2,3,4,5,6,7,8,9,10,11). I want to draw a sample of N = 2, 5 times from this vector without replacement; I would like to save the results from each selection in a separate column.
The output could look like this:
structure(c(1, 2, 3, 9, 7, 10, 4, 8, 5, 6), dim = c(2L, 5L)).
matrix with two rows and five columns.
matrix(sample(x), nrow=2, ncol=5)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 5 7 4 8 2
# [2,] 3 10 9 1 6
Something like the following:
set.seed(7*11*13)
x <- c(1,2,3,4,5,6,7,8,9,10,11)
result <-matrix(as.numeric(NA), 2, 5)
for (i in 1:5) result[,i] <-
sample(x, 2, replace=FALSE)

R subsetting 3d array and modifying specific values if three conditions met

I'm working with a 3-d array and attempting to replace specific values when three conditions are met, and it will cope with NA values, and it performs a new evaluation for each time the conditions are met. I read somewhere that attempting to subset multiple dimension arrays in R was not a good idea. Any comments/suggestions to overcome these issues is most welcome. Any solution using base R or tidyverse (or anything!) most welcome. Thx. J
Essentially, I'm trying to replace the 7's in the final row of the third "sheet", with 0, 50% of the time when the other conditions are met.
This is my attempt using an ifelse but it fails, think it might need to be a more sophisticated apply statement or something. Here is my MWE:
library(abind)
arr1 <- as.array (matrix (c (1, 0, 1, 1, 1, 0, 0, NA, 1, 0, 1, 1,
1, 1, NA, 0, 1, 0, 1, 1, 0, 1, 1, 1), ncol = 8))
arr2 <- as.array (matrix (c (7, 5, 9, 1, 8, 4, 2, 3, 0, 8, 7, NA,
2, 4, 6, 3, 2, 8, 8, 3, 3, 6, 8, 5), ncol = 8))
arr3 <- as.array (matrix (c (7, 5, 7, 1, 8, 7, 2, 3, 6, 8, 7, 7,
2, 4, 5, 3, 2, NA, 8, 3, 4, 6, 8, 7), ncol = 8))
arrtot <- abind (arr1, arr2, arr3, along = 3)
## get the array to be changed
arrtot[dim(arrtot)[1], ,3]
arrtot[dim(arrtot)[1], ,3] <- ifelse(arrtot[dim(arrtot)[1], ,3] == 7 &
arrtot[dim(arrtot)[1], ,1] == 1 &
arrtot[dim(arrtot)[1], ,2] >= 5,
function (x) rbinom(1,1,0.5) * 7,
"original value unchanged")
Although there are several possible solutions, because of the random function, one possible correct solution would look like this where the two 7's that meet the conditions are modified to become zeros.
, , 1
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 1 0 0 1 0 1 1
[2,] 0 1 NA 1 1 1 1 1
[3,] 1 0 1 1 NA 0 0 1
, , 2
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 7 1 2 8 2 3 8 6
[2,] 5 8 3 7 4 2 3 8
[3,] 9 4 0 NA 6 8 3 5
, , 3
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 7 1 2 8 2 3 8 6
[2,] 5 8 3 7 4 2 3 8
[3,] 0 7 6 7 5 NA 4 0

Selecting all the row combinations from a matrix

I have a matrix consisting of 10 rows ,
I would like to make a combination between these row using R such as:
M= matrix(c(
1,2,3,4,
5,6,7,3,
5,5,4,8,
5,2,7,8,
4,8,7,8,
2,6,7,9,
5,6,7,4,
5,6,7,2,
5,6,7,3,
5,6,7,0),nrow=10, byrow=TRUE)
First step
combination (3 row ) from ( 10 row ).
This means that we have other matrices (resulting from matrix M) their number 120- matrix(3*4)
Second step
combination (6 row ) from ( 10 row )
This means that we have other matrices (we also resulting from matrix M) their number 210-matrix(6*4)
You can split matrix with apply to list of rows than use combn function as below:
M <- structure(c(1, 5, 5, 5, 4, 2, 5, 5, 5, 5, 2, 6, 5, 2, 8, 6, 6,
6, 6, 6, 3, 7, 4, 7, 7, 7, 7, 7, 7, 7, 4, 3, 8, 8, 8, 9, 4, 2,
3, 0), .Dim = c(10L, 4L))
x <- apply(M, 1, list)
# combinations for three rows
cmbs3 <- combn(x, 3)
ncol(cmbs3)
# 120
cmbs3[, 2]
# second combination
# [[1]]
# [[1]][[1]]
# [1] 1 2 3 4
#
#
# [[2]]
# [[2]][[1]]
# [1] 5 6 7 3
#
#
# [[3]]
# [[3]][[1]]
# [1] 5 2 7 8
# combinations for six rows
cmbs6 <- combn(x, 6)
ncol(cmbs6)
# 210
EDIT:
Or use elgant solution provided by nicola - subsetting by row index generated by combn (I like it much more :):
lapply(combn(10, 3, simplify = FALSE), function(x) M[x, ])
Output:
[[1]]
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 3
[3,] 5 5 4 8
[[2]]
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 3
[3,] 5 2 7 8
...
[[119]]
[,1] [,2] [,3] [,4]
[1,] 5 6 7 4
[2,] 5 6 7 3
[3,] 5 6 7 0
[[120]]
[,1] [,2] [,3] [,4]
[1,] 5 6 7 2
[2,] 5 6 7 3
[3,] 5 6 7 0

How to compare single values of a vector with matrix and if they occur take values from another matrix with the same position?

I'm a programming beginner and I'm not able to solve this problem:
I have a vector length 132 and two matrices A and B with the size of 132x24. I would like to take every single value of the vector and compare it rowwise with matrix A. If the value occurs in A I want to have the index of the column to go to matrix B and pick the value from the column with the same position (row and column indices) as in matrix A. The results should be given back as a vector with the same length of 132.
How to do this? Do I need a for loop or are there some smart ways to work with packages?
Unfortunately I can not give example data.
Thank you for your help!
# vector v contains values that I want to compare with matrix A
> v
[1] 5 1 10 1 7
# every single value of v occurs in every row of A only once
# I want to have the position of this value in matrix A
> A
[,1] [,2] [,3] [,4]
[1,] 5 7 4 1
[2,] 14 1 3 3
[3,] 13 3 1 10
[4,] 2 1 5 8
[5,] 13 2 5 7
# the position in matrix A equals the position in matrix B
# now the values of B have to be returned as a vector
> B
[,1] [,2] [,3] [,4]
[1,] 6 3 4 3
[2,] 5 2 5 5
[3,] 4 6 3 1
[4,] 3 6 1 5
[5,] 2 4 6 3
# vector with fitting values of B
> x
[1] 6 2 1 6 3
v <- c(5, 1, 10, 1, 7)
A <- matrix(c(
5, 7, 4, 1,
14, 1, 3, 3,
13, 3, 1, 10,
2, 1, 5, 8,
13, 2, 5, 7), 5, byrow = TRUE)
B <- matrix(c(
6, 3, 4, 3,
5, 2, 5, 5,
4, 6, 3, 1,
3, 6, 1, 5,
2, 4, 6, 3), 5, byrow = TRUE)
myfun <- function(i) which(v[i]==A[i,])
ii <- 1:length(v)
B[cbind(ii, sapply(ii, myfun))]
The function myfun() is quick'n'dirty.
To test if your data are ok you can calculate how often the value v[i] is found in the row A[i,]
countv <- function(i) sum(v[i]==A[i,])
all(sapply(ii, countv)==1) ### should be TRUE
If you get FALSE then inspect:
which(sapply(ii, countv)!=1)
Alright, I'm not sure how you pictured your output, but I've got something that comes near.
Example data:
x <- 1:132
set.seed(123)
A <- matrix(sample(1:1000, size = 132*24, replace = TRUE), nrow = 132, ncol = 24)
B <- matrix(rnorm(132*24), nrow = 132, ncol = 24)
Now we check for every value of vector x if and where it occurs in every row of matrix A:
x.vs.A <- sapply(x, function(x){
apply(A, 1, function(y) {
match(x, y)
})
})
This gives us a matrix x.vs.A with 132 rows (the rows of A) and 132 columns (the values of x). Within the cells of this matrix, we will find either NA, if the combination of one value of x and one row of A was unsuccessful, or the column position within A of the FIRST match of the value of x.
And now we extract the rowwise position and bind them together with the cell value, depiting the second (column) dimension of the matched value. Thus we create for every value of x a matrix of row/column position of matches in matrix A:
x.in.A <- apply(x.vs.A, 2, function(x) cbind(which(!is.na(x)), x[!is.na(x)]))
Example:
> x.in.A[[1]]
[,1] [,2]
[1,] 12 17
[2,] 42 17
[3,] 73 12
[4,] 123 21
This would show that the first value in vector x can be found in A[12, 17], in A[42, 17] and so on.
Now access these values in B, returning vectors for each value of x, and bind them to the matrices in the list:
x.in.B <- lapply(x.in.A, function(x){
apply(x, 1, function(y){
B[y[1], y[2]]
})
})
x.in.AB <- mapply(function(x, y) cbind(x, y),
x.in.A, x.in.B)
> x.in.AB[[1]]
y
[1,] 12 17 -0.2492526
[2,] 42 17 -0.7985330
[3,] 73 12 0.1253824
[4,] 123 21 -0.9704919

Combinatorics R

I have a problem I think best can be solved using cominatorics.
Lets say you have values 4 values (2,5,6,7). I would like to get all vectors where I pick out 3 of them, that is I would like a matrix with (2,5,6),(2,5,7),(5,6,7). I would like to do this with a general vector. How do I do it?
x <- c(2, 5, 6, 7)
combn(x, 3)
gives
> combn(x, 3)
[,1] [,2] [,3] [,4]
[1,] 2 2 2 5
[2,] 5 5 6 6
[3,] 6 7 7 7
I have created a package iterpc which is able to solve most of the combination/permutation related problems.
library(iterpc)
x <- c(2, 5, 6, 7)
# combinations
getall(iterpc(4, 3, label=x))
# combinations with replacement
getall(iterpc(4, 3, replace=TRUE, label=x))
# permutations
getall(iterpc(4, 3, label=x, ordered=TRUE))

Resources