You can do this without looping in R. Let's assume you have a matrix m
, which is probably more appropriate than a data.frame
in this case. Then, we just use order
to order within the rows, such that NA values go last. Since the sorting in R is conservative, the order of the non-NA values is preserved.
v <- m[order(row(m), is.na(m))]
dim(v) <- dim(m)
t(v)
## [,1] [,2] [,3] [,4]
## [1,] "a" "b" "c" NA
## [2,] "d" "e" NA NA
## [3,] "f" "g" "h" "i"
## [4,] "j" "k" "l" NA
To achieve performance over millions of rows, you would probably want to use radix sort. Unfortunately, that is currently limited (why?) to 100,000 unique values, but it would look like:
v2 <- m[sort.list(is.na(m) + (row(m)-1L)*2L + 1L, method="radix")]