Reputation: 71
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.
EDIT:
is there a way that this can be done by a loop? or like transferring the elements into another matrix then the new matrix has the correct position of the elements? many thanks
Upvotes: 1
Views: 358
Reputation: 4346
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
where map_dfc(<data>, <function>)
will apply a <function>
to each column in the <data>
and stick the returned columns together as a new data.frame
, hence map_dfc (dataframe columns)
<data>
here is provided by data.frame(mat)
which is your matrix mat
converted into a dataframe
.
the <function>
provided is rev
which reverses each column.
finally the result of map_dfc
is converted back into a matrix.
Upvotes: 0
Reputation: 101327
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(c(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
Upvotes: 2
Reputation: 10375
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
Upvotes: 1