Selecting odd and even columns in a matrix

Hi,
I would like to select odd and even columns from a matrix that in columns' names has got odd and even numbers as a strings.
Here is my_matrix:

my_matrix <- structure(c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA), .Dim = c(6L, 14L), .Dimnames = list(
    c("P18", "P19", "P20", "P21", "P22", "P23"), c("P35_cor", 
    "P35_p", "P36_cor", "P36_p", "P37_cor", "P37_p", "P38_cor", 
    "P38_p", "P39_cor", "P39_p", "P40_cor", "P40_p", "P41_cor", 
    "P41_p")))

I have tried with parse_number but it converts all variables to V1, V2 and so on.

colnames(my_matrix) <- names(parse_number(colnames(my_matrix)))

How do I do it ? Thank you for any ideas.

my_matrix <- structure(c(
  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
  NA, NA, NA, NA, NA, NA, NA
), .Dim = c(6L, 14L), .Dimnames = list(
  c("P18", "P19", "P20", "P21", "P22", "P23"), c(
    "P35_cor",
    "P35_p", "P36_cor", "P36_p", "P37_cor", "P37_p", "P38_cor",
    "P38_p", "P39_cor", "P39_p", "P40_cor", "P40_p", "P41_cor",
    "P41_p"
  )
))

# odd and even columns

# get indices of columns
get_index <- function(x,y) seq(from = y, to = dim(x)[2],by = 2)

my_matrix[,get_index(my_matrix,1)]
#>     P35_cor P36_cor P37_cor P38_cor P39_cor P40_cor P41_cor
#> P18      NA      NA      NA      NA      NA      NA      NA
#> P19      NA      NA      NA      NA      NA      NA      NA
#> P20      NA      NA      NA      NA      NA      NA      NA
#> P21      NA      NA      NA      NA      NA      NA      NA
#> P22      NA      NA      NA      NA      NA      NA      NA
#> P23      NA      NA      NA      NA      NA      NA      NA
my_matrix[,get_index(my_matrix,2)]
#>     P35_p P36_p P37_p P38_p P39_p P40_p P41_p
#> P18    NA    NA    NA    NA    NA    NA    NA
#> P19    NA    NA    NA    NA    NA    NA    NA
#> P20    NA    NA    NA    NA    NA    NA    NA
#> P21    NA    NA    NA    NA    NA    NA    NA
#> P22    NA    NA    NA    NA    NA    NA    NA
#> P23    NA    NA    NA    NA    NA    NA    NA

# odd and even column names
shadow <- as.numeric(gsub("[Pp_cor]","",colnames(my_matrix)))

my_matrix[,which(shadow %% 2 != 0)]
#>     P35_cor P35_p P37_cor P37_p P39_cor P39_p P41_cor P41_p
#> P18      NA    NA      NA    NA      NA    NA      NA    NA
#> P19      NA    NA      NA    NA      NA    NA      NA    NA
#> P20      NA    NA      NA    NA      NA    NA      NA    NA
#> P21      NA    NA      NA    NA      NA    NA      NA    NA
#> P22      NA    NA      NA    NA      NA    NA      NA    NA
#> P23      NA    NA      NA    NA      NA    NA      NA    NA
my_matrix[,which(shadow %% 2 == 0)]
#>     P36_cor P36_p P38_cor P38_p P40_cor P40_p
#> P18      NA    NA      NA    NA      NA    NA
#> P19      NA    NA      NA    NA      NA    NA
#> P20      NA    NA      NA    NA      NA    NA
#> P21      NA    NA      NA    NA      NA    NA
#> P22      NA    NA      NA    NA      NA    NA
#> P23      NA    NA      NA    NA      NA    NA
1 Like

This is great, works like a charm. Thank you.
If I may ask please:

  1. in the get_index function, what does it mean, I mean x are rows and y are columns ?
seq(from = y, to = dim(x)[2],by = 2)

and here:

"[Pp_cor]"

I think this is regex, why do you use Pp ?
Thank you again.

Yes, subsets work by row/column order, but x and y in the quoted code are the formal arguments to get_index() representing the name of the matrix, x and the positions from which to be the seq so that we end up with odd and even indices with which to work.

seq(from = 1, to = dim(mtcars)[2], by = 2) # the first one is passed as y
#> [1]  1  3  5  7  9 11
seq(from = 2, to = dim(mtcars)[2], by = 2) # the first one is passed as y
#> [1]  2  4  6  8 10

is called a character class regex that searches for the letters and characters ; here it is being used to remove those from the variable names as an argument to gsub.

Thank you, that's great.
So "p" stands for "35" in this regex character class ?
obraz

Why does it have to be "p" ?

p stands for "p", just one of the characters in the variable names that are non-numeric and are being removed to be able to specify those columns whose names, if their names contained only numbers could be identified as odd or even.

Thank you very much indeed, I just try to understand the magic behind this regex of yours [Pp_cor],
that it removes all letters and _ from both columns like "P35_cor" and "P35_p".

obraz

Hi @technocrat
I have tried a bit experimenting with your code and suddenly RStudio's behaviour became a bit strange.
When I write following line of code:

my_matrix[,which(shadow %% 2 != 0)] %>% apply(my_matrix[, odd], 2, function(x) {return(1)}) aaaaaa

at the end of a line cursor become a vertical line crossing letters "a".
obraz

obraz

It looks like Delete and Backspace keys are not deleting what I want as usual.
The cursor is standing right in the middle of "a" not before as usual.

Did I press something on my keyboard or is it a bug ?

Error: unexpected symbol in "my_matrix[,which(shadow %% 2 != 0)] %>% apply(my_matrix[, odd], 2, function(x) {return(1)}) aaaaaa

should produce an error message

Yes, I know, I just have written it to show a bit strange behaviour of the cursor itself.

Here is a different solution. There is no requirement to use column names just because they are present.

odd <- seq(1, 14, 2)
my_matrix2<-matrix(0,nrow=6,ncol=7)
j=1
for (i in odd){
  my_matrix2[,j] <- my_matrix[ ,i]
  j=j+1
}
### now recover column names and reapply them
colnames(my_matrix2) <- colnames(my_matrix[,odd])

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.