32

Sample data:

temp = data.frame(col = list(NA, 1, 2, 3) )

Using arrange:

temp %>%
    arrange(col)

gives

  col
1   1
2   2
3   3
4  NA

and

temp %>%
            arrange(desc(col))

gives

  col
1   3
2   2
3   1
4  NA

I would like

  col
1   NA
2   3
3   2
4   1

that is, to put NAs first. Does anyone know how to do this?

zx8754
  • 52,746
  • 12
  • 114
  • 209
Alex
  • 15,186
  • 15
  • 73
  • 127

3 Answers3

71

You could also do:

 m %>%
 arrange(!is.na(wt), wt) #@Spacedman's dataset
 #    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
 #1  18.7   8 360.0 175 3.15    NA 17.02  0  0    3    2
 #2  24.4   4 146.7  62 3.69    NA 20.00  1  0    4    2
 #3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
 #4  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
 #5  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
 #6  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
 #7  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
 #8  19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
 #9  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
 #10 14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
akrun
  • 874,273
  • 37
  • 540
  • 662
  • 2
    @user3858 Here we are arranging by the logical vector `!is.na(wt)` of TRUE/FALSE. So, now it will order based on the letters i.e. `sort(sample(c(TRUE, FALSE), 10, replace = TRUE))` or if we are using `is.na` then `set.seed(24); sort(!is.na(sample(c(1:3, NA), 10, replace = TRUE)))` Note that F in FALSE is before T in TRUE alphabetically – akrun Dec 05 '17 at 16:34
5

Write a function that sorts a data frame and then pass the handy na.last=FALSE option to order. My original version can be found in the edit history, David Arenburg improved it to this:

> sortNA=function(d,n,...){d[order(d[[deparse(substitute(n))]],...),]}

Then use like this

> m=mtcars[1:10,]
> m$wt[5]=NA
> m$wt[8]=NA
> m %.% sortNA(wt, na.last=FALSE)
                   mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Hornet Sportabout 18.7   8 360.0 175 3.15    NA 17.02  0  0    3    2
Merc 240D         24.4   4 146.7  62 3.69    NA 20.00  1  0    4    2
Datsun 710        22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Mazda RX4         21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Merc 230          22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
Hornet 4 Drive    21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Merc 280          19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
Valiant           18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
Duster 360        14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4

Add decreasing=TRUE to sort in the opposite order.

You might also consider posting an issue to the dplyr github issue tracker to suggest a new option to the arrange function to do this.

Spacedman
  • 92,590
  • 12
  • 140
  • 224
  • Thanks. I wonder whether this, or akrun's solution is faster? As Akrun's solution uses the built in arrange function but this one uses order? – Alex Aug 13 '14 at 00:45
  • I used a similar hack in [my duplicate of this question](http://stackoverflow.com/q/43343590/2451238). – mschilli Apr 12 '17 at 08:01
3

The order function in base R has an na.last argument:

> temp=data.frame(col=c(NA,1,2,3))
> temp[order(temp[,"col"],na.last=F),]
[1] NA  1  2  3
nisetama
  • 7,764
  • 1
  • 34
  • 21