Martin Møller Skarbiniks Pedersen
2023-Dec-14 08:00 UTC
[R] Sorting based a custom sorting function
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? Regards Martin
This sounds suspiciously like homework (which is off-topic... see the Posting Guide), and you haven't indicated how you plan to encode your poker hands, and most core features of other languages are possible in R so if you really understand these other techniques and R then you should be able to do this already. If this is not homework, then please show your work so far instead of showing a completely different example. On December 14, 2023 12:00:12 AM PST, "Martin M?ller Skarbiniks Pedersen" <traxplayer at gmail.com> 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? > >Regards >Martin > >______________________________________________ >R-help at 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.-- Sent from my phone. Please excuse my brevity.
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