Re: [R] Sorting based a custom sorting function
On 14/12/2023 11:37 a.m., Martin Morgan wrote: In the spirit of 'advent of code', maybe it is better to exploit the features of the particular language you've chosen? Then the use of factors seems very relevant. value_levels <- c("Small", "Medium", "Large") df <- data.frame( person = c("Alice", "Bob", "Bob", "Charlie"), value = factor( c("Medium", "Large", "Small", "Large"), levels = value_levels ) ) df[with(df, order(person, value)),] Likely this is more efficient than the hints of your existing solution, because it will act on vectors rather than iterating through individual elements of the 'person' and 'value' vectors. For a more general solution, I don't think I'd follow the low-level approach Duncan suggests (maybe see also ?Math for S3 generics), but rather define a class (e.g., that requires vectors person and value) and implement a corresponding `xtfrm()` method. I'd agree, in cases where it's feasible to implement one. But there are cases where the pairwise comparison is obvious, while the numeric conversion isn't. A simple one would be a list of string vectors of different lengths, where you want to sort lexicographically. Duncan Have fun with the remainder of the advent! Another Martin From: R-help on behalf of Martin Møller Skarbiniks Pedersen Date: Thursday, December 14, 2023 at 6:42 AM To: R mailing list Subject: Re: [R] Sorting based a custom sorting function On Thu, 14 Dec 2023 at 12:02, Duncan Murdoch wrote: 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. Great! Just what I need. I will create a class and overwrite > and ==. I didn't know that order() used these exact methods. My best solution was something like this: quicksort <- function(arr, compare_func) { if (length(arr) <= 1) { return(arr) } else { pivot <- arr[[1]] less <- arr[-1][compare_func(arr[-1], pivot) <= 0] greater <- arr[-1][compare_func(arr[-1], pivot) > 0] return(c(quicksort(less, compare_func), pivot, quicksort(greater, compare_func))) } } persons <- c("alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliett", "kilo", "lima", "mike", "november", "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform", "victor", "whiskey", "x-ray", "yankee", "zulu") quicksort(persons, function(left, right) { nchar(left) - nchar(right) }) Regards Martin __ 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. [[alternative HTML version deleted]] __ 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. __ 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.
Re: [R] Sorting based a custom sorting function
In the spirit of 'advent of code', maybe it is better to exploit the features of the particular language you've chosen? Then the use of factors seems very relevant. value_levels <- c("Small", "Medium", "Large") df <- data.frame( person = c("Alice", "Bob", "Bob", "Charlie"), value = factor( c("Medium", "Large", "Small", "Large"), levels = value_levels ) ) df[with(df, order(person, value)),] Likely this is more efficient than the hints of your existing solution, because it will act on vectors rather than iterating through individual elements of the 'person' and 'value' vectors. For a more general solution, I don't think I'd follow the low-level approach Duncan suggests (maybe see also ?Math for S3 generics), but rather define a class (e.g., that requires vectors person and value) and implement a corresponding `xtfrm()` method. Have fun with the remainder of the advent! Another Martin From: R-help on behalf of Martin Møller Skarbiniks Pedersen Date: Thursday, December 14, 2023 at 6:42 AM To: R mailing list Subject: Re: [R] Sorting based a custom sorting function On Thu, 14 Dec 2023 at 12:02, Duncan Murdoch wrote: > > 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. Great! Just what I need. I will create a class and overwrite > and ==. I didn't know that order() used these exact methods. My best solution was something like this: quicksort <- function(arr, compare_func) { if (length(arr) <= 1) { return(arr) } else { pivot <- arr[[1]] less <- arr[-1][compare_func(arr[-1], pivot) <= 0] greater <- arr[-1][compare_func(arr[-1], pivot) > 0] return(c(quicksort(less, compare_func), pivot, quicksort(greater, compare_func))) } } persons <- c("alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliett", "kilo", "lima", "mike", "november", "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform", "victor", "whiskey", "x-ray", "yankee", "zulu") quicksort(persons, function(left, right) { nchar(left) - nchar(right) }) Regards Martin __ 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. [[alternative HTML version deleted]] __ 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.
[R] Suggestion for list - change reply-to
Hi, I suggest that reply-to is changed to r-help@r-project.org and not the original sender. The reason for my suggestion: I just made a mistake when replying to a message. I forgot to change the reply address from the sender to the r-help and I think that happens quite often for others also. Any reason to keep it to the original sender? Regards Martin __ 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.
Re: [R] Sorting based a custom sorting function
On Thu, 14 Dec 2023 at 12:02, Duncan Murdoch wrote: > > 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. Great! Just what I need. I will create a class and overwrite > and ==. I didn't know that order() used these exact methods. My best solution was something like this: quicksort <- function(arr, compare_func) { if (length(arr) <= 1) { return(arr) } else { pivot <- arr[[1]] less <- arr[-1][compare_func(arr[-1], pivot) <= 0] greater <- arr[-1][compare_func(arr[-1], pivot) > 0] return(c(quicksort(less, compare_func), pivot, quicksort(greater, compare_func))) } } persons <- c("alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliett", "kilo", "lima", "mike", "november", "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform", "victor", "whiskey", "x-ray", "yankee", "zulu") quicksort(persons, function(left, right) { nchar(left) - nchar(right) }) Regards Martin __ 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.
Re: [R] Sorting based a custom sorting function
> This sounds suspiciously like homework (which is off-topic... see the Posting > Guide) It is not homework. Currently I am trying to solve this: https://adventofcode.com/2023/day/7 But it is something that has puzzled me for a long time. In many programming languages, you can give a "less" function to the sorting function. The "less" function normally takes two arguments and tells which is greater. The sorting function then uses that. Eg. in perl: @products = sort { $a->{price} <=> $b->{price} || $b->{discount} <=> $a->{discount} } @products; > and you haven't indicated how you plan to encode your poker hands > If this is not homework, then please show your work so far instead of showing > a completely different example. I believe a MRE is better than a lot of code with many details that are not related to the precise problem. See https://stackoverflow.com/help/minimal-reproducible-example My encoding of poker hands doesn't matter for the general problem of providing a custom sorting function to any of the many sorting functions in R. > 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. I understand R quite well and implemented my own quicksort but I was wondering for a better solution. Here is my current solution. quicksort <- function(arr, compare_func) { if (length(arr) <= 1) { return(arr) } else { pivot <- arr[1] less <- arr[-1][compare_func(arr[-1], pivot) <= 0] greater <- arr[-1][compare_func(arr[-1], pivot) > 0] return(c(quicksort(less, compare_func), pivot, quicksort(greater, compare_func))) } } Regards Martin Martin __ 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.
Re: [R] Sorting based a custom sorting function
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.
Re: [R] Sorting based a custom sorting function
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" 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@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. __ 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.
[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 __ 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.