I want to create symmetric circulant matrices.
Example of order 4:
1 2 : 3 4
2 1 : 4 3
.........
3 4 : 1 2
4 3 : 2 1
Example of order 8:
1 2 3 4 : 5 6 7 8
2 1 4 3 : 6 5 8 7
3 4 1 2 : 7 8 5 6
4 3 2 1 : 8 7 6 5
..................
5 6 7 8 : 1 2 3 4
6 5 8 7 : 2 1 4 3
7 8 5 6 : 3 4 1 2
8 7 6 5 : 4 3 2 1
How do I do this in R?
This appears to solve the problem but is way too clever. The flip(x)==1 idiom gives a matrix (once converted to numeric) of the form [0 1; 1 0] ...
flip <- function(x) x[rev(seq(nrow(x))),]
x <- matrix(c(1,2,2,1),2)
x2 <- kronecker(2*(flip(x)==1),x,"+") ## 4x4 solution
x3 <- kronecker(4*(flip(x)==1),x2,"+") ## 8x8 solution
Repeat for larger matrices of size 2^n (embed in a for loop if you want to do this a lot) ... I don't know what your desired answer would be for a matrix that's not of size 2^n (e.g. 12x12), but you might be able to find a way to extend this machinery.
Related
This question already has answers here:
How to create a consecutive group number
(13 answers)
Closed 1 year ago.
I have these set of variables in the column Num I want to create another column that ranks them with size similar to rankt below but I don't like how this is done.
x <- data.frame("Num" = c(2,5,2,7,7,7,2,5,5))
x$rankt <- rank(x$Num)
Num rankt
1 2 2
2 5 5
3 2 2
4 7 8
5 7 8
6 7 8
7 2 2
8 5 5
9 5 5
Desired Outcome I would like for rankt
Num rankt
1 2 1
2 5 2
3 2 1
4 7 3
5 7 3
6 7 3
7 2 1
8 5 2
9 5 2
Well, a crude approach is to turn them to factors, which are just increasing numbers with labels, and then fetch those numbers:
x <- data.frame("Num" = c(2,5,2,7,7,7,2,5,5))
x$rankt <- as.numeric(as.factor( rank(x$Num) ))
x
It produces:
Num rankt
1 2 1
2 5 2
3 2 1
4 7 3
5 7 3
6 7 3
7 2 1
8 5 2
9 5 2
A solution with dplyr
library(dplyr)
x1 <- x %>%
mutate(rankt=dense_rank(desc(-Num)))
I have a factor variable with 6 levels, which simplified looks like:
1 1 2 2 2 3 3 3 4 4 4 4 5 5 5 6 6 6 1 1 1 2 2 2 2... 1 1 1 2 2... (with n = 78)
Note, that each number is repeated mostly but not always three times.
I need to transform this variable into the following pattern:
1 1 2 2 2 3 3 3 4 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 8...
where each repetition of the 6 levels continuous counting ascending.
Is there any way / any function that lets me do that?
Sorry for my bad description!
Assuming that you have a numerical vector that represents your simplified version you posted. i.e. x = c(1,1,1,2,2,3,3,3,1,1,2,2), you can use this:
library(dplyr)
cumsum(x != lag(x, default = 0))
# [1] 1 1 1 2 2 3 3 3 4 4 5 5
which compares each value to its previous one and if they are different it adds 1 (starting from 1).
Maybe you can try rle, i.e.,
v <- rep(seq_along((v<-rle(x))$values),v$lengths)
Example with dummy data
x = c(1,1,1,2,2,3,3,3,4,4,5,6,1,1,2,2,3,3,3,4,4)
then we can get
> v
[1] 1 1 1 2 2 3 3 3 4 4 5 6 7 7 8 8 9 9
[19] 9 10 10
In base you can use diff and cumsum.
c(1, cumsum(diff(x)!=0)+1)
# [1] 1 1 2 2 2 3 3 3 4 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 8
Data:
x <- c(1,1,2,2,2,3,3,3,4,4,4,4,5,5,5,6,6,6,1,1,1,2,2,2,2)
I want to replicate a vector with one value within this vector is missing (sequentially).
For example, my vector is
value <- 1:7
First, the series is without 1, second without 2, and so on. In the end, the series is in one vector.
The intended output looks like
2 3 4 5 6 7 1 3 4 5 6 7 1 2 4 5 6 7 1 2 3 5 6 7 1 2 3 4 6 7 1 2 3 4 5 6
Is there any smart way to do this?
You could use the diagonal matrix to set up a logical vector, using it to remove the appropriate values.
n <- 7
rep(1:n, n)[!diag(n)]
# [1] 2 3 4 5 6 7 1 3 4 5 6 7 1 2 4 5 6 7 1 2 3 5 6 7 1 2 3 4 6 7 1 2 3 4 5
# [36] 7 1 2 3 4 5 6
Well, you can certainly do it as a one-liner but I am not sure it qualifies as smart. For example:
x <- 1:7
do.call("c", lapply(as.list(-1:-length(x)), function(a)x[a]))
This simple uses lapply to create a list of copies of x with each of its entries deleted, and then concatenates them using c. The do.call function applies its first argument (a function) to its second argument (a list of arguments to the function).
For fun, it's also possible to just use rep:
> n <- 7
> rep(1:n, n)[rep(c(FALSE, rep(TRUE, n)), length.out=n^2)]
[1] 2 3 4 5 6 7 1 3 4 5 6 7 1 2 4 5 6 7 1 2 3 5 6 7 1 2 3 4 6 7 1 2 3 4 5 7 1 2
[39] 3 4 5 6
But lapply is cleaner, I think.
You could also do:
n <- 7
rep(seq(n), n)[-seq(1,n*n,n+1)]
#[1] 2 3 4 5 6 7 1 3 4 5 6 7 1 2 4 5 6 7 1 2 3 5 6 7 1 2 3 4 6 7 1 2 3 4 5 7 1 2 3 4 5 6
I have a data frame and a function. I when I run a function with the data frame as an argument, somehow it seems it changes the structure.
So I am getting errors.
I pasted the code and the data frame I am working on.
The error I am getting is "Error in plot[row, 1] : incorrect number of dimensions"
Code
avg.value = function(plot,delta,row) {
#plot=deparse(substitute(plot))
#delta=Week1DeltaT
value=as.numeric()
avg.value=as.numeric()
for (row in 1:11) {
# compute firtst value separately
value[1]=plot[row,1]*delta[1]
value[1]
# Loop for rest of the values
i=1
end = length(delta)-1
end
for( i in 1:end) {
value[i+1]=(plot[row,i+1]-plot[row,i])*delta[i+1]
i=i+1
}
avg.value[row]=sum(value)/4
}
return(avg.value)
}
Variable(data frame)
plot
6 7 8 9 10 11 12 13
R1 3 3 4 4 4 4 4 4
R2 1 3 3 3 3 4 4 4
R3 1 1 3 4 4 4 4 4
R4 1 3 4 4 4 4 4 4
R5 3 4 4 4 4 4 4 4
R6 1 3 3 4 4 4 4 4
R7 1 2 2 3 3 4 4 4
R8 2 4 4 4 4 4 4 4
R9 1 2 2 4 4 4 4 4
R10 3 4 4 4 4 4 4 4
R11 1 1 4 4 4 4 4 4
delta(a numeric vector of length 8)
6 7 8 9 10 11 12 13
row(a single numeric value. It can be from 1 to 11)
1~11, numeric
I realized from the comment that I accidentally begin the loop from the wrong place. Now this function works as I wanted.
Suppose I have a vector of size n=8 v=(5,8,2,7,9,12,2,1). I would like to know how to build a N x N matrix that compares every pair of values of v and returns the minimum value of each comparation. In this example, it would be like this:
5 5 2 5 5 5 2 1
5 8 2 7 8 8 2 1
2 2 2 2 2 2 2 1
5 7 2 7 7 7 2 1
5 8 2 7 9 9 2 1
5 8 2 7 9 12 2 1
2 2 2 2 2 2 2 1
1 1 1 1 1 1 1 1
Could you help me with this, please?
outer(v, v, pmin)
Notice the use of pmin, not min, as the former is vectorised but not the latter.