I want to apply two functions one function on the block diagonal and the second function on the off-diagonal elements in the data frame
Asked Answered
P

2

8
df<- data.frame(a=c(1:10), b=c(21:30),c=c(1:10), d=c(14:23),e=c(11:20),f=c(-6:-15),g=c(11:20),h=c(-14:-23),i=c(4:13),j=c(1:10))

In this data frame, I have three block-diagonal matrices which are as shown in the image below enter image description here

I want to apply two functions, one is the sine function for block diagonal and the second is cosine function for the other elements and generates the same structure of the data frame.

sin(df[1:2,1:2])
sin(df[3:5,3:5])
sin(df[6:10,6:10])
cos(the rest of the elements)
Pola answered 22/5, 2020 at 12:25 Comment(0)
P
7

1) outer/arithmetic Create a logical block diagonal matrix indicating whether the current cell is on the block diagonal or not and then use that to take a convex combination of the sin and cos values giving a data.frame as follows:

v <- rep(1:3, c(2, 3, 5))
ind <- outer(v, v, `==`)
ind * sin(df) + (!ind) * cos(df)

2) ifelse Alternately, this gives a matrix result (or use as.matrix on the above). ind is from above.

m <- as.matrix(df)
ifelse(ind, sin(m), cos(m))

3) Matrix::bdiag Another approach is to use bdiag in the Matrix package (which comes with R -- no need to install it).

library(Matrix)

ones <- function(n) matrix(1, n, n)
ind <- bdiag(ones(2), ones(3), ones(5)) == 1

Now proceed as in the last line of (1) or as in (2).

Photoengrave answered 22/5, 2020 at 12:45 Comment(0)
S
2

If it's okay for you that the result is stored in a new data frame you could change the order of your instructions and do it like that:

ndf <- cos(df)
ndf[1:2,1:2] <- sin(df[1:2,1:2])
ndf[3:5,3:5] <- sin(df[3:5,3:5])
ndf[6:10,6:10] <- sin(df[6:10,6:10])
Sedative answered 22/5, 2020 at 12:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.