In general, xtfrm() is the generic function to get a numeric vector that
sorts like the given input vector. Decreasing sorting can then be done by
sorting with the negated value of xtfrm(). (This is exactly how e.g.
dplyr’s desc() is implemented.)
For example, with the data in question:
df <- read.table(text = "
P1 P2 P3 T1 T2 T3 I1 I2
2 3 5 52 43 61 6 b
6 4 3 72 NA 59 1 a
1 5 6 55 48 60 6 f
2 4 4 65 64 58 2 b
", header = TRUE)
df[order(-xtfrm(df$I1), df$I2), ]
#> P1 P2 P3 T1 T2 T3 I1 I2
#> 1 2 3 5 52 43 61 6 b
#> 3 1 5 6 55 48 60 6 f
#> 4 2 4 4 65 64 58 2 b
#> 2 6 4 3 72 NA 59 1 a
This approach can be generalized into a base R function to sort
data frames by given columns, that also accepts a vector-valued decreasing
argument. From my answer to
this recent question:
sortdf <- function(x, by = colnames(x), decreasing = FALSE) {
x[do.call(order, Map(sortproxy, x[by], decreasing)), , drop = FALSE]
}
sortproxy <- function(x, decreasing = FALSE) {
as.integer((-1)^as.logical(decreasing)) * xtfrm(x)
}
And with the current example data, we (of course) get:
sortdf(df, by = c("I1", "I2"), decreasing = c(TRUE, FALSE))
#> P1 P2 P3 T1 T2 T3 I1 I2
#> 1 2 3 5 52 43 61 6 b
#> 3 1 5 6 55 48 60 6 f
#> 4 2 4 4 65 64 58 2 b
#> 2 6 4 3 72 NA 59 1 a