Subtracting two columns to give a new column in R - r

Hello I´am trying to subtract the column B from column A in a dat matrix to create a C column (A - B):
My input:
A B
1 2
2 2
3 2
4 2
My expected output:
A B C
1 2 -1
2 2 0
3 2 1
4 2 2
I have tried: dat$C <- (dat$A - dat$B), but I get a: ## $ operator is invalid for atomic vectorserror
Cheers.

As #Bryan Hanson was saying in the above comment, your syntax and data organization relates more to a data frame. I would treat your data as a data frame and simply use the syntax you provided earlier:
> data <- data.frame(A = c(1,2,3,4), B = c(2,2,2,2))
> data$C <- (data$A - data$B)
> data
A B C
1 1 2 -1
2 2 2 0
3 3 2 1
4 4 2 2

Yes right, If you really mean a matrix, you can see this example
> x <- matrix(data=1:3,nrow=4,ncol=3)
> x
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 3 1
[3,] 3 1 2
[4,] 1 2 3
> x[,3] = x[,1]-x[,2]
> x
[,1] [,2] [,3]
[1,] 1 2 -1
[2,] 2 3 -1
[3,] 3 1 2
[4,] 1 2 -1
>

However, one should absolutely point out here that matrix operations in R don't abide by the usual linear algebra closure.
> x[,3]-x[,1]
[1] 2 -1 -1 2
> is.matrix(x[,3]-x[,1])
[1] FALSE
Further, one more directly anticipates a column vector which can be obtained by applying the matrix transpose TWICE (which is weird in itself) with the first one casting the output as a matrix.
> t(t(x[,3]-x[,1]))
[,1]
[1,] 2
[2,] -1
[3,] -1
[4,] 2
Or one can use the drop=FALSE option:
>x[,3,drop=FALSE] - x[,1,drop=FALSE]
[,1]
[1,] 2
[2,] -1
[3,] -1
[4,] 2
Behavior of 2D slices From 3D array are fine though.

Related

Get a grid of unique combination from vector

I'd like to return a grid with unique rows from a sequence vector. I'm looking for a general solution so I can pass any number of sequences in a vector. I don't know the terminology for this, so how can I do this?
Example
num <- 3
v <- c(seq(1, num, 1))
Desired Output
1 2 3
2 3 1
3 1 2
Second and third column can be switched:
1 3 2
2 1 3
3 2 1
I tried manipulating expand.grid() but it requires sorting and filtering which seems excessive.
We can use permn from combinat package which generates all possible permutations of v and then select top num of them using head
head(as.data.frame(do.call(rbind, combinat::permn(v))), num)
# V1 V2 V3
#1 1 2 3
#2 1 3 2
#3 3 1 2
We can also use sample to select any num rows instead of first num rows using head.
where
combinat::permn(v) #gives
#[[1]]
#[1] 1 2 3
#[[2]]
#[1] 1 3 2
#[[3]]
#[1] 3 1 2
#[[4]]
#[1] 3 2 1
#[[5]]
#[1] 2 3 1
#[[6]]
#[1] 2 1 3
Here's one solution (column order differs but the idea holds):
n = 3
sweep(replicate(n, 1:n), 2, 1:n, "+") %% n + 1
[,1] [,2] [,3]
[1,] 3 1 2
[2,] 1 2 3
[3,] 2 3 1
Explanation:
replicate will first create a matrix where each row is 1:n:
[,1] [,2] [,3]
[1,] 1 1 1
[2,] 2 2 2
[3,] 3 3 3
I then use the sweep function to add 1 to column 1, 2 to column 2, 3 to column 3:
[,1] [,2] [,3]
[1,] 2 3 4
[2,] 3 4 5
[3,] 4 5 6
At this point, you can do a modulo on the matrix and then add 1 to arrive at the desired matrix.
Edit: If you need to have the same column order as you had above, can do
(sweep(replicate(n, 1:n), 2, 1:n, "+") + 1) %% n + 1
Another base R option
t(sapply(1:length(v), function(i) rep(v, 2)[i:(i+2)]))
# [,1] [,2] [,3]
#[1,] 1 2 3
#[2,] 2 3 1
#[3,] 3 1 2
Explanation: We cyclically permute v and store the vectors as column vectors in a matrix.
For general v (of length length(v)) this becomes
t(sapply(1:length(v), function(i) rep(v, 2)[i:(i + length(v) - 1)]))

Frequency/Contingency table along 1 dimension in R

I'm trying to count co-occurrences along a single dimension. It's somewhat similar to win/loss, dominance matrices, or frequency tables, (and spectrograms/raster plots) but without directionality and along 1 variable.
Here's an example of the data:
person response
1 a 1
2 a 2
3 a 4
4 b 1
5 b 2
6 c 2
7 c 4
8 d 4
9 d 3
The goal would be to get an n x n matrix as the one shown below (the NA's can also be the number of occurrences period):
[,1] [,2] [,3] [,4]
[1,] NA 2 0 1
[2,] - NA 0 2
[3,] - - NA 1
[4,] - - - NA
How can I convert the long data into a matrix in R? (without manual counting).
What is this type of metric is called? It's not a typical 'contingency' table.
After the table is created, what's the best way to plot the resulting matrix with colors denoting the count/frequency?
Test this
r1 = sort(unique(df1$response))
r2 = split(df1$response, df1$person)
ans = sapply(seq_along(r1), function(i)
rowSums(sapply(r2, function(x) (r1[i] %in% x) * (r1 %in% x))))
diag(ans) = NA
ans
# [,1] [,2] [,3] [,4]
#[1,] NA 2 0 1
#[2,] 2 NA 0 2
#[3,] 0 0 NA 1
#[4,] 1 2 1 NA

Extracting unique rows in a 3+ column matrix

Using R, I am trying to extract unique rows in a matrix, where a "unique row" is subject to all the values in a given row.
For example if I had this data set:
x = matrix(c(1,1,1,2,2,5,1,2,2,1,2,1,5,3,5,2,1,1),6,3)
Rows 1 & 6, and rows 4 & 5 are duplicated since (1,1,5) = (5,1,1) and (2,1,2) = (2,2,1).
Ultimately, i'm trying to end up with something in the form of:
y = matrix(c(1,1,1,2,1,2,2,1,5,3,5,2),4,3)
or
z = matrix(c(1,1,2,5,2,2,2,1,3,5,1,1),4,3)
The order doesn't matter as long as only one of the unique rows remains. I've searched online, but functions such as unique() and duplicated() have only worked for exact matching rows.
Thanks in advance for any help you provide.
Another answer: use sets. Slightly modified matrix:
library(sets)
x <- matrix(c(1,1,1,2,2,5,5, 1,2,2,1,2,1,5, 5,3,5,2,1,1,1),7,3)
x
[,1] [,2] [,3]
[1,] 1 1 5
[2,] 1 2 3
[3,] 1 2 5
[4,] 2 1 2
[5,] 2 2 1
[6,] 5 1 1
[7,] 5 5 1
If (5,1,1) = (5,5,1) you can use just ordinary sets:
a <- sapply(1:nrow(x), function(i) as.set(x[i,]))
x[!duplicated(a),]
[,1] [,2] [,3]
[1,] 1 1 5
[2,] 1 2 3
[3,] 1 2 5
[4,] 2 1 2
Note: rows 6 and 7 are both gone.
If (5,1,1) != (5,5,1), use generalized sets:
b <- sapply(1:nrow(x), function(i) as.gset(x[i,]))
x[!duplicated(b),]
[,1] [,2] [,3]
[1,] 1 1 5
[2,] 1 2 3
[3,] 1 2 5
[4,] 2 1 2
[5,] 5 5 1

Creating a matrix of increasing concentric rings of numbers in R

I need to write a function in R that creates a matrix of increasing concentric rings of numbers. This function's argument is a number of layers. For example, if x = 3, matrix will look like following:
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
I have no idea how to do it. I would really appreciate any suggestions.
1) Try this:
x <- 3 # input
n <- 2*x-1
m <- diag(n)
x - pmax(abs(row(m) - x), abs(col(m) - x))
giving:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 1 2 2 2 1
[3,] 1 2 3 2 1
[4,] 1 2 2 2 1
[5,] 1 1 1 1 1
2) A second approach is:
x <- 3 # input
n <- 2*x-1
mid <- pmin(1:n, n:1) # middle row/column
outer(mid, mid, pmin)
giving the same result as before.
3) yet another approach having some similarities to the prior two approaches is:
x <- 3 # input
n <- 2*x-1
Dist <- abs(seq_len(n) - x)
x - outer(Dist, Dist, pmax)
Note: The above gives the sample matrix shown in the question but the subject of the question says the rings should be increasing which may mean increasing from the center to the outside so if that is what is wanted then try this where m, mid and Dist are as before:
pmax(abs(row(m) - x), abs(col(m) - x)) + 1
or
x - outer(mid, mid, pmin) + 1
or
outer(Dist, Dist, pmax) + 1
Any of these give:
[,1] [,2] [,3] [,4] [,5]
[1,] 3 3 3 3 3
[2,] 3 2 2 2 3
[3,] 3 2 1 2 3
[4,] 3 2 2 2 3
[5,] 3 3 3 3 3
Try this:
x<-3
res<-matrix(nrow=2*x-1,ncol=2*x-1)
for (i in 1:x) res[i:(2*x-i),i:(2*x-i)]<-i
res
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 1 1 1 1
#[2,] 1 2 2 2 1
#[3,] 1 2 3 2 1
#[4,] 1 2 2 2 1
#[5,] 1 1 1 1 1
A recursive solution for kicks (odd n only)
f <- function(n) if (n == 1) 1 else `[<-`(matrix(1,n,n), 2:(n-1), 2:(n-1), 1+Recall(n-2))
f(5)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 1 1 1 1
# [2,] 1 2 2 2 1
# [3,] 1 2 3 2 1
# [4,] 1 2 2 2 1
# [5,] 1 1 1 1 1
Here's the logic, implement it yourself in R.
Create a matrix with number of rows and columns equal to 2*x-1 and
fill it with zeros and start traversing the array from (0,0) to
(2*x-2,2*x-2).
Now, at each cell, calculate the 'level' of the cell. The level of
the cell is the nearest distance of it from the four borders of
the matrix, i.e. min(i,j,2*x-2-i,2*x-2-j).
This 'level' value is the one to be put in the cell.

R: Return a vector for each row of a matrix which lists what colum the value x is in

Okay, sorry I know this sounds unnecessarily confusing. I am basically looking to return a vector of elements equal to the number of rows with each element specifying where in the matrix the specified outcome occurred.
library(gtools)
(A <- permutations(3, 3))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 1 3 2
[3,] 2 1 3
[4,] 2 3 1
[5,] 3 1 2
[6,] 3 2 1
Using the unknown function foo would return:
foo(A, match=1)
[1] 1 1 2 3 2 3
foo(A, match=2)
[1] 2 3 1 1 3 2
Thank you for any help you can provide!
Use max.col and some indexing of the matrix:
> max.col(A==1)
[1] 1 1 2 3 2 3
> max.col(A==2)
[1] 2 3 1 1 3 2
Try
foo <- function(mat, match=1){
indx <- which(mat==match, arr.ind=TRUE)
indx[order(indx[,1]),2]
}
foo(A, 1)
#[1] 1 1 2 3 2 3
foo(A,2)
#[1] 2 3 1 1 3 2

Resources