On 14/12/2023 3:00 a.m., Martin Møller Skarbiniks Pedersen wrote:
Hi,

   I need to sort a data.frame based on a custom sorting function.
   It is easy in many languages but I can't find a way to do it in R.

   In many cases I could just use an ordered factor but my data.frame
contains poker hands and
I need to rank these hands. I already got a function that compares two hands.

Here is a MRE (Minimal, Reproducible Example):


df <- data.frame(person = c("Alice", "Bob", "Charlie"), value =
c("Medium", "Small", "Large"))

# 0 means equal, -1 means left before right, 1 means right before left
custom_sort <- function(left, right) {
   if (left == right) return(0)
   if (left == "Small") return(-1)
   if (left == "Medium" & right == "Large") return(-1)
   return(1)
}

#  sort df according to custom_soft
# expect output is a data.frame:
#     name   size
# 1     Bob Medium
# 2   Alice  Small
# 3 Charlie  Large

In this simple case I can just use an ordered factor but what about
the poker hands situation?


The general way in base R is to put the objects in a vector (which might be a list if they are complex objects), assign a class to that vector, and define either an xtfrm method or methods for ==, >, is.na, and extraction for that vector. The xtfrm method is basically the same as using an ordered factor, so I'll skip that, and show you the other way:

For your example, you could do it like this:

class(df$value) <- "sizeclass"

`>.sizeclass` <- function(left, right) custom_sort(unclass(left), unclass(right)) == 1

`==.sizeclass` <- function(left, right) custom_sort(unclass(left), unclass(right)) == 0

`[.sizeclass` <- function(x, i) structure(unclass(x)[i], class="sizeclass")

df[order(df$value),]

All the "unclass()" calls are needed to avoid infinite recursion. For a more complex kind of object where you are extracting attributes to compare, you probably wouldn't need so many of those.

There are likely other ways to do this in particular packages such as dplyr or data.table.

Duncan Murdoch

______________________________________________
R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to