Home > Mobile >  How to move the NA's from top of each column to below of each column in a matrix
How to move the NA's from top of each column to below of each column in a matrix

Time:11-14

this is my table now

    c1   c2   c3   c4   c5
r1  1    NA   NA   NA   NA
r2  1    1    NA   NA   NA
r3  1    1    1    NA   NA
r4  1    1    1    1    NA
r5  1    1    1    1    1

i want to shift the NA's at the bottom of each column and then shift the non NA numbers upward with out doing anything or arranging the non NA values in the matrix (suppose that the non NA values are unique), i just want them to shift up and make the NA's be at the bottom like this:

    c1   c2   c3   c4   c5
r1  1    1    1    1    1
r2  1    1    1    1    NA
r3  1    1    1    NA   NA
r4  1    1    NA   NA   NA
r5  1    NA   NA   NA   NA

is there any function that can do what i want to do with my matrix? i already found a similar question like this but the question is the oppposite of mine so i cant really use the answers in that question. any help would be appreciated.

CodePudding user response:

With a better example

df=data.frame(outer(1:5,1:5))
df[upper.tri(df)]=NA

  X1 X2 X3 X4 X5
1  1 NA NA NA NA
2  2  4 NA NA NA
3  3  6  9 NA NA
4  4  8 12 16 NA
5  5 10 15 20 25

sapply(df,function(x){c(x[!is.na(x)],rep(NA,sum(is.na(x))))})

     X1 X2 X3 X4 X5
[1,]  1  4  9 16 25
[2,]  2  6 12 20 NA
[3,]  3  8 15 NA NA
[4,]  4 10 NA NA NA
[5,]  5 NA NA NA NA

CodePudding user response:

mat[] = apply(mat, 2, sort, na.last = TRUE)

#    c1 c2 c3 c4 c5
# r1  1  1  1  1  1
# r2  1  1  1  1 NA
# r3  1  1  1 NA NA
# r4  1  1 NA NA NA
# r5  1 NA NA NA NA

(Reproducible) Data

mat = matrix(
  c(1,1,1,1,1,NA,1,1,1,1,NA,NA,1,1,1,NA,NA,NA,1,1,NA,NA,NA,NA,1),
  nrow = 5L,
  dimnames = list(paste0("r", 1:5), paste0("c", 1:5))
)

CodePudding user response:

We can try the code below by extracting out the non-NA entries and assigning them to new positions in a all NA matrix, e.g.,

idx <- !is.na(mat)
m <- mat   NA
m[cbind(sequence(colSums(idx)), col(mat)[idx])] <- na.omit(mat)

which gives

> m
   c1 c2 c3 c4 c5
r1  1  1  1  1  1
r2  1  1  1  1 NA
r3  1  1  1 NA NA
r4  1  1 NA NA NA
r5  1 NA NA NA NA

CodePudding user response:

using the tidyverse, it's a little clumsy as you have to put the data into a dataframe then back into a matrix, but the rev function is pretty easy to understand:

# Reproducible data
library(tidyverse)
mat <- as.matrix(read_csv("c1,c2,c3,c4,c5
         1, NA,NA,NA,NA
         1, 1, NA,NA,NA
         1, 1, 1, NA,NA
         1, 1, 1, 1, NA
         1, 1, 1, 1, 1"))  


as.matrix(map_dfc(data.frame(mat), rev))

>     c1 c2 c3 c4 c5
>[1,]  1  1  1  1  1
>[2,]  1  1  1  1 NA
>[3,]  1  1  1 NA NA
>[4,]  1  1 NA NA NA
>[5,]  1 NA NA NA NA
  • Related